From 414177aa0cab59a504200304591c5f8f560198e8 Mon Sep 17 00:00:00 2001 From: Brad Zacher Date: Thu, 27 Apr 2023 10:30:22 +0930 Subject: [PATCH 1/3] feat: fork json schema types for better compat with ESLint rule validation --- docs/architecture/Utils.mdx | 22 +- packages/eslint-plugin/package.json | 1 - packages/utils/package.json | 1 - packages/utils/src/json-schema.ts | 277 ++++++++++++++++++++++-- patches/@types+json-schema+7.0.11.patch | 35 --- yarn.lock | 9 +- 6 files changed, 271 insertions(+), 74 deletions(-) delete mode 100644 patches/@types+json-schema+7.0.11.patch diff --git a/docs/architecture/Utils.mdx b/docs/architecture/Utils.mdx index 7c4fd674d707..4b307f4db42d 100644 --- a/docs/architecture/Utils.mdx +++ b/docs/architecture/Utils.mdx @@ -15,14 +15,14 @@ Any custom rules you write generally will be as well. ## Exports -| Name | Description | -| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `AST_NODE_TYPES` | An enum with the names of every single _node_ found in `TSESTree`. | -| `AST_TOKEN_TYPES` | An enum with the names of every single _token_ found in `TSESTree`. | -| `ASTUtils` | Tools for operating on the ESTree AST. Also includes the [`@eslint-community/eslint-utils`](https://www.npmjs.com/package/@eslint-community/eslint-utils) package, correctly typed to work with the types found in `TSESTree` | -| `ESLintUtils` | Tools for creating ESLint rules with TypeScript. | -| `JSONSchema` | Types from the [`@types/json-schema`](https://www.npmjs.com/package/@types/json-schema) package, re-exported to save you having to manually import them. Also ensures you're using the same version of the types as this package. | -| `ParserServices` | Typing for the parser services provided when parsing a file using `@typescript-eslint/typescript-estree`. | -| `TSESLint` | Types for ESLint, correctly typed to work with the types found in `TSESTree`. | -| `TSESLintScope` | The [`eslint-scope`](https://www.npmjs.com/package/eslint-scope) package, correctly typed to work with the types found in both `TSESTree` and `TSESLint` | -| `TSESTree` | Types for the TypeScript flavor of ESTree created by `@typescript-eslint/typescript-estree`. | +| Name | Description | +| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `AST_NODE_TYPES` | An enum with the names of every single _node_ found in `TSESTree`. | +| `AST_TOKEN_TYPES` | An enum with the names of every single _token_ found in `TSESTree`. | +| `ASTUtils` | Tools for operating on the ESTree AST. Also includes the [`@eslint-community/eslint-utils`](https://www.npmjs.com/package/@eslint-community/eslint-utils) package, correctly typed to work with the types found in `TSESTree` | +| `ESLintUtils` | Tools for creating ESLint rules with TypeScript. | +| `JSONSchema` | Strict types for the JSON Schema v4 spec - the version that ESLint uses to validate all rules with. | +| `ParserServices` | Typing for the parser services provided when parsing a file using `@typescript-eslint/typescript-estree`. | +| `TSESLint` | Types for ESLint, correctly typed to work with the types found in `TSESTree`. | +| `TSESLintScope` | The [`eslint-scope`](https://www.npmjs.com/package/eslint-scope) package, correctly typed to work with the types found in both `TSESTree` and `TSESLint` | +| `TSESTree` | Types for the TypeScript flavor of ESTree created by `@typescript-eslint/typescript-estree`. | diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 6e99af1df7d1..2a54901d8220 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -67,7 +67,6 @@ }, "devDependencies": { "@types/debug": "*", - "@types/json-schema": "*", "@types/marked": "*", "@types/natural-compare": "*", "@types/prettier": "*", diff --git a/packages/utils/package.json b/packages/utils/package.json index a852cc6e0261..ea271b5d04f2 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -66,7 +66,6 @@ }, "dependencies": { "@eslint-community/eslint-utils": "^4.3.0", - "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", "@typescript-eslint/scope-manager": "5.59.1", "@typescript-eslint/types": "5.59.1", diff --git a/packages/utils/src/json-schema.ts b/packages/utils/src/json-schema.ts index 8e11b8b3caa2..a38e71bb2be5 100644 --- a/packages/utils/src/json-schema.ts +++ b/packages/utils/src/json-schema.ts @@ -1,24 +1,253 @@ -// Note - @types/json-schema@7.0.4 added some function declarations to the type package -// If we do export *, then it will also export these function declarations. -// This will cause typescript to not scrub the require from the build, breaking anyone who doesn't have it as a dependency - -// eslint-disable-next-line import/no-extraneous-dependencies -export { - JSONSchema4, - JSONSchema4Type, - JSONSchema4TypeName, - JSONSchema4Version, - JSONSchema6, - JSONSchema6Definition, - JSONSchema6Type, - JSONSchema6TypeName, - JSONSchema6Version, - JSONSchema7, - JSONSchema7Array, - JSONSchema7Definition, - JSONSchema7Type, - JSONSchema7TypeName, - JSONSchema7Version, - ValidationError, - ValidationResult, -} from 'json-schema'; +/** + * This is a fork of https://github.com/DefinitelyTyped/DefinitelyTyped/blob/13f63c2eb8d7479caf01ab8d72f9e3683368a8f5/types/json-schema/index.d.ts + * We intentionally fork this because: + * - ESLint ***ONLY*** supports JSONSchema v4 + * - We want to provide stricter types + */ + +//================================================================================================== +// JSON Schema Draft 04 +//================================================================================================== + +/** + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.1 + */ +export type JSONSchema4TypeName = + | 'string' // + | 'number' + | 'integer' + | 'boolean' + | 'object' + | 'array' + | 'null' + | 'any'; + +/** + * @see https://tools.ietf.org/html/draft-zyp-json-schema-04#section-3.5 + */ +export type JSONSchema4Type = + | string // + | number + | boolean + | JSONSchema4Object + | JSONSchema4Array + | null; + +// Workaround for infinite type recursion +export interface JSONSchema4Object { + [key: string]: JSONSchema4Type; +} + +// Workaround for infinite type recursion +// https://github.com/Microsoft/TypeScript/issues/3496#issuecomment-128553540 +export interface JSONSchema4Array extends Array {} + +/** + * Meta schema + * + * Recommended values: + * - 'http://json-schema.org/schema#' + * - 'http://json-schema.org/hyper-schema#' + * - 'http://json-schema.org/draft-04/schema#' + * - 'http://json-schema.org/draft-04/hyper-schema#' + * - 'http://json-schema.org/draft-03/schema#' + * - 'http://json-schema.org/draft-03/hyper-schema#' + * + * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-5 + */ +export type JSONSchema4Version = string; + +/** + * JSON Schema V4 + * @see https://tools.ietf.org/html/draft-zyp-json-schema-04 + */ +export interface JSONSchema4 { + id?: string | undefined; + $ref?: string | undefined; + $schema?: JSONSchema4Version | undefined; + + /** + * This attribute is a string that provides a short description of the + * instance property. + * + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.21 + */ + title?: string | undefined; + + /** + * This attribute is a string that provides a full description of the of + * purpose the instance property. + * + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.22 + */ + description?: string | undefined; + + default?: JSONSchema4Type | undefined; + multipleOf?: number | undefined; + maximum?: number | undefined; + exclusiveMaximum?: boolean | undefined; + minimum?: number | undefined; + exclusiveMinimum?: boolean | undefined; + maxLength?: number | undefined; + minLength?: number | undefined; + pattern?: string | undefined; + + /** + * May only be defined when "items" is defined, and is a tuple of JSONSchemas. + * + * This provides a definition for additional items in an array instance + * when tuple definitions of the items is provided. This can be false + * to indicate additional items in the array are not allowed, or it can + * be a schema that defines the schema of the additional items. + * + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.6 + */ + additionalItems?: boolean | JSONSchema4 | undefined; + + /** + * This attribute defines the allowed items in an instance array, and + * MUST be a schema or an array of schemas. The default value is an + * empty schema which allows any value for items in the instance array. + * + * When this attribute value is a schema and the instance value is an + * array, then all the items in the array MUST be valid according to the + * schema. + * + * When this attribute value is an array of schemas and the instance + * value is an array, each position in the instance array MUST conform + * to the schema in the corresponding position for this array. This + * called tuple typing. When tuple typing is used, additional items are + * allowed, disallowed, or constrained by the "additionalItems" + * (Section 5.6) attribute using the same rules as + * "additionalProperties" (Section 5.4) for objects. + * + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.5 + */ + items?: JSONSchema4 | JSONSchema4[] | undefined; + + maxItems?: number | undefined; + minItems?: number | undefined; + uniqueItems?: boolean | undefined; + maxProperties?: number | undefined; + minProperties?: number | undefined; + + /** + * This attribute indicates if the instance must have a value, and not + * be undefined. This is false by default, making the instance + * optional. + * + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.7 + */ + required?: boolean | string[] | undefined; + + /** + * This attribute defines a schema for all properties that are not + * explicitly defined in an object type definition. If specified, the + * value MUST be a schema or a boolean. If false is provided, no + * additional properties are allowed beyond the properties defined in + * the schema. The default value is an empty schema which allows any + * value for additional properties. + * + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.4 + */ + additionalProperties?: boolean | JSONSchema4 | undefined; + + /** + * Reusable definitions that can be referenced via `$ref` + */ + definitions?: + | { + [k: string]: JSONSchema4; + } + | undefined; + /** + * Reusable definitions that can be referenced via `$ref` + */ + $defs?: + | { + [k: string]: JSONSchema4; + } + | undefined; + + /** + * This attribute is an object with property definitions that define the + * valid values of instance object property values. When the instance + * value is an object, the property values of the instance object MUST + * conform to the property definitions in this object. In this object, + * each property definition's value MUST be a schema, and the property's + * name MUST be the name of the instance property that it defines. The + * instance property value MUST be valid according to the schema from + * the property definition. Properties are considered unordered, the + * order of the instance properties MAY be in any order. + * + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.2 + */ + properties?: + | { + [k: string]: JSONSchema4; + } + | undefined; + + /** + * This attribute is an object that defines the schema for a set of + * property names of an object instance. The name of each property of + * this attribute's object is a regular expression pattern in the ECMA + * 262/Perl 5 format, while the value is a schema. If the pattern + * matches the name of a property on the instance object, the value of + * the instance's property MUST be valid against the pattern name's + * schema value. + * + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.3 + */ + patternProperties?: + | { + [k: string]: JSONSchema4; + } + | undefined; + dependencies?: + | { + [k: string]: JSONSchema4 | string[]; + } + | undefined; + + /** + * This provides an enumeration of all possible values that are valid + * for the instance property. This MUST be an array, and each item in + * the array represents a possible value for the instance value. If + * this attribute is defined, the instance value MUST be one of the + * values in the array in order for the schema to be valid. + * + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19 + */ + enum?: JSONSchema4Type[] | undefined; + + /** + * A single type, or a union of simple types + */ + type?: JSONSchema4TypeName | JSONSchema4TypeName[] | undefined; + + allOf?: JSONSchema4[] | undefined; + anyOf?: JSONSchema4[] | undefined; + oneOf?: JSONSchema4[] | undefined; + not?: JSONSchema4 | undefined; + + /** + * The value of this property MUST be another schema which will provide + * a base schema which the current schema will inherit from. The + * inheritance rules are such that any instance that is valid according + * to the current schema MUST be valid according to the referenced + * schema. This MAY also be an array, in which case, the instance MUST + * be valid for all the schemas in the array. A schema that extends + * another schema MAY define additional attributes, constrain existing + * attributes, or add other constraints. + * + * Conceptually, the behavior of extends can be seen as validating an + * instance against all constraints in the extending schema as well as + * the extended schema(s). + * + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.26 + */ + extends?: string | string[] | undefined; + + format?: string | undefined; +} diff --git a/patches/@types+json-schema+7.0.11.patch b/patches/@types+json-schema+7.0.11.patch deleted file mode 100644 index 33f3206e1acb..000000000000 --- a/patches/@types+json-schema+7.0.11.patch +++ /dev/null @@ -1,35 +0,0 @@ -diff --git a/node_modules/@types/json-schema/index.d.ts b/node_modules/@types/json-schema/index.d.ts -index 7a92dec..44d9691 100755 ---- a/node_modules/@types/json-schema/index.d.ts -+++ b/node_modules/@types/json-schema/index.d.ts -@@ -154,9 +154,18 @@ export interface JSONSchema4 { - */ - additionalProperties?: boolean | JSONSchema4 | undefined; - -+ /** -+ * Reusable definitions that can be referenced via `$ref` -+ */ - definitions?: { - [k: string]: JSONSchema4; - } | undefined; -+ /** -+ * Reusable definitions that can be referenced via `$ref` -+ */ -+ $defs?: { -+ [k: string]: JSONSchema4; -+ } | undefined; - - /** - * This attribute is an object with property definitions that define the -@@ -232,11 +241,6 @@ export interface JSONSchema4 { - */ - extends?: string | string[] | undefined; - -- /** -- * @see https://tools.ietf.org/html/draft-zyp-json-schema-04#section-5.6 -- */ -- [k: string]: any; -- - format?: string | undefined; - } - diff --git a/yarn.lock b/yarn.lock index 8b3c889b137f..18b0020f9895 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2202,6 +2202,11 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.36.0.tgz#9837f768c03a1e4a30bd304a64fb8844f0e72efe" integrity sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg== +"@eslint/js@8.38.0": + version "8.38.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.38.0.tgz#73a8a0d8aa8a8e6fe270431c5e72ae91b5337892" + integrity sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g== + "@eslint/js@8.39.0": version "8.39.0" resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.39.0.tgz#58b536bcc843f4cd1e02a7e6171da5c040f4d44b" @@ -3813,7 +3818,7 @@ expect "^29.0.0" pretty-format "^29.0.0" -"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": +"@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== @@ -6907,7 +6912,7 @@ eslint-scope@5.1.1, eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-scope@^7.2.0: +eslint-scope@^7.1.1, eslint-scope@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b" integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw== From 24a27af1a9179ceda3cd389ee6dd980a67bbaf5c Mon Sep 17 00:00:00 2001 From: Brad Zacher Date: Fri, 28 Apr 2023 10:28:00 +0930 Subject: [PATCH 2/3] make the schema types a discriminated union --- .../eslint-plugin/src/rules/array-type.ts | 1 + .../eslint-plugin/src/rules/ban-ts-comment.ts | 1 + packages/eslint-plugin/src/rules/ban-types.ts | 2 + .../src/rules/class-literal-property-style.ts | 7 +- .../eslint-plugin/src/rules/comma-dangle.ts | 4 +- .../rules/consistent-generic-constructors.ts | 1 + .../rules/consistent-indexed-object-style.ts | 1 + .../src/rules/consistent-type-assertions.ts | 3 + .../src/rules/consistent-type-definitions.ts | 1 + .../src/rules/consistent-type-imports.ts | 2 + .../rules/explicit-member-accessibility.ts | 3 + .../src/rules/func-call-spacing.ts | 2 + .../src/rules/keyword-spacing.ts | 3 +- .../src/rules/member-delimiter-style.ts | 11 +- .../src/rules/member-ordering.ts | 2 +- .../src/rules/method-signature-style.ts | 1 + .../src/rules/no-empty-function.ts | 4 +- .../src/rules/no-invalid-void-type.ts | 2 +- .../src/rules/no-magic-numbers.ts | 3 +- packages/eslint-plugin/src/rules/no-shadow.ts | 1 + .../eslint-plugin/src/rules/no-type-alias.ts | 2 + .../eslint-plugin/src/rules/no-unused-vars.ts | 4 + .../src/rules/no-use-before-define.ts | 1 + .../rules/padding-line-between-statements.ts | 11 +- .../src/rules/parameter-properties.ts | 2 + .../eslint-plugin/src/rules/return-await.ts | 1 + .../src/rules/space-before-function-paren.ts | 4 + .../src/rules/triple-slash-reference.ts | 3 + .../tests/schema-snapshots/array-type.shot | 3 +- .../schema-snapshots/ban-ts-comment.shot | 3 +- .../tests/schema-snapshots/ban-types.shot | 6 +- .../class-literal-property-style.shot | 3 +- .../tests/schema-snapshots/comma-dangle.shot | 8 +- .../consistent-generic-constructors.shot | 3 +- .../consistent-indexed-object-style.shot | 3 +- .../consistent-type-assertions.shot | 9 +- .../consistent-type-definitions.shot | 3 +- .../consistent-type-imports.shot | 6 +- .../explicit-member-accessibility.shot | 9 +- .../schema-snapshots/func-call-spacing.shot | 6 +- .../member-delimiter-style.shot | 9 +- .../method-signature-style.shot | 3 +- .../schema-snapshots/no-empty-function.shot | 3 +- .../no-invalid-void-type.shot | 4 +- .../tests/schema-snapshots/no-shadow.shot | 3 +- .../tests/schema-snapshots/no-type-alias.shot | 6 +- .../schema-snapshots/no-unused-vars.shot | 12 +- .../no-use-before-define.shot | 3 +- .../padding-line-between-statements.shot | 9 +- .../parameter-properties.shot | 6 +- .../tests/schema-snapshots/return-await.shot | 3 +- .../space-before-function-paren.shot | 12 +- .../triple-slash-reference.shot | 9 +- packages/eslint-plugin/tests/schemas.test.ts | 10 +- .../src/generateArrayType.ts | 7 +- .../src/generateObjectType.ts | 4 +- .../src/generateType.ts | 18 +- .../src/index.ts | 2 +- .../rule-tester/src/utils/config-schema.ts | 6 +- packages/rule-tester/tests/RuleTester.test.ts | 2 +- packages/utils/src/json-schema.ts | 478 +++++++----------- .../rule-tester/RuleTester.test.ts | 2 +- .../website/src/components/lib/jsonSchema.ts | 37 +- 63 files changed, 401 insertions(+), 392 deletions(-) diff --git a/packages/eslint-plugin/src/rules/array-type.ts b/packages/eslint-plugin/src/rules/array-type.ts index 1e3b978a2813..08ff550a1418 100644 --- a/packages/eslint-plugin/src/rules/array-type.ts +++ b/packages/eslint-plugin/src/rules/array-type.ts @@ -109,6 +109,7 @@ export default util.createRule({ { $defs: { arrayOption: { + type: 'string', enum: ['array', 'generic', 'array-simple'], }, }, diff --git a/packages/eslint-plugin/src/rules/ban-ts-comment.ts b/packages/eslint-plugin/src/rules/ban-ts-comment.ts index f3622c693ac9..3f9c60bdb8db 100644 --- a/packages/eslint-plugin/src/rules/ban-ts-comment.ts +++ b/packages/eslint-plugin/src/rules/ban-ts-comment.ts @@ -49,6 +49,7 @@ export default util.createRule<[Options], MessageIds>({ default: true, }, { + type: 'string', enum: ['allow-with-description'], }, { diff --git a/packages/eslint-plugin/src/rules/ban-types.ts b/packages/eslint-plugin/src/rules/ban-types.ts index 688164c5f6c6..b2912dc83023 100644 --- a/packages/eslint-plugin/src/rules/ban-types.ts +++ b/packages/eslint-plugin/src/rules/ban-types.ts @@ -148,11 +148,13 @@ export default util.createRule({ description: 'Bans the type with the default message', }, { + type: 'boolean', enum: [false], description: 'Un-bans the type (useful when paired with `extendDefaults`)', }, { + type: 'boolean', enum: [true], description: 'Bans the type with the default message', }, diff --git a/packages/eslint-plugin/src/rules/class-literal-property-style.ts b/packages/eslint-plugin/src/rules/class-literal-property-style.ts index 7e4d6b2d6b1c..7563c6b97fc0 100644 --- a/packages/eslint-plugin/src/rules/class-literal-property-style.ts +++ b/packages/eslint-plugin/src/rules/class-literal-property-style.ts @@ -50,7 +50,12 @@ export default util.createRule({ preferFieldStyle: 'Literals should be exposed using readonly fields.', preferGetterStyle: 'Literals should be exposed using getters.', }, - schema: [{ enum: ['fields', 'getters'] }], + schema: [ + { + type: 'string', + enum: ['fields', 'getters'], + }, + ], }, defaultOptions: ['fields'], create(context, [style]) { diff --git a/packages/eslint-plugin/src/rules/comma-dangle.ts b/packages/eslint-plugin/src/rules/comma-dangle.ts index 119907db762f..029e9e3e6517 100644 --- a/packages/eslint-plugin/src/rules/comma-dangle.ts +++ b/packages/eslint-plugin/src/rules/comma-dangle.ts @@ -49,9 +49,11 @@ export default util.createRule({ schema: { $defs: { value: { + type: 'string', enum: OPTION_VALUE_SCHEME, }, valueWithIgnore: { + type: 'string', enum: [...OPTION_VALUE_SCHEME, 'ignore'], }, }, @@ -79,7 +81,7 @@ export default util.createRule({ ], }, ], - additionalProperties: false, + additionalItems: false, }, fixable: 'code', hasSuggestions: baseRule.meta.hasSuggestions, diff --git a/packages/eslint-plugin/src/rules/consistent-generic-constructors.ts b/packages/eslint-plugin/src/rules/consistent-generic-constructors.ts index ed842628d9eb..e437bc38d761 100644 --- a/packages/eslint-plugin/src/rules/consistent-generic-constructors.ts +++ b/packages/eslint-plugin/src/rules/consistent-generic-constructors.ts @@ -24,6 +24,7 @@ export default createRule({ fixable: 'code', schema: [ { + type: 'string', enum: ['type-annotation', 'constructor'], }, ], diff --git a/packages/eslint-plugin/src/rules/consistent-indexed-object-style.ts b/packages/eslint-plugin/src/rules/consistent-indexed-object-style.ts index d8ae71bec1d4..268946ae463b 100644 --- a/packages/eslint-plugin/src/rules/consistent-indexed-object-style.ts +++ b/packages/eslint-plugin/src/rules/consistent-indexed-object-style.ts @@ -21,6 +21,7 @@ export default createRule({ fixable: 'code', schema: [ { + type: 'string', enum: ['record', 'index-signature'], }, ], diff --git a/packages/eslint-plugin/src/rules/consistent-type-assertions.ts b/packages/eslint-plugin/src/rules/consistent-type-assertions.ts index 942bc8f3de58..47908e44c26a 100644 --- a/packages/eslint-plugin/src/rules/consistent-type-assertions.ts +++ b/packages/eslint-plugin/src/rules/consistent-type-assertions.ts @@ -48,6 +48,7 @@ export default util.createRule({ type: 'object', properties: { assertionStyle: { + type: 'string', enum: ['never'], }, }, @@ -58,9 +59,11 @@ export default util.createRule({ type: 'object', properties: { assertionStyle: { + type: 'string', enum: ['as', 'angle-bracket'], }, objectLiteralTypeAssertions: { + type: 'string', enum: ['allow', 'allow-as-parameter', 'never'], }, }, diff --git a/packages/eslint-plugin/src/rules/consistent-type-definitions.ts b/packages/eslint-plugin/src/rules/consistent-type-definitions.ts index a28f07529b5c..b504081ee4a1 100644 --- a/packages/eslint-plugin/src/rules/consistent-type-definitions.ts +++ b/packages/eslint-plugin/src/rules/consistent-type-definitions.ts @@ -18,6 +18,7 @@ export default util.createRule({ }, schema: [ { + type: 'string', enum: ['interface', 'type'], }, ], diff --git a/packages/eslint-plugin/src/rules/consistent-type-imports.ts b/packages/eslint-plugin/src/rules/consistent-type-imports.ts index 3b9de8bad835..701c53b25416 100644 --- a/packages/eslint-plugin/src/rules/consistent-type-imports.ts +++ b/packages/eslint-plugin/src/rules/consistent-type-imports.ts @@ -65,12 +65,14 @@ export default util.createRule({ type: 'object', properties: { prefer: { + type: 'string', enum: ['type-imports', 'no-type-imports'], }, disallowTypeAnnotations: { type: 'boolean', }, fixStyle: { + type: 'string', enum: ['separate-type-imports', 'inline-type-imports'], }, }, diff --git a/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts b/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts index 71a85b4e701b..9670659c975c 100644 --- a/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts +++ b/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts @@ -51,14 +51,17 @@ export default util.createRule({ accessibilityLevel: { oneOf: [ { + type: 'string', enum: ['explicit'], description: 'Always require an accessor.', }, { + type: 'string', enum: ['no-public'], description: 'Require an accessor except when public.', }, { + type: 'string', enum: ['off'], description: 'Never check whether there is an accessor.', }, diff --git a/packages/eslint-plugin/src/rules/func-call-spacing.ts b/packages/eslint-plugin/src/rules/func-call-spacing.ts index cbb2bba5939c..fd0b50a65fd0 100644 --- a/packages/eslint-plugin/src/rules/func-call-spacing.ts +++ b/packages/eslint-plugin/src/rules/func-call-spacing.ts @@ -29,6 +29,7 @@ export default util.createRule({ type: 'array', items: [ { + type: 'string', enum: ['never'], }, ], @@ -39,6 +40,7 @@ export default util.createRule({ type: 'array', items: [ { + type: 'string', enum: ['always'], }, { diff --git a/packages/eslint-plugin/src/rules/keyword-spacing.ts b/packages/eslint-plugin/src/rules/keyword-spacing.ts index 0ec1d17ec388..893c70db7674 100644 --- a/packages/eslint-plugin/src/rules/keyword-spacing.ts +++ b/packages/eslint-plugin/src/rules/keyword-spacing.ts @@ -1,5 +1,6 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; +import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema'; import * as util from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; @@ -26,7 +27,7 @@ const schema = util.deepMerge( }, }, }, -); +) as unknown as JSONSchema4; export default util.createRule({ name: 'keyword-spacing', diff --git a/packages/eslint-plugin/src/rules/member-delimiter-style.ts b/packages/eslint-plugin/src/rules/member-delimiter-style.ts index fb14ad32910c..ac2d9e1aea42 100644 --- a/packages/eslint-plugin/src/rules/member-delimiter-style.ts +++ b/packages/eslint-plugin/src/rules/member-delimiter-style.ts @@ -150,9 +150,15 @@ export default util.createRule({ schema: [ { $defs: { - multiLineOption: { enum: ['none', 'semi', 'comma'] }, + multiLineOption: { + type: 'string', + enum: ['none', 'semi', 'comma'], + }, // note can't have "none" for single line delimiter as it's invalid syntax - singleLineOption: { enum: ['semi', 'comma'] }, + singleLineOption: { + type: 'string', + enum: ['semi', 'comma'], + }, // note - need to define this last as it references the enums delimiterConfig: BASE_SCHEMA, }, @@ -172,6 +178,7 @@ export default util.createRule({ additionalProperties: false, }, multilineDetection: { + type: 'string', enum: ['brackets', 'last-member'], }, }, diff --git a/packages/eslint-plugin/src/rules/member-ordering.ts b/packages/eslint-plugin/src/rules/member-ordering.ts index 97a5bd24c8d7..ee2093a19ede 100644 --- a/packages/eslint-plugin/src/rules/member-ordering.ts +++ b/packages/eslint-plugin/src/rules/member-ordering.ts @@ -644,7 +644,7 @@ export default util.createRule({ }, allItems: { type: 'string', - enum: allMemberTypes, + enum: allMemberTypes as string[], }, typeItems: { type: 'string', diff --git a/packages/eslint-plugin/src/rules/method-signature-style.ts b/packages/eslint-plugin/src/rules/method-signature-style.ts index 3cc8773159cc..e9db86cd6870 100644 --- a/packages/eslint-plugin/src/rules/method-signature-style.ts +++ b/packages/eslint-plugin/src/rules/method-signature-style.ts @@ -22,6 +22,7 @@ export default util.createRule({ }, schema: [ { + type: 'string', enum: ['property', 'method'], }, ], diff --git a/packages/eslint-plugin/src/rules/no-empty-function.ts b/packages/eslint-plugin/src/rules/no-empty-function.ts index b908b6c6d889..8113ee6ce553 100644 --- a/packages/eslint-plugin/src/rules/no-empty-function.ts +++ b/packages/eslint-plugin/src/rules/no-empty-function.ts @@ -1,5 +1,6 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; +import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema'; import * as util from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; @@ -18,6 +19,7 @@ const schema = util.deepMerge( properties: { allow: { items: { + type: 'string', enum: [ 'functions', 'arrowFunctions', @@ -38,7 +40,7 @@ const schema = util.deepMerge( }, }, }, -); +) as unknown as JSONSchema4; export default util.createRule({ name: 'no-empty-function', diff --git a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts index e367c3928be6..38872f499ca0 100644 --- a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts +++ b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts @@ -47,7 +47,7 @@ export default util.createRule<[Options], MessageIds>({ { type: 'array', items: { type: 'string' }, - minLength: 1, + minItems: 1, }, ], }, diff --git a/packages/eslint-plugin/src/rules/no-magic-numbers.ts b/packages/eslint-plugin/src/rules/no-magic-numbers.ts index 18ae31abea0c..92a03c9078d4 100644 --- a/packages/eslint-plugin/src/rules/no-magic-numbers.ts +++ b/packages/eslint-plugin/src/rules/no-magic-numbers.ts @@ -1,5 +1,6 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; +import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema'; import * as util from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; @@ -31,7 +32,7 @@ const schema = util.deepMerge( }, }, }, -); +) as unknown as JSONSchema4; export default util.createRule({ name: 'no-magic-numbers', diff --git a/packages/eslint-plugin/src/rules/no-shadow.ts b/packages/eslint-plugin/src/rules/no-shadow.ts index 991beb9f1eb7..f40ea991dbaf 100644 --- a/packages/eslint-plugin/src/rules/no-shadow.ts +++ b/packages/eslint-plugin/src/rules/no-shadow.ts @@ -43,6 +43,7 @@ export default util.createRule({ type: 'boolean', }, hoist: { + type: 'string', enum: ['all', 'functions', 'never'], }, allow: { diff --git a/packages/eslint-plugin/src/rules/no-type-alias.ts b/packages/eslint-plugin/src/rules/no-type-alias.ts index 7356f00fbc59..cc41d65f78e8 100644 --- a/packages/eslint-plugin/src/rules/no-type-alias.ts +++ b/packages/eslint-plugin/src/rules/no-type-alias.ts @@ -50,6 +50,7 @@ export default util.createRule({ { $defs: { expandedOptions: { + type: 'string', enum: [ 'always', 'never', @@ -59,6 +60,7 @@ export default util.createRule({ ] satisfies Values[], }, simpleOptions: { + type: 'string', enum: ['always', 'never'], }, }, diff --git a/packages/eslint-plugin/src/rules/no-unused-vars.ts b/packages/eslint-plugin/src/rules/no-unused-vars.ts index edb07bce0ccb..a847294a52d7 100644 --- a/packages/eslint-plugin/src/rules/no-unused-vars.ts +++ b/packages/eslint-plugin/src/rules/no-unused-vars.ts @@ -44,18 +44,21 @@ export default util.createRule({ { oneOf: [ { + type: 'string', enum: ['all', 'local'], }, { type: 'object', properties: { vars: { + type: 'string', enum: ['all', 'local'], }, varsIgnorePattern: { type: 'string', }, args: { + type: 'string', enum: ['all', 'after-used', 'none'], }, ignoreRestSiblings: { @@ -65,6 +68,7 @@ export default util.createRule({ type: 'string', }, caughtErrors: { + type: 'string', enum: ['all', 'none'], }, caughtErrorsIgnorePattern: { diff --git a/packages/eslint-plugin/src/rules/no-use-before-define.ts b/packages/eslint-plugin/src/rules/no-use-before-define.ts index eccbb320db33..8cca3042691e 100644 --- a/packages/eslint-plugin/src/rules/no-use-before-define.ts +++ b/packages/eslint-plugin/src/rules/no-use-before-define.ts @@ -251,6 +251,7 @@ export default util.createRule({ { oneOf: [ { + type: 'string', enum: ['nofunc'], }, { diff --git a/packages/eslint-plugin/src/rules/padding-line-between-statements.ts b/packages/eslint-plugin/src/rules/padding-line-between-statements.ts index b1e974e1b863..deeeafadad5a 100644 --- a/packages/eslint-plugin/src/rules/padding-line-between-statements.ts +++ b/packages/eslint-plugin/src/rules/padding-line-between-statements.ts @@ -598,14 +598,21 @@ export default util.createRule({ schema: { $defs: { paddingType: { + type: 'string', enum: Object.keys(PaddingTypes), }, statementType: { anyOf: [ - { enum: Object.keys(StatementTypes) }, + { + type: 'string', + enum: Object.keys(StatementTypes), + }, { type: 'array', - items: { enum: Object.keys(StatementTypes) }, + items: { + type: 'string', + enum: Object.keys(StatementTypes), + }, minItems: 1, uniqueItems: true, additionalItems: false, diff --git a/packages/eslint-plugin/src/rules/parameter-properties.ts b/packages/eslint-plugin/src/rules/parameter-properties.ts index 10c15b061779..f70bdb8b81b1 100644 --- a/packages/eslint-plugin/src/rules/parameter-properties.ts +++ b/packages/eslint-plugin/src/rules/parameter-properties.ts @@ -41,6 +41,7 @@ export default util.createRule({ { $defs: { modifier: { + type: 'string', enum: [ 'readonly', 'private', @@ -62,6 +63,7 @@ export default util.createRule({ minItems: 1, }, prefer: { + type: 'string', enum: ['class-property', 'parameter-property'], }, }, diff --git a/packages/eslint-plugin/src/rules/return-await.ts b/packages/eslint-plugin/src/rules/return-await.ts index 89422a32db08..f9d6584d13f8 100644 --- a/packages/eslint-plugin/src/rules/return-await.ts +++ b/packages/eslint-plugin/src/rules/return-await.ts @@ -37,6 +37,7 @@ export default util.createRule({ }, schema: [ { + type: 'string', enum: ['in-try-catch', 'always', 'never'], }, ], diff --git a/packages/eslint-plugin/src/rules/space-before-function-paren.ts b/packages/eslint-plugin/src/rules/space-before-function-paren.ts index 369ae43d8806..d82e8a94b26a 100644 --- a/packages/eslint-plugin/src/rules/space-before-function-paren.ts +++ b/packages/eslint-plugin/src/rules/space-before-function-paren.ts @@ -29,18 +29,22 @@ export default util.createRule({ { oneOf: [ { + type: 'string', enum: ['always', 'never'], }, { type: 'object', properties: { anonymous: { + type: 'string', enum: ['always', 'never', 'ignore'], }, named: { + type: 'string', enum: ['always', 'never', 'ignore'], }, asyncArrow: { + type: 'string', enum: ['always', 'never', 'ignore'], }, }, diff --git a/packages/eslint-plugin/src/rules/triple-slash-reference.ts b/packages/eslint-plugin/src/rules/triple-slash-reference.ts index 0eef13685055..10f85b6cc6e6 100644 --- a/packages/eslint-plugin/src/rules/triple-slash-reference.ts +++ b/packages/eslint-plugin/src/rules/triple-slash-reference.ts @@ -30,12 +30,15 @@ export default util.createRule({ type: 'object', properties: { lib: { + type: 'string', enum: ['always', 'never'], }, path: { + type: 'string', enum: ['always', 'never'], }, types: { + type: 'string', enum: ['always', 'never', 'prefer-import'], }, }, diff --git a/packages/eslint-plugin/tests/schema-snapshots/array-type.shot b/packages/eslint-plugin/tests/schema-snapshots/array-type.shot index 4fef7c8ec978..4f46cb9a726c 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/array-type.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/array-type.shot @@ -8,7 +8,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos { "$defs": { "arrayOption": { - "enum": ["array", "array-simple", "generic"] + "enum": ["array", "array-simple", "generic"], + "type": "string" } }, "additionalProperties": false, diff --git a/packages/eslint-plugin/tests/schema-snapshots/ban-ts-comment.shot b/packages/eslint-plugin/tests/schema-snapshots/ban-ts-comment.shot index ee076d804daa..a39ac4e59b3b 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/ban-ts-comment.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/ban-ts-comment.shot @@ -14,7 +14,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos "type": "boolean" }, { - "enum": ["allow-with-description"] + "enum": ["allow-with-description"], + "type": "string" }, { "additionalProperties": false, diff --git a/packages/eslint-plugin/tests/schema-snapshots/ban-types.shot b/packages/eslint-plugin/tests/schema-snapshots/ban-types.shot index 68f35c203ee1..a7fe2d555cda 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/ban-types.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/ban-types.shot @@ -15,11 +15,13 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos }, { "description": "Un-bans the type (useful when paired with \`extendDefaults\`)", - "enum": [false] + "enum": [false], + "type": "boolean" }, { "description": "Bans the type with the default message", - "enum": [true] + "enum": [true], + "type": "boolean" }, { "description": "Bans the type with a custom message", diff --git a/packages/eslint-plugin/tests/schema-snapshots/class-literal-property-style.shot b/packages/eslint-plugin/tests/schema-snapshots/class-literal-property-style.shot index 1bf67927f610..ab5b34c1d89c 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/class-literal-property-style.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/class-literal-property-style.shot @@ -6,7 +6,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos [ { - "enum": ["fields", "getters"] + "enum": ["fields", "getters"], + "type": "string" } ] diff --git a/packages/eslint-plugin/tests/schema-snapshots/comma-dangle.shot b/packages/eslint-plugin/tests/schema-snapshots/comma-dangle.shot index a5b0ca54a315..645b7ce040f7 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/comma-dangle.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/comma-dangle.shot @@ -7,7 +7,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos { "$defs": { "value": { - "enum": ["always", "always-multiline", "never", "only-multiline"] + "enum": ["always", "always-multiline", "never", "only-multiline"], + "type": "string" }, "valueWithIgnore": { "enum": [ @@ -16,10 +17,11 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos "ignore", "never", "only-multiline" - ] + ], + "type": "string" } }, - "additionalProperties": false, + "additionalItems": false, "items": [ { "oneOf": [ diff --git a/packages/eslint-plugin/tests/schema-snapshots/consistent-generic-constructors.shot b/packages/eslint-plugin/tests/schema-snapshots/consistent-generic-constructors.shot index 540eea55862f..339f564088a9 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/consistent-generic-constructors.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/consistent-generic-constructors.shot @@ -6,7 +6,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos [ { - "enum": ["constructor", "type-annotation"] + "enum": ["constructor", "type-annotation"], + "type": "string" } ] diff --git a/packages/eslint-plugin/tests/schema-snapshots/consistent-indexed-object-style.shot b/packages/eslint-plugin/tests/schema-snapshots/consistent-indexed-object-style.shot index 5befaa24e0c4..d498aa9d3571 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/consistent-indexed-object-style.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/consistent-indexed-object-style.shot @@ -6,7 +6,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos [ { - "enum": ["index-signature", "record"] + "enum": ["index-signature", "record"], + "type": "string" } ] diff --git a/packages/eslint-plugin/tests/schema-snapshots/consistent-type-assertions.shot b/packages/eslint-plugin/tests/schema-snapshots/consistent-type-assertions.shot index 04acdfde423c..b50dc807a9ba 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/consistent-type-assertions.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/consistent-type-assertions.shot @@ -11,7 +11,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos "additionalProperties": false, "properties": { "assertionStyle": { - "enum": ["never"] + "enum": ["never"], + "type": "string" } }, "required": ["assertionStyle"], @@ -21,10 +22,12 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos "additionalProperties": false, "properties": { "assertionStyle": { - "enum": ["angle-bracket", "as"] + "enum": ["angle-bracket", "as"], + "type": "string" }, "objectLiteralTypeAssertions": { - "enum": ["allow", "allow-as-parameter", "never"] + "enum": ["allow", "allow-as-parameter", "never"], + "type": "string" } }, "required": ["assertionStyle"], diff --git a/packages/eslint-plugin/tests/schema-snapshots/consistent-type-definitions.shot b/packages/eslint-plugin/tests/schema-snapshots/consistent-type-definitions.shot index 130f2ac3c9cd..0a7217423843 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/consistent-type-definitions.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/consistent-type-definitions.shot @@ -6,7 +6,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos [ { - "enum": ["interface", "type"] + "enum": ["interface", "type"], + "type": "string" } ] diff --git a/packages/eslint-plugin/tests/schema-snapshots/consistent-type-imports.shot b/packages/eslint-plugin/tests/schema-snapshots/consistent-type-imports.shot index 4f8ad7949097..7164fbdd3672 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/consistent-type-imports.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/consistent-type-imports.shot @@ -12,10 +12,12 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos "type": "boolean" }, "fixStyle": { - "enum": ["inline-type-imports", "separate-type-imports"] + "enum": ["inline-type-imports", "separate-type-imports"], + "type": "string" }, "prefer": { - "enum": ["no-type-imports", "type-imports"] + "enum": ["no-type-imports", "type-imports"], + "type": "string" } }, "type": "object" diff --git a/packages/eslint-plugin/tests/schema-snapshots/explicit-member-accessibility.shot b/packages/eslint-plugin/tests/schema-snapshots/explicit-member-accessibility.shot index f0a2dc9a4fba..5a33d7fca21f 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/explicit-member-accessibility.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/explicit-member-accessibility.shot @@ -11,15 +11,18 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos "oneOf": [ { "description": "Always require an accessor.", - "enum": ["explicit"] + "enum": ["explicit"], + "type": "string" }, { "description": "Require an accessor except when public.", - "enum": ["no-public"] + "enum": ["no-public"], + "type": "string" }, { "description": "Never check whether there is an accessor.", - "enum": ["off"] + "enum": ["off"], + "type": "string" } ] } diff --git a/packages/eslint-plugin/tests/schema-snapshots/func-call-spacing.shot b/packages/eslint-plugin/tests/schema-snapshots/func-call-spacing.shot index 3c9d0f7ed235..d3192bbdc547 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/func-call-spacing.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/func-call-spacing.shot @@ -9,7 +9,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos { "items": [ { - "enum": ["never"] + "enum": ["never"], + "type": "string" } ], "maxItems": 1, @@ -19,7 +20,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos { "items": [ { - "enum": ["always"] + "enum": ["always"], + "type": "string" }, { "additionalProperties": false, diff --git a/packages/eslint-plugin/tests/schema-snapshots/member-delimiter-style.shot b/packages/eslint-plugin/tests/schema-snapshots/member-delimiter-style.shot index 6b5cf0a4a419..a1c9dcc17eee 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/member-delimiter-style.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/member-delimiter-style.shot @@ -38,10 +38,12 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos "type": "object" }, "multiLineOption": { - "enum": ["comma", "none", "semi"] + "enum": ["comma", "none", "semi"], + "type": "string" }, "singleLineOption": { - "enum": ["comma", "semi"] + "enum": ["comma", "semi"], + "type": "string" } }, "additionalProperties": false, @@ -59,7 +61,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos "type": "object" }, "multilineDetection": { - "enum": ["brackets", "last-member"] + "enum": ["brackets", "last-member"], + "type": "string" }, "overrides": { "additionalProperties": false, diff --git a/packages/eslint-plugin/tests/schema-snapshots/method-signature-style.shot b/packages/eslint-plugin/tests/schema-snapshots/method-signature-style.shot index d03573a08981..b66647bd92d3 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/method-signature-style.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/method-signature-style.shot @@ -6,7 +6,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos [ { - "enum": ["method", "property"] + "enum": ["method", "property"], + "type": "string" } ] diff --git a/packages/eslint-plugin/tests/schema-snapshots/no-empty-function.shot b/packages/eslint-plugin/tests/schema-snapshots/no-empty-function.shot index e863a0f81ccd..c7660d3ec1ea 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/no-empty-function.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/no-empty-function.shot @@ -25,7 +25,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos "private-constructors", "protected-constructors", "setters" - ] + ], + "type": "string" }, "type": "array", "uniqueItems": true diff --git a/packages/eslint-plugin/tests/schema-snapshots/no-invalid-void-type.shot b/packages/eslint-plugin/tests/schema-snapshots/no-invalid-void-type.shot index 61f32fe43a8e..a6d271f1a0f4 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/no-invalid-void-type.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/no-invalid-void-type.shot @@ -20,7 +20,7 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos "items": { "type": "string" }, - "minLength": 1, + "minItems": 1, "type": "array" } ] @@ -36,7 +36,7 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos type Options = [ { allowAsThisParameter?: boolean; - allowInGenericTypeArguments?: boolean | string[]; + allowInGenericTypeArguments?: [string, ...string[]] | boolean; }, ]; " diff --git a/packages/eslint-plugin/tests/schema-snapshots/no-shadow.shot b/packages/eslint-plugin/tests/schema-snapshots/no-shadow.shot index d16291030d6b..78b85fbadc0d 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/no-shadow.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/no-shadow.shot @@ -18,7 +18,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos "type": "boolean" }, "hoist": { - "enum": ["all", "functions", "never"] + "enum": ["all", "functions", "never"], + "type": "string" }, "ignoreFunctionTypeParameterNameValueShadow": { "type": "boolean" diff --git a/packages/eslint-plugin/tests/schema-snapshots/no-type-alias.shot b/packages/eslint-plugin/tests/schema-snapshots/no-type-alias.shot index 16653ab25654..f2c6920de9c2 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/no-type-alias.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/no-type-alias.shot @@ -14,10 +14,12 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos "in-unions", "in-unions-and-intersections", "never" - ] + ], + "type": "string" }, "simpleOptions": { - "enum": ["always", "never"] + "enum": ["always", "never"], + "type": "string" } }, "additionalProperties": false, diff --git a/packages/eslint-plugin/tests/schema-snapshots/no-unused-vars.shot b/packages/eslint-plugin/tests/schema-snapshots/no-unused-vars.shot index 802a33bfade6..a87d2016784b 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/no-unused-vars.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/no-unused-vars.shot @@ -8,19 +8,22 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos { "oneOf": [ { - "enum": ["all", "local"] + "enum": ["all", "local"], + "type": "string" }, { "additionalProperties": false, "properties": { "args": { - "enum": ["after-used", "all", "none"] + "enum": ["after-used", "all", "none"], + "type": "string" }, "argsIgnorePattern": { "type": "string" }, "caughtErrors": { - "enum": ["all", "none"] + "enum": ["all", "none"], + "type": "string" }, "caughtErrorsIgnorePattern": { "type": "string" @@ -32,7 +35,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos "type": "boolean" }, "vars": { - "enum": ["all", "local"] + "enum": ["all", "local"], + "type": "string" }, "varsIgnorePattern": { "type": "string" diff --git a/packages/eslint-plugin/tests/schema-snapshots/no-use-before-define.shot b/packages/eslint-plugin/tests/schema-snapshots/no-use-before-define.shot index cfe91c2c7b7e..624448da333f 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/no-use-before-define.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/no-use-before-define.shot @@ -8,7 +8,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos { "oneOf": [ { - "enum": ["nofunc"] + "enum": ["nofunc"], + "type": "string" }, { "additionalProperties": false, diff --git a/packages/eslint-plugin/tests/schema-snapshots/padding-line-between-statements.shot b/packages/eslint-plugin/tests/schema-snapshots/padding-line-between-statements.shot index 7e87a4e68563..63acbd25d501 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/padding-line-between-statements.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/padding-line-between-statements.shot @@ -7,7 +7,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos { "$defs": { "paddingType": { - "enum": ["always", "any", "never"] + "enum": ["always", "any", "never"], + "type": "string" }, "statementType": { "anyOf": [ @@ -53,7 +54,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos "var", "while", "with" - ] + ], + "type": "string" }, { "additionalItems": false, @@ -99,7 +101,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos "var", "while", "with" - ] + ], + "type": "string" }, "minItems": 1, "type": "array", diff --git a/packages/eslint-plugin/tests/schema-snapshots/parameter-properties.shot b/packages/eslint-plugin/tests/schema-snapshots/parameter-properties.shot index f317443ca001..461b50d919ef 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/parameter-properties.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/parameter-properties.shot @@ -16,7 +16,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos "public", "public readonly", "readonly" - ] + ], + "type": "string" } }, "additionalProperties": false, @@ -29,7 +30,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos "type": "array" }, "prefer": { - "enum": ["class-property", "parameter-property"] + "enum": ["class-property", "parameter-property"], + "type": "string" } }, "type": "object" diff --git a/packages/eslint-plugin/tests/schema-snapshots/return-await.shot b/packages/eslint-plugin/tests/schema-snapshots/return-await.shot index 7d0a6d5e142e..5d79a331bf33 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/return-await.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/return-await.shot @@ -6,7 +6,8 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos [ { - "enum": ["always", "in-try-catch", "never"] + "enum": ["always", "in-try-catch", "never"], + "type": "string" } ] diff --git a/packages/eslint-plugin/tests/schema-snapshots/space-before-function-paren.shot b/packages/eslint-plugin/tests/schema-snapshots/space-before-function-paren.shot index 67ca6e24371e..08a6df9b9029 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/space-before-function-paren.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/space-before-function-paren.shot @@ -8,19 +8,23 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos { "oneOf": [ { - "enum": ["always", "never"] + "enum": ["always", "never"], + "type": "string" }, { "additionalProperties": false, "properties": { "anonymous": { - "enum": ["always", "ignore", "never"] + "enum": ["always", "ignore", "never"], + "type": "string" }, "asyncArrow": { - "enum": ["always", "ignore", "never"] + "enum": ["always", "ignore", "never"], + "type": "string" }, "named": { - "enum": ["always", "ignore", "never"] + "enum": ["always", "ignore", "never"], + "type": "string" } }, "type": "object" diff --git a/packages/eslint-plugin/tests/schema-snapshots/triple-slash-reference.shot b/packages/eslint-plugin/tests/schema-snapshots/triple-slash-reference.shot index c5b400712bf4..330be71ffe18 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/triple-slash-reference.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/triple-slash-reference.shot @@ -9,13 +9,16 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos "additionalProperties": false, "properties": { "lib": { - "enum": ["always", "never"] + "enum": ["always", "never"], + "type": "string" }, "path": { - "enum": ["always", "never"] + "enum": ["always", "never"], + "type": "string" }, "types": { - "enum": ["always", "never", "prefer-import"] + "enum": ["always", "never", "prefer-import"], + "type": "string" } }, "type": "object" diff --git a/packages/eslint-plugin/tests/schemas.test.ts b/packages/eslint-plugin/tests/schemas.test.ts index 19cf8280c5b1..08221924026a 100644 --- a/packages/eslint-plugin/tests/schemas.test.ts +++ b/packages/eslint-plugin/tests/schemas.test.ts @@ -1,16 +1,16 @@ import 'jest-specific-snapshot'; +import fs from 'node:fs'; +import path from 'node:path'; + import { compile } from '@typescript-eslint/rule-schema-to-typescript-types'; -import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema'; -import fs, { mkdirSync } from 'fs'; -import path from 'path'; import { format, resolveConfig } from 'prettier'; import rules from '../src/rules/index'; const snapshotFolder = path.resolve(__dirname, 'schema-snapshots'); try { - mkdirSync(snapshotFolder); + fs.mkdirSync(snapshotFolder); } catch { // ignore failure as it means it already exists probably } @@ -129,7 +129,7 @@ const VALID_SCHEMA_PROPS = new Set([ 'title', 'type', 'uniqueItems', -] satisfies (keyof JSONSchema4)[]); +]); describe('Rules should only define valid keys on schemas', () => { for (const [ruleName, ruleDef] of Object.entries(rules)) { (ruleName === ONLY ? it.only : it)(ruleName, () => { diff --git a/packages/rule-schema-to-typescript-types/src/generateArrayType.ts b/packages/rule-schema-to-typescript-types/src/generateArrayType.ts index cece1fa40255..1165ec7dbc4a 100644 --- a/packages/rule-schema-to-typescript-types/src/generateArrayType.ts +++ b/packages/rule-schema-to-typescript-types/src/generateArrayType.ts @@ -1,4 +1,7 @@ -import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema'; +import type { + JSONSchema4, + JSONSchema4ArraySchema, +} from '@typescript-eslint/utils/json-schema'; import { NotSupportedError, UnexpectedError } from './errors'; import { generateType } from './generateType'; @@ -13,7 +16,7 @@ import type { ArrayAST, AST, RefMap, TupleAST, UnionAST } from './types'; const MAX_ITEMS_TO_TUPLIZE = 20; export function generateArrayType( - schema: JSONSchema4, + schema: JSONSchema4ArraySchema, refMap: RefMap, ): ArrayAST | TupleAST | UnionAST { if (!schema.items) { diff --git a/packages/rule-schema-to-typescript-types/src/generateObjectType.ts b/packages/rule-schema-to-typescript-types/src/generateObjectType.ts index c0de43699d36..30ece46cdf33 100644 --- a/packages/rule-schema-to-typescript-types/src/generateObjectType.ts +++ b/packages/rule-schema-to-typescript-types/src/generateObjectType.ts @@ -1,5 +1,5 @@ import { requiresQuoting } from '@typescript-eslint/type-utils'; -import type { JSONSchema4 } from 'json-schema'; +import type { JSONSchema4ObjectSchema } from '@typescript-eslint/utils/json-schema'; import { generateType } from './generateType'; import { getCommentLines } from './getCommentLines'; @@ -7,7 +7,7 @@ import { isArray } from './isArray'; import type { AST, ObjectAST, RefMap } from './types'; export function generateObjectType( - schema: JSONSchema4, + schema: JSONSchema4ObjectSchema, refMap: RefMap, ): ObjectAST { const commentLines = getCommentLines(schema); diff --git a/packages/rule-schema-to-typescript-types/src/generateType.ts b/packages/rule-schema-to-typescript-types/src/generateType.ts index d6c0efa2890f..e077926c34b6 100644 --- a/packages/rule-schema-to-typescript-types/src/generateType.ts +++ b/packages/rule-schema-to-typescript-types/src/generateType.ts @@ -9,7 +9,7 @@ import { isArray } from './isArray'; import type { AST, RefMap } from './types'; // keywords we probably should support but currently do not support -const UNSUPPORTED_KEYWORDS = new Set([ +const UNSUPPORTED_KEYWORDS = new Set([ 'allOf', 'dependencies', 'extends', @@ -18,7 +18,7 @@ const UNSUPPORTED_KEYWORDS = new Set([ 'multipleOf', 'not', 'patternProperties', -] satisfies (keyof JSONSchema4)[]); +]); export function generateType(schema: JSONSchema4, refMap: RefMap): AST { const unsupportedProps = Object.keys(schema).filter(key => @@ -46,13 +46,13 @@ export function generateType(schema: JSONSchema4, refMap: RefMap): AST { commentLines, }; } - if (schema.enum) { + if ('enum' in schema && schema.enum) { return { ...generateUnionType(schema.enum, refMap), commentLines, }; } - if (schema.anyOf) { + if ('anyOf' in schema && schema.anyOf) { return { // a union isn't *TECHNICALLY* correct - technically anyOf is actually // anyOf: [T, U, V] -> T | U | V | T & U | T & V | U & V @@ -61,22 +61,22 @@ export function generateType(schema: JSONSchema4, refMap: RefMap): AST { commentLines, }; } - if (schema.oneOf) { + if ('oneOf' in schema && schema.oneOf) { return { ...generateUnionType(schema.oneOf, refMap), commentLines, }; } - if (isArray(schema.type)) { - throw new NotSupportedError('schemas with multiple types', schema); - } - if (schema.type == null) { + if (!('type' in schema) || schema.type == null) { throw new NotSupportedError( 'untyped schemas without one of [$ref, enum, oneOf]', schema, ); } + if (isArray(schema.type)) { + throw new NotSupportedError('schemas with multiple types', schema); + } switch (schema.type) { case 'any': diff --git a/packages/rule-schema-to-typescript-types/src/index.ts b/packages/rule-schema-to-typescript-types/src/index.ts index 3100f122f2dd..43d16826ab30 100644 --- a/packages/rule-schema-to-typescript-types/src/index.ts +++ b/packages/rule-schema-to-typescript-types/src/index.ts @@ -1,4 +1,4 @@ -import type { JSONSchema4 } from 'json-schema'; +import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema'; import path from 'path'; import { format as prettierFormat, resolveConfig } from 'prettier'; diff --git a/packages/rule-tester/src/utils/config-schema.ts b/packages/rule-tester/src/utils/config-schema.ts index 8261ac8749c8..8aaa46d4cace 100644 --- a/packages/rule-tester/src/utils/config-schema.ts +++ b/packages/rule-tester/src/utils/config-schema.ts @@ -1,8 +1,8 @@ // Forked from https://github.com/eslint/eslint/blob/ad9dd6a933fd098a0d99c6a9aa059850535c23ee/conf/config-schema.js -import type { JSONSchema } from '@typescript-eslint/utils'; +import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema'; -const baseConfigProperties: JSONSchema.JSONSchema4['properties'] = { +const baseConfigProperties: Record = { $schema: { type: 'string' }, defaultFilenames: { type: 'object', @@ -39,7 +39,7 @@ const baseConfigProperties: JSONSchema.JSONSchema4['properties'] = { ecmaFeatures: { type: 'object' }, // deprecated; logs a warning when used }; -export const configSchema: JSONSchema.JSONSchema4 = { +export const configSchema: JSONSchema4 = { definitions: { stringOrStrings: { oneOf: [ diff --git a/packages/rule-tester/tests/RuleTester.test.ts b/packages/rule-tester/tests/RuleTester.test.ts index 6ed3edc23f35..384b2cd3e20e 100644 --- a/packages/rule-tester/tests/RuleTester.test.ts +++ b/packages/rule-tester/tests/RuleTester.test.ts @@ -125,7 +125,7 @@ const NOOP_RULE: RuleModule<'error', []> = { error: 'error', }, type: 'problem', - schema: {}, + schema: [], }, defaultOptions: [], create() { diff --git a/packages/utils/src/json-schema.ts b/packages/utils/src/json-schema.ts index 9c9836f3d82a..f022791c2f81 100644 --- a/packages/utils/src/json-schema.ts +++ b/packages/utils/src/json-schema.ts @@ -3,11 +3,6 @@ * We intentionally fork this because: * - ESLint ***ONLY*** supports JSONSchema v4 * - We want to provide stricter types - * - * Changes: - * - Removed loose `[k: string]: any` indexer as it allows for bad, unused properties. - * - Added `$defs` as an alternate to `definitions`. - * - strictly typed `formats` for ajv v6 */ //================================================================================================== @@ -18,34 +13,19 @@ * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.1 */ export type JSONSchema4TypeName = - // | 'string' - // | 'number' - // | 'integer' + | 'string' + | 'number' + | 'integer' | 'boolean' - // | 'object' - // | 'array' + | 'object' + | 'array' | 'null' | 'any'; /** * @see https://tools.ietf.org/html/draft-zyp-json-schema-04#section-3.5 */ -export type JSONSchema4Type = - | string - | number - | boolean - | JSONSchema4Object - | JSONSchema4Array - | null; - -// Workaround for infinite type recursion -export interface JSONSchema4Object { - [key: string]: JSONSchema4Type; -} - -// Workaround for infinite type recursion -// https://github.com/Microsoft/TypeScript/issues/3496#issuecomment-128553540 -export interface JSONSchema4Array extends Array {} +export type JSONSchema4Type = string | number | boolean | null; /** * Meta schema @@ -66,112 +46,62 @@ export type JSONSchema4Version = string; * JSON Schema V4 * @see https://tools.ietf.org/html/draft-zyp-json-schema-04 */ -export interface JSONSchema4 { +export type JSONSchema4 = + | JSONSchema4ObjectSchema + | JSONSchema4ArraySchema + | JSONSchema4StringSchema + | JSONSchema4NumberSchema + | JSONSchema4BoleanSchema + | JSONSchema4NullSchema + | JSONSchema4AnySchema + | JSONSchema4RefSchema + | JSONSchema4AllOfSchema + | JSONSchema4AnyOfSchema + | JSONSchema4OneOfSchema + | JSONSchema4MultiSchema; + +interface JSONSchema4Base { id?: string | undefined; - $ref?: string | undefined; + $schema?: JSONSchema4Version | undefined; /** - * This attribute is a string that provides a short description of the - * instance property. - * - * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.21 + * A single type, or a union of simple types */ - title?: string | undefined; + type?: JSONSchema4TypeName | JSONSchema4TypeName[] | undefined; /** - * This attribute is a string that provides a full description of the of - * purpose the instance property. + * Path to a schema defined in `definitions`/`$defs` that will form the base + * for this schema. * - * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.22 - */ - description?: string | undefined; - - default?: JSONSchema4Type | undefined; - multipleOf?: number | undefined; - maximum?: number | undefined; - exclusiveMaximum?: boolean | undefined; - minimum?: number | undefined; - exclusiveMinimum?: boolean | undefined; - maxLength?: number | undefined; - minLength?: number | undefined; - pattern?: string | undefined; - - /** - * May only be defined when "items" is defined, and is a tuple of JSONSchemas. + * If you are defining an "array" schema (`schema: [ ... ]`) for your rule + * then you should prefix this with `items/0` so that the validator can find + * your definitions. * - * This provides a definition for additional items in an array instance - * when tuple definitions of the items is provided. This can be false - * to indicate additional items in the array are not allowed, or it can - * be a schema that defines the schema of the additional items. + * eg: `'#/items/0/definitions/myDef'` * - * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.6 - */ - additionalItems?: boolean | JSONSchema4 | undefined; - - /** - * This attribute defines the allowed items in an instance array, and - * MUST be a schema or an array of schemas. The default value is an - * empty schema which allows any value for items in the instance array. + * Otherwise if you are defining an "object" schema (`schema: { ... }`) for + * your rule you can directly reference your definitions * - * When this attribute value is a schema and the instance value is an - * array, then all the items in the array MUST be valid according to the - * schema. - * - * When this attribute value is an array of schemas and the instance - * value is an array, each position in the instance array MUST conform - * to the schema in the corresponding position for this array. This - * called tuple typing. When tuple typing is used, additional items are - * allowed, disallowed, or constrained by the "additionalItems" - * (Section 5.6) attribute using the same rules as - * "additionalProperties" (Section 5.4) for objects. - * - * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.5 - */ - items?: JSONSchema4 | JSONSchema4[] | undefined; - - /** - * Defines the maximum length of an array - */ - maxItems?: number | undefined; - /** - * Defines the minimum length of an array - */ - minItems?: number | undefined; - /** - * Enforces that all items in the array are unique - */ - uniqueItems?: boolean | undefined; - - /** - * The maximum number of properties allowed for record-style schemas + * eg: `'#/definitions/myDef'` */ - maxProperties?: number | undefined; - /** - * The minimum number of properties required for record-style schemas - */ - minProperties?: number | undefined; + $ref?: string | undefined; /** - * This attribute indicates if the instance must have a value, and not - * be undefined. This is false by default, making the instance - * optional. + * This attribute is a string that provides a short description of the + * instance property. * - * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.7 + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.21 */ - required?: boolean | string[] | undefined; + title?: string | undefined; /** - * This attribute defines a schema for all properties that are not - * explicitly defined in an object type definition. If specified, the - * value MUST be a schema or a boolean. If false is provided, no - * additional properties are allowed beyond the properties defined in - * the schema. The default value is an empty schema which allows any - * value for additional properties. + * This attribute is a string that provides a full description of the of + * purpose the instance property. * - * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.4 + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.22 */ - additionalProperties?: boolean | JSONSchema4 | undefined; + description?: string | undefined; /** * Reusable definitions that can be referenced via `$ref` @@ -190,86 +120,6 @@ export interface JSONSchema4 { } | undefined; - /** - * This attribute is an object with property definitions that define the - * valid values of instance object property values. When the instance - * value is an object, the property values of the instance object MUST - * conform to the property definitions in this object. In this object, - * each property definition's value MUST be a schema, and the property's - * name MUST be the name of the instance property that it defines. The - * instance property value MUST be valid according to the schema from - * the property definition. Properties are considered unordered, the - * order of the instance properties MAY be in any order. - * - * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.2 - */ - properties?: - | { - [k: string]: JSONSchema4; - } - | undefined; - - /** - * This attribute is an object that defines the schema for a set of - * property names of an object instance. The name of each property of - * this attribute's object is a regular expression pattern in the ECMA - * 262/Perl 5 format, while the value is a schema. If the pattern - * matches the name of a property on the instance object, the value of - * the instance's property MUST be valid against the pattern name's - * schema value. - * - * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.3 - */ - patternProperties?: - | { - [k: string]: JSONSchema4; - } - | undefined; - - /** - * The `dependencies` keyword conditionally applies a sub-schema when a given - * property is present. This schema is applied in the same way `allOf` applies - * schemas. Nothing is merged or extended. Both schemas apply independently. - */ - dependencies?: - | { - [k: string]: JSONSchema4 | string[]; - } - | undefined; - - /** - * This provides an enumeration of all possible values that are valid - * for the instance property. This MUST be an array, and each item in - * the array represents a possible value for the instance value. If - * this attribute is defined, the instance value MUST be one of the - * values in the array in order for the schema to be valid. - * - * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19 - */ - enum?: JSONSchema4Type[] | undefined; - - /** - * A single type, or a union of simple types - */ - type?: JSONSchema4TypeName | JSONSchema4TypeName[] | undefined; - - /** - * (AND) Must be valid against all of the sub-schemas - */ - allOf?: JSONSchema4[] | undefined; - /** - * (OR) Must be valid against any of the sub-schemas - */ - anyOf?: JSONSchema4[] | undefined; - /** - * (XOR) Must be valid against exactly one of the sub-schemas - */ - oneOf?: JSONSchema4[] | undefined; - /** - * (NOT) Must not be valid against the given schema - */ - not?: JSONSchema4 | undefined; - /** * The value of this property MUST be another schema which will provide * a base schema which the current schema will inherit from. The @@ -289,80 +139,23 @@ export interface JSONSchema4 { extends?: string | string[] | undefined; /** - * The `format` keyword allows for basic semantic identification of certain - * kinds of string values that are commonly used. - * - * For example, because JSON doesn’t have a “DateTime” type, dates need to be - * encoded as strings. `format` allows the schema author to indicate that the - * string value should be interpreted as a date. - * - * ajv v6 provides a few built-in formats - all other strings will cause AJV - * to throw during schema compilation - */ - format?: - | 'date' - | 'time' - | 'date-time' - | 'uri' - | 'uri-reference' - | 'uri-template' - | 'url' - | 'email' - | 'hostname' - | 'ipv4' - | 'ipv6' - | 'regex' - | 'uuid' - | 'json-pointer' - | 'json-pointer-uri-fragment' - | 'relative-json-pointer' - | undefined; -} - -interface JSONSchema4Base { - id?: string | undefined; - - $schema?: JSONSchema4Version | undefined; - - /** - * Path to a schema defined in `definitions`/`$defs` that will form the base - * for this chema + * The default value for the item if not present */ - $ref?: string | undefined; - - /** - * This attribute is a string that provides a short description of the - * instance property. - * - * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.21 - */ - title?: string | undefined; + default?: JSONSchema4Type | undefined; /** - * This attribute is a string that provides a full description of the of - * purpose the instance property. + * This attribute indicates if the instance must have a value, and not + * be undefined. This is false by default, making the instance + * optional. * - * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.22 + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.7 */ - description?: string | undefined; + required?: boolean | string[] | undefined; /** - * Reusable definitions that can be referenced via `$ref` - */ - definitions?: - | { - [k: string]: JSONSchema4; - } - | undefined; - /** - * Reusable definitions that can be referenced via `$ref` + * (NOT) Must not be valid against the given schema */ - $defs?: - | { - [k: string]: JSONSchema4; - } - | undefined; - + not?: JSONSchema4 | undefined; /** * (AND) Must be valid against all of the sub-schemas */ @@ -375,28 +168,47 @@ interface JSONSchema4Base { * (XOR) Must be valid against exactly one of the sub-schemas */ oneOf?: JSONSchema4[] | undefined; - /** - * (NOT) Must not be valid against the given schema - */ - not?: JSONSchema4 | undefined; +} + +export interface JSONSchema4RefSchema extends JSONSchema4Base { + type?: undefined; + $ref: string; +} + +export interface JSONSchema4AllOfSchema extends JSONSchema4Base { + type?: undefined; + allOf: JSONSchema4[]; +} +export interface JSONSchema4AnyOfSchema extends JSONSchema4Base { + type?: undefined; + anyOf: JSONSchema4[]; +} + +export interface JSONSchema4OneOfSchema extends JSONSchema4Base { + type?: undefined; + oneOf: JSONSchema4[]; +} + +export interface JSONSchema4MultiSchema + extends Omit, + Omit, + Omit, + Omit, + Omit, + Omit, + Omit { + type: JSONSchema4TypeName[]; /** - * The value of this property MUST be another schema which will provide - * a base schema which the current schema will inherit from. The - * inheritance rules are such that any instance that is valid according - * to the current schema MUST be valid according to the referenced - * schema. This MAY also be an array, in which case, the instance MUST - * be valid for all the schemas in the array. A schema that extends - * another schema MAY define additional attributes, constrain existing - * attributes, or add other constraints. - * - * Conceptually, the behavior of extends can be seen as validating an - * instance against all constraints in the extending schema as well as - * the extended schema(s). + * This provides an enumeration of all possible values that are valid + * for the instance property. This MUST be an array, and each item in + * the array represents a possible value for the instance value. If + * this attribute is defined, the instance value MUST be one of the + * values in the array in order for the schema to be valid. * - * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.26 + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19 */ - extends?: string | string[] | undefined; + enum?: JSONSchema4Type[]; } /** @@ -529,25 +341,22 @@ export interface JSONSchema4ArraySchema extends JSONSchema4Base { uniqueItems?: boolean | undefined; } -interface JSONSchema4PrimitiveBase extends JSONSchema4Base { - /** - * This provides an enumeration of all possible values that are valid - * for the instance property. This MUST be an array, and each item in - * the array represents a possible value for the instance value. If - * this attribute is defined, the instance value MUST be one of the - * values in the array in order for the schema to be valid. - * - * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19 - */ - enum?: JSONSchema4Type[] | undefined; -} - /** * @see https://json-schema.org/understanding-json-schema/reference/string.html */ -export interface JSONSchema4StringSchema extends JSONSchema4PrimitiveBase { +export interface JSONSchema4StringSchema extends JSONSchema4Base { type: 'string'; + /** + * The maximum allowed length for the string + */ + maxLength?: number | undefined; + + /** + * The minimum allowed length for the string + */ + minLength?: number | undefined; + /** * The `pattern` keyword is used to restrict a string to a particular regular * expression. The regular expression syntax is the one defined in JavaScript @@ -592,11 +401,98 @@ export interface JSONSchema4StringSchema extends JSONSchema4PrimitiveBase { | 'json-pointer-uri-fragment' | 'relative-json-pointer' | undefined; + + enum?: string[] | undefined; } /** * @see https://json-schema.org/understanding-json-schema/reference/numeric.html */ -export interface JSONSchema4NumberSchema extends JSONSchema4PrimitiveBase { +export interface JSONSchema4NumberSchema extends JSONSchema4Base { type: 'number' | 'integer'; + + /** + * Numbers can be restricted to a multiple of a given number, using the + * `multipleOf` keyword. It may be set to any positive number. + */ + multipleOf?: number | undefined; + + /** + * The maximum allowed value for the number + */ + maximum?: number | undefined; + + /** + * The minimum allowed value for the number + */ + minimum?: number | undefined; + + /** + * The exclusive minimum allowed value for the number + * - `true` = `x < maximum` + * - `false` = `x <= maximum` + * + * Default is `false` + */ + exclusiveMaximum?: boolean | undefined; + + /** + * Indicates whether or not `minimum` is the inclusive or exclusive minimum + * - `true` = `x > minimum` + * - `false` = `x ≥ minimum` + * + * Default is `false` + */ + exclusiveMinimum?: boolean | undefined; + + /** + * This provides an enumeration of all possible values that are valid + * for the instance property. This MUST be an array, and each item in + * the array represents a possible value for the instance value. If + * this attribute is defined, the instance value MUST be one of the + * values in the array in order for the schema to be valid. + * + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19 + */ + enum?: number[] | undefined; +} + +/** + * @see https://json-schema.org/understanding-json-schema/reference/boolean.html + */ +export interface JSONSchema4BoleanSchema extends JSONSchema4Base { + type: 'boolean'; + + /** + * This provides an enumeration of all possible values that are valid + * for the instance property. This MUST be an array, and each item in + * the array represents a possible value for the instance value. If + * this attribute is defined, the instance value MUST be one of the + * values in the array in order for the schema to be valid. + * + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19 + */ + enum?: boolean[] | undefined; +} + +/** + * @see https://json-schema.org/understanding-json-schema/reference/null.html + */ +export interface JSONSchema4NullSchema extends JSONSchema4Base { + type: 'null'; + + /** + * This provides an enumeration of all possible values that are valid + * for the instance property. This MUST be an array, and each item in + * the array represents a possible value for the instance value. If + * this attribute is defined, the instance value MUST be one of the + * values in the array in order for the schema to be valid. + * + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19 + */ + enum?: null[] | undefined; +} + +export interface JSONSchema4AnySchema extends JSONSchema4Base { + type: 'any'; } diff --git a/packages/utils/tests/eslint-utils/rule-tester/RuleTester.test.ts b/packages/utils/tests/eslint-utils/rule-tester/RuleTester.test.ts index 57ac48b38c18..1f38883aad32 100644 --- a/packages/utils/tests/eslint-utils/rule-tester/RuleTester.test.ts +++ b/packages/utils/tests/eslint-utils/rule-tester/RuleTester.test.ts @@ -91,7 +91,7 @@ const NOOP_RULE: RuleModule<'error', []> = { error: 'error', }, type: 'problem', - schema: {}, + schema: [], }, defaultOptions: [], create() { diff --git a/packages/website/src/components/lib/jsonSchema.ts b/packages/website/src/components/lib/jsonSchema.ts index 124b85e73426..cc68b440163c 100644 --- a/packages/website/src/components/lib/jsonSchema.ts +++ b/packages/website/src/components/lib/jsonSchema.ts @@ -37,24 +37,27 @@ export function getRuleJsonSchemaWithErrorLevel( additionalItems: false, }; } - // example: explicit-member-accessibility - if (isArray(ruleSchema.items)) { - return { - ...ruleSchema, - items: [defaultRuleSchema, ...ruleSchema.items], - maxItems: ruleSchema.maxItems ? ruleSchema.maxItems + 1 : undefined, - minItems: ruleSchema.minItems ? ruleSchema.minItems + 1 : 1, - additionalItems: false, - }; - } - // example: naming-convention rule - if (typeof ruleSchema.items === 'object' && ruleSchema.items) { - return { - ...ruleSchema, - items: [defaultRuleSchema], - additionalItems: ruleSchema.items, - }; + if (ruleSchema.type === 'array') { + // example: explicit-member-accessibility + if (isArray(ruleSchema.items)) { + return { + ...ruleSchema, + items: [defaultRuleSchema, ...ruleSchema.items], + maxItems: ruleSchema.maxItems ? ruleSchema.maxItems + 1 : undefined, + minItems: ruleSchema.minItems ? ruleSchema.minItems + 1 : 1, + additionalItems: false, + }; + } + // example: naming-convention rule + if (typeof ruleSchema.items === 'object' && ruleSchema.items) { + return { + ...ruleSchema, + items: [defaultRuleSchema], + additionalItems: ruleSchema.items, + }; + } } + // example eqeqeq if (isArray(ruleSchema.anyOf)) { return { From 96e019c78364200f2615c60b75286ddcb20d4703 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Fri, 16 Jun 2023 21:54:37 -0400 Subject: [PATCH 3/3] Also update blog --- .../blog/2023-03-13-announcing-typescript-eslint-v6-beta.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/website/blog/2023-03-13-announcing-typescript-eslint-v6-beta.md b/packages/website/blog/2023-03-13-announcing-typescript-eslint-v6-beta.md index 615a99907dd4..43647637bef6 100644 --- a/packages/website/blog/2023-03-13-announcing-typescript-eslint-v6-beta.md +++ b/packages/website/blog/2023-03-13-announcing-typescript-eslint-v6-beta.md @@ -332,6 +332,7 @@ For more information on the package, [see the `rule-tester` package documentatio - [feat(typescript-estree): remove optionality from AST boolean properties](https://github.com/typescript-eslint/typescript-eslint/pull/6274): Switches most AST properties marked as `?: boolean` to `: boolean`, as well as some properties marked as `?:` optional to `| undefined`. This results in more predictable AST node object shapes. - [chore(typescript-estree): remove visitor-keys backwards compat export](https://github.com/typescript-eslint/typescript-eslint/pull/6242): `visitorKeys` can now only be imported from `@typescript-eslint/visitor-keys`. Previously it was also re-exported by `@typescript-eslint/utils`. - [feat: add package.json exports for public packages](https://github.com/typescript-eslint/typescript-eslint/pull/6458): `@typescript-eslint/*` packages now use `exports` to prevent importing internal file paths. +- [feat: fork json schema types for better compat with ESLint rule validation #6963](https://github.com/typescript-eslint/typescript-eslint/pull/6963): `@typescript-eslint/utils` now exports a more strict version of `JSONSchema4` types, which are more strict in type checking rule options types ## Appreciation