From 481fb44162626ff94a7ab7786c99959991832c1f Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Mon, 25 Apr 2022 19:52:28 -0400 Subject: [PATCH 01/88] feat: adding enums to member-ordering rule --- .vscode/settings.json | 3 + packages/eslint-plugin/README.md | 1 + packages/eslint-plugin/docs/rules/README.md | 1 + .../eslint-plugin/docs/rules/strict-enums.md | 145 +++ packages/eslint-plugin/src/configs/all.ts | 1 + .../recommended-requiring-type-checking.ts | 1 + packages/eslint-plugin/src/rules/index.ts | 2 + .../src/rules/member-ordering.ts | 6 +- .../src/rules/no-invalid-void-type.ts | 2 +- .../eslint-plugin/src/rules/strict-enums.ts | 496 +++++++ .../tests/rules/strict-enums.test.ts | 1135 +++++++++++++++++ 11 files changed, 1789 insertions(+), 4 deletions(-) create mode 100644 packages/eslint-plugin/docs/rules/strict-enums.md create mode 100644 packages/eslint-plugin/src/rules/strict-enums.ts create mode 100644 packages/eslint-plugin/tests/rules/strict-enums.test.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index f0677068d037..4e2f3ac4ecb2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,8 @@ { + // This matches the value in the Prettier config + "editor.rulers": [80], + // An array of language ids which should be validated by ESLint "eslint.validate": [ "javascript", diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index f9126c5f1334..90e880f7170d 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -176,6 +176,7 @@ Pro Tip: For larger codebases you may want to consider splitting our linting int | [`@typescript-eslint/restrict-template-expressions`](./docs/rules/restrict-template-expressions.md) | Enforce template literal expressions to be of string type | :white_check_mark: | | :thought_balloon: | | [`@typescript-eslint/sort-type-union-intersection-members`](./docs/rules/sort-type-union-intersection-members.md) | Enforces that members of a type union/intersection are sorted alphabetically | | :wrench: | | | [`@typescript-eslint/strict-boolean-expressions`](./docs/rules/strict-boolean-expressions.md) | Restricts the types allowed in boolean expressions | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/strict-enums`](./docs/rules/strict-enums.md) | Disallows the usage of unsafe enum patterns | :white_check_mark: | | :thought_balloon: | | [`@typescript-eslint/switch-exhaustiveness-check`](./docs/rules/switch-exhaustiveness-check.md) | Exhaustiveness checking in switch with union type | | | :thought_balloon: | | [`@typescript-eslint/triple-slash-reference`](./docs/rules/triple-slash-reference.md) | Sets preference level for triple slash directives versus ES6-style import declarations | :white_check_mark: | | | | [`@typescript-eslint/type-annotation-spacing`](./docs/rules/type-annotation-spacing.md) | Require consistent spacing around type annotations | | :wrench: | | diff --git a/packages/eslint-plugin/docs/rules/README.md b/packages/eslint-plugin/docs/rules/README.md index 02a16d4452b0..13bf51ee3a16 100644 --- a/packages/eslint-plugin/docs/rules/README.md +++ b/packages/eslint-plugin/docs/rules/README.md @@ -98,6 +98,7 @@ slug: / | [`@typescript-eslint/restrict-template-expressions`](./restrict-template-expressions.md) | Enforce template literal expressions to be of string type | :white_check_mark: | | :thought_balloon: | | [`@typescript-eslint/sort-type-union-intersection-members`](./sort-type-union-intersection-members.md) | Enforces that members of a type union/intersection are sorted alphabetically | | :wrench: | | | [`@typescript-eslint/strict-boolean-expressions`](./strict-boolean-expressions.md) | Restricts the types allowed in boolean expressions | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/strict-enums`](./docs/rules/strict-enums.md) | Disallows the usage of unsafe enum patterns | :white_check_mark: | | :thought_balloon: | | [`@typescript-eslint/switch-exhaustiveness-check`](./switch-exhaustiveness-check.md) | Exhaustiveness checking in switch with union type | | | :thought_balloon: | | [`@typescript-eslint/triple-slash-reference`](./triple-slash-reference.md) | Sets preference level for triple slash directives versus ES6-style import declarations | :white_check_mark: | | | | [`@typescript-eslint/type-annotation-spacing`](./type-annotation-spacing.md) | Require consistent spacing around type annotations | | :wrench: | | diff --git a/packages/eslint-plugin/docs/rules/strict-enums.md b/packages/eslint-plugin/docs/rules/strict-enums.md new file mode 100644 index 000000000000..1b1c24524b1d --- /dev/null +++ b/packages/eslint-plugin/docs/rules/strict-enums.md @@ -0,0 +1,145 @@ +# `strict-enums` + +Disallows the usage of unsafe enum patterns. + +## Rule Details + +Horrifyingly, the TypeScript compiler will allow you to set any number to a variable containing a number enum, like this: + +```ts +enum Fruit { + Apple, + Banana, +} + +let fruit = Fruit.Apple; +fruit = 999; // No error +``` + +This has resulted in many TypeScript programmers avoiding the use of enums altogether. Instead, they should use this rule, which bans working with enums in potentially unsafe ways. + +See the examples below for the types of patterns that are prevented. + +## Goals + +The goal of this rule is to make enums work like they do in other languages. One of the main benefits of enums is that they allow you to write code that is future-safe, because enums are supposed to be resilient to reorganization. If you arbitrarily change the values of an enum (or change the ordering of an enum with computed values), the idea is that nothing in your code-base should break. + +Subsequently, this rule bans potentially-dangerous patterns that you might already be using, like using the greater than operator to select a subset of enum values. + +## Banned Patterns + +This rule bans: + +1. Mismatched enum declarations +1. Mismatched enum assignments +1. Enum incrementing/decrementing +1. Mismatched enum comparisons +1. Mismatched enum function arguments + + + +### ❌ Incorrect + +```ts +const fruit: Fruit = 0; +``` + +```ts +let fruit = Fruit.Apple; +fruit = 1; +``` + +```ts +let fruit = Fruit.Apple; +fruit++; +``` + +```ts +if (fruit === 0) { +} +if (vegetable === 'lettuce') { +} +``` + +```ts +if (fruit > Fruit.Apple) { +} +``` + +```ts +function useFruit(fruit: Fruit) {} +useFruit(0); +``` + +### ✅ Correct + +```ts +const fruit = Fruit.Apple; +``` + +```ts +let fruit = Fruit.Apple; +fruit = Fruit.Banana; +``` + +```ts +let fruit = Fruit.Apple; +fruit = Fruit.Banana; +``` + +```ts +if (fruit === Fruit.Apple) { +} +if (vegetable === Vegetable.Lettuce) { +} +``` + +```ts +if (fruit !== Fruit.Apple) { +} +``` + +```ts +function useFruit(fruit: Fruit) {} +useFruit(Fruit.Apple); +``` + +## Number Enums vs String Enums + +Surprisingly, the TypeScript compiler deals with string enums in a safer way than it does with number enums. If we duplicate the first example above by using a string enum, the TypeScript compiler will correctly throw an error: + +```ts +enum Vegetable { + Lettuce = 'lettuce', + Carrot = 'carrot', +} + +let vegetable = Vegetable.Lettuce; +vegetable = 'tomato'; // Type '"tomato"' is not assignable to type 'Vegetable'. + +// Even "valid" strings will not work, which is good! +vegetable = 'carrot'; // Type '"carrot"' is not assignable to type 'Vegetable'. +``` + +Thus, the `strict-enums` rule is mostly concerned with throwing errors for misused number enums. However, it still prevents mismatched comparison, which slips by the TypeScript compiler even for string enums: + +```ts +// Bad +if (vegetable === 'lettuce') { + // The TypeScript compiler allows this, but the `strict-enums` rule does not +} + +// Good +if (vegetable === Vegetable.Lettuce) { +} +``` + +## Options + +No options are provided. + +## Attributes + +- [x] ✅ Recommended +- [ ] 🔧 Fixable +- [x] 💭 Requires type information diff --git a/packages/eslint-plugin/src/configs/all.ts b/packages/eslint-plugin/src/configs/all.ts index c55e0e6ac37a..5c00c3edf5da 100644 --- a/packages/eslint-plugin/src/configs/all.ts +++ b/packages/eslint-plugin/src/configs/all.ts @@ -160,6 +160,7 @@ export = { 'space-before-blocks': 'off', '@typescript-eslint/space-before-blocks': 'error', '@typescript-eslint/strict-boolean-expressions': 'error', + '@typescript-eslint/strict-enums': 'error', '@typescript-eslint/switch-exhaustiveness-check': 'error', '@typescript-eslint/triple-slash-reference': 'error', '@typescript-eslint/type-annotation-spacing': 'error', diff --git a/packages/eslint-plugin/src/configs/recommended-requiring-type-checking.ts b/packages/eslint-plugin/src/configs/recommended-requiring-type-checking.ts index 369d33d6687e..7e8e2047767e 100644 --- a/packages/eslint-plugin/src/configs/recommended-requiring-type-checking.ts +++ b/packages/eslint-plugin/src/configs/recommended-requiring-type-checking.ts @@ -21,6 +21,7 @@ export = { '@typescript-eslint/require-await': 'error', '@typescript-eslint/restrict-plus-operands': 'error', '@typescript-eslint/restrict-template-expressions': 'error', + '@typescript-eslint/strict-enums': 'error', '@typescript-eslint/unbound-method': 'error', }, }; diff --git a/packages/eslint-plugin/src/rules/index.ts b/packages/eslint-plugin/src/rules/index.ts index fb48ee5cadc2..e0969334ab83 100644 --- a/packages/eslint-plugin/src/rules/index.ts +++ b/packages/eslint-plugin/src/rules/index.ts @@ -117,6 +117,7 @@ import spaceBeforeBlocks from './space-before-blocks'; import spaceBeforeFunctionParen from './space-before-function-paren'; import spaceInfixOps from './space-infix-ops'; import strictBooleanExpressions from './strict-boolean-expressions'; +import strictEnums from './strict-enums'; import switchExhaustivenessCheck from './switch-exhaustiveness-check'; import tripleSlashReference from './triple-slash-reference'; import typeAnnotationSpacing from './type-annotation-spacing'; @@ -244,6 +245,7 @@ export default { 'space-before-function-paren': spaceBeforeFunctionParen, 'space-infix-ops': spaceInfixOps, 'strict-boolean-expressions': strictBooleanExpressions, + 'strict-enums': strictEnums, 'switch-exhaustiveness-check': switchExhaustivenessCheck, 'triple-slash-reference': tripleSlashReference, 'type-annotation-spacing': typeAnnotationSpacing, diff --git a/packages/eslint-plugin/src/rules/member-ordering.ts b/packages/eslint-plugin/src/rules/member-ordering.ts index 8c423b2f1044..b3a752aefa53 100644 --- a/packages/eslint-plugin/src/rules/member-ordering.ts +++ b/packages/eslint-plugin/src/rules/member-ordering.ts @@ -349,7 +349,7 @@ function getMemberName( * @param memberGroups the valid names to be validated. * @param orderConfig the current order to be validated. * - * @return Index of the matching member type in the order configuration. + * @returns Index of the matching member type in the order configuration. */ function getRankOrder( memberGroups: string[], @@ -542,7 +542,7 @@ export default util.createRule({ * @param groupOrder Group order to be validated. * @param supportsModifiers A flag indicating whether the type supports modifiers (scope or accessibility) or not. * - * @return Array of member groups or null if one of the groups is not correctly sorted. + * @returns Array of member groups or null if one of the groups is not correctly sorted. */ function checkGroupSort( members: Member[], @@ -594,7 +594,7 @@ export default util.createRule({ * @param members Members to be validated. * @param caseSensitive indicates if the alpha ordering is case sensitive or not. * - * @return True if all members are correctly sorted. + * @returns True if all members are correctly sorted. */ function checkAlphaSort( members: Member[], 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 cd28cfa16da7..eebd82f49396 100644 --- a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts +++ b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts @@ -128,7 +128,7 @@ export default util.createRule<[Options], MessageIds>({ /** * @brief checks that a union containing void is valid - * @return true if every member of the union is specified as a valid type in + * @returns true if every member of the union is specified as a valid type in * validUnionMembers, or is a valid generic type parametrized by void */ function isValidUnionType(node: TSESTree.TSUnionType): boolean { diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts new file mode 100644 index 000000000000..ebdd674c280c --- /dev/null +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -0,0 +1,496 @@ +import * as util from '../util'; +import { + getCallSignaturesOfType, + isSymbolFlagSet, + isTypeFlagSet, + unionTypeParts, +} from 'tsutils'; +import * as ts from 'typescript'; +import { TSESTree } from '@typescript-eslint/utils'; + +export type Options = []; +export type MessageIds = + | 'incorrectComparisonOperator' + | 'incorrectIncrement' + | 'mismatchedAssignment' + | 'mismatchedComparison' + | 'mismatchedFunctionArgument'; + +export default util.createRule({ + name: 'strict-enums', + meta: { + type: 'suggestion', + docs: { + description: 'Disallows the usage of unsafe enum patterns', + recommended: 'error', + requiresTypeChecking: true, + }, + messages: { + incorrectComparisonOperator: + 'You can only compare enum values (or variables that potentially have enum values) with the strict equality (===) and the strict inequality (!==) operators. (Enums are supposed to be resilient to reorganization, so you should only explicitly compare them.)', + incorrectIncrement: + 'You cannot increment or decrement an enum type. (Enums are supposed to be resilient to reorganization, so you should explicitly assign a new value instead.)', + mismatchedAssignment: + 'The type of the assignment does not match the declared enum type of the variable. In other words, you are trying to assign a Foo enum value to a variable with a Bar type. (Enums are supposed to be resilient to reorganization, so this kind of code can be dangerous.)', + mismatchedComparison: + 'The two things in the comparison do not have a shared enum type. You might be trying to use a number literal, like `Foo.Value1 === 1`. Or, you might be trying to use a disparate enum type, like `Foo.Value1 === Bar.Value1`. Either way, you need to use a value that corresponds to the correct enum, like `foo === Foo.Value1`, where `foo` is type `Foo`. (Enums are supposed to be resilient to reorganization, so this kind of code can be dangerous.)', + mismatchedFunctionArgument: + 'The argument in the function call does not match the declared enum type of the function signature. You might be trying to use a number literal, like `useFoo(1);`. Or, you might be trying to use a disparate enum type, like `useFoo(Bar.Value1)`. Either way, you need to use a value that corresponds to the correct enum, like `useFoo(Foo.Value1)`. (Enums are supposed to be resilient to reorganization, so this kind of code can be dangerous.)', + }, + schema: [ + { + type: 'object', + properties: {}, + additionalProperties: false, + }, + ], + }, + defaultOptions: [], + create(context) { + const parserServices = util.getParserServices(context); + const typeChecker = parserServices.program.getTypeChecker(); + + // ---------------- + // Helper functions + // ---------------- + + /** + * If passed an enum member, returns the type of the parent. Otherwise, + * returns itself. + */ + function getBaseEnumType(type: ts.Type): ts.Type { + const symbol = type.getSymbol(); + if (symbol === undefined) { + return type; + } + + if (!isSymbolFlagSet(symbol, ts.SymbolFlags.EnumMember)) { + return type; + } + + const { valueDeclaration } = symbol; + if (valueDeclaration === undefined) { + return type; + } + + const parentType = getTypeFromTSNode(valueDeclaration.parent); + if (parentType === undefined) { + return type; + } + + return parentType; + } + + /** + * A thing can have 0 or more enum types. For example: + * - 123 --> [] + * - {} --> [] + * - Fruit.Apple --> [Fruit] + * - Fruit.Apple | Vegetable.Lettuce --> [Fruit, Vegetable] + * - Fruit.Apple | Vegetable.Lettuce | 123 --> [Fruit, Vegetable] + */ + function getEnumTypes(type: ts.Type): Set { + const subTypes = unionTypeParts(type); + const enumSubTypes = subTypes.filter(subType => isEnum(subType)); + const baseEnumSubTypes = enumSubTypes.map(subType => + getBaseEnumType(subType), + ); + return new Set(baseEnumSubTypes); + } + + /** + * Given a set A and set B, return a set that contains only elements that are in + * both sets. + */ + function getIntersectingSet(a: Set, b: Set): Set { + const intersectingValues = [...a.values()].filter(value => b.has(value)); + return new Set(intersectingValues); + } + + /** + * Given a call expression like `foo(1)`, derive the corresponding + * parameter/argument types of the "real" foo function (as opposed to + * looking at the arguments of the call expression itself). + * + * @returns A `Map` of argument index number to a `Set` of one or more + */ + function getRealFunctionParameterTypes( + node: TSESTree.CallExpression, + ): Map> { + const functionIdentifier = node.callee; + const functionType = getTypeFromNode(functionIdentifier); + if (functionType === undefined) { + return new Map(); + } + + /** + * There can be potentially multiple signatures for the same function, so + * we have to iterate over all of them. + */ + const signatures = getCallSignaturesOfType(functionType); + + /** + * Indexed by parameter number. For example, the first function parameter + * type names are stored at index 0. + */ + const paramNumToTypesMap = new Map>(); + + for (const signature of signatures) { + for (let i = 0; i < signature.parameters.length; i++) { + const parameter = signature.parameters[i]; + if (parameter.valueDeclaration === undefined) { + continue; + } + + const parameterType = typeChecker.getTypeOfSymbolAtLocation( + parameter, + parameter.valueDeclaration, + ); + + let typeSet = paramNumToTypesMap.get(i); + if (typeSet === undefined) { + typeSet = new Set(); + paramNumToTypesMap.set(i, typeSet); + } + + typeSet.add(parameterType); + } + } + + return paramNumToTypesMap; + } + + function getTypeFromNode(node: TSESTree.Node): ts.Type | undefined { + const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); + return getTypeFromTSNode(tsNode); + } + + function getTypeFromTSNode(tsNode: ts.Node): ts.Type | undefined { + /** + * Skip declarations like: + * + * ```ts + * let [, b] = myArray; + * ``` + * + * Situations like this will cause a runtime error in the + * "getTypeAtLocation" method below. + * + * Someone should probably fix the getTypeAtLocation method so that it + * does not cause runtime errors. + */ + // @ts-expect-error The type definitions for this are wrong and its over + // my pay grade to change them + if (!tsNode.symbol) { + return undefined; + } + + return typeChecker.getTypeAtLocation(tsNode); + } + + function getTypeName(type: ts.Type): string { + return util.getTypeName(typeChecker, type); + } + + function hasEnumTypes(type: ts.Type): boolean { + const enumTypes = getEnumTypes(type); + return enumTypes.size > 0; + } + + function typeIncludesNull(type: ts.Type): boolean { + return typeIncludesTypeName(type, 'null'); + } + + function typeIncludesTypeName(type: ts.Type, typeName: string): boolean { + const subTypes = unionTypeParts(type); + const subTypeNames = subTypes.map(subType => getTypeName(subType)); + return subTypeNames.includes(typeName); + } + + function typeIncludesUndefined(type: ts.Type): boolean { + return typeIncludesTypeName(type, 'undefined'); + } + + function typeSetHasEnum(typeSet: Set): boolean { + for (const type of typeSet.values()) { + const subTypes = unionTypeParts(type); + for (const subType of subTypes) { + if (isEnum(subType)) { + return true; + } + } + } + + return false; + } + + function isAssigningNonEnumValueToEnumVariable( + leftType: ts.Type, + rightType: ts.Type, + ): boolean { + const leftEnumTypes = getEnumTypes(leftType); + if (leftEnumTypes.size === 0) { + // This is not an enum assignment + return false; + } + + /** + * As a special case, allow assignment of null and undefined in all + * circumstances, since the TypeScript compiler should properly type-check + * this. + */ + if (typeIncludesNull(rightType) || typeIncludesUndefined(rightType)) { + return false; + } + + const rightEnumTypes = getEnumTypes(rightType); + const intersectingTypes = getIntersectingSet( + leftEnumTypes, + rightEnumTypes, + ); + return intersectingTypes.size === 0; + } + + function isEnum(type: ts.Type): boolean { + return isTypeFlagSet(type, ts.TypeFlags.EnumLiteral); + } + + function isMismatchedEnumFunctionArgument( + i: number, + type: ts.Type, + paramNumToTypesMap: Map>, + ): boolean { + const typeSet = paramNumToTypesMap.get(i); + if (typeSet === undefined) { + // This should never happen + return false; + } + + // First, ignore all function arguments that don't have any enum types + if (!typeSetHasEnum(typeSet)) { + return false; + } + + /** + * Allow function calls that exactly match the function type, like the + * following: + * + * ```ts + * function useApple(apple: Fruit.Apple) {} + * useApple(Fruit.Apple); + * ``` + */ + if (typeSet.has(type)) { + return false; + } + + /** + * Allow function calls that have a base enum that match the function + * type, like the following: + * + * ```ts + * function useFruit(apple: Fruit) {} + * useFruit(Fruit.Apple); + * ``` + */ + const baseEnumType = getBaseEnumType(type); + if (typeSet.has(baseEnumType)) { + return false; + } + + /** + * Allow function calls that match function types with a union, like the + * following: + * + * ```ts + * function useFruit(fruit: Fruit | null) {} + * useFruit(Fruit.Apple); + * ``` + */ + for (const paramType of typeSet.values()) { + if (!paramType.isUnion()) { + continue; + } + + /** + * Naively, you would expect the parts of a "Fruit | null" type to be: + * [Fruit, null] + * + * Instead, they are actually: + * [Fruit.Apple, Fruit.Banana, Fruit.Pear, null] + * + * Thus, we must get the base types. + */ + const subTypes = unionTypeParts(paramType); + + for (const subType of subTypes) { + const baseEnumTypeSubType = getBaseEnumType(subType); + if (baseEnumType === baseEnumTypeSubType) { + return false; + } + } + } + + return true; + } + + // ------------------ + // AST node callbacks + // ------------------ + + return { + /** When something is assigned to a variable. */ + AssignmentExpression(node): void { + const leftType = getTypeFromNode(node.left); + if (leftType === undefined) { + return; + } + + const rightType = getTypeFromNode(node.right); + if (rightType === undefined) { + return; + } + + if (isAssigningNonEnumValueToEnumVariable(leftType, rightType)) { + context.report({ node, messageId: 'mismatchedAssignment' }); + } + }, + + /** When a comparison between two things happen. */ + BinaryExpression(node): void { + const leftType = getTypeFromNode(node.left); + if (leftType === undefined) { + return; + } + + const rightType = getTypeFromNode(node.right); + if (rightType === undefined) { + return; + } + + const leftEnumTypes = getEnumTypes(leftType); + const rightEnumTypes = getEnumTypes(rightType); + if (leftEnumTypes.size === 0 && rightEnumTypes.size === 0) { + // This is not an enum comparison + return; + } + + /** + * Disallow mismatched comparisons, like the following: + * + * ```ts + * if (fruit === 0) {} + * ``` + */ + const intersectingTypes = getIntersectingSet( + leftEnumTypes, + rightEnumTypes, + ); + if (intersectingTypes.size === 0) { + context.report({ node, messageId: 'mismatchedComparison' }); + } + + /** + * Only allow the strict equality and strict inequality operators for + * enums comparisons. + */ + if (node.operator !== '===' && node.operator !== '!==') { + context.report({ node, messageId: 'incorrectComparisonOperator' }); + } + }, + + /** When a function is invoked. */ + CallExpression(node): void { + const paramNumToTypesMap = getRealFunctionParameterTypes(node); + + /** + * Iterate through the arguments provided to the call function and cross + * reference their types to the types of the "real" function parameters. + */ + for (let i = 0; i < node.arguments.length; i++) { + const argument = node.arguments[i]; + const argumentType = getTypeFromNode(argument); + if (argumentType === undefined) { + continue; + } + + /** + * Disallow mismatched function calls, like the following: + * + * ```ts + * function useFruit(fruit: Fruit) {} + * useFruit(0); + * ``` + */ + if ( + isMismatchedEnumFunctionArgument( + i, + argumentType, + paramNumToTypesMap, + ) + ) { + context.report({ node, messageId: 'mismatchedFunctionArgument' }); + } + } + }, + + /** When a unary operator is invoked. */ + UpdateExpression(node): void { + const argumentType = getTypeFromNode(node.argument); + if (argumentType === undefined) { + return; + } + + /** + * Disallow using enums with unary operators, like the following: + * + * ```ts + * const fruit = Fruit.Apple; + * fruit++; + * ``` + */ + if (hasEnumTypes(argumentType)) { + context.report({ node, messageId: 'incorrectIncrement' }); + } + }, + + /** When a new variable is created. */ + VariableDeclaration(node): void { + for (const declaration of node.declarations) { + const leftTSNode = + parserServices.esTreeNodeToTSNodeMap.get(declaration); + + /** + * Allow enum declarations without an initializer, like the following: + * + * ```ts + * let fruit: Fruit; + * if (something()) { + * fruit = Fruit.Apple; + * } else { + * fruit = Fruit.Banana; + * } + * ``` + */ + if (leftTSNode.initializer === undefined) { + continue; + } + + const leftType = getTypeFromNode(declaration); + if (leftType === undefined) { + continue; + } + + const rightType = getTypeFromTSNode(leftTSNode.initializer); + if (rightType === undefined) { + continue; + } + + if (isAssigningNonEnumValueToEnumVariable(leftType, rightType)) { + context.report({ node, messageId: 'mismatchedAssignment' }); + } + } + }, + }; + }, +}); diff --git a/packages/eslint-plugin/tests/rules/strict-enums.test.ts b/packages/eslint-plugin/tests/rules/strict-enums.test.ts new file mode 100644 index 000000000000..8f10a0e61fa7 --- /dev/null +++ b/packages/eslint-plugin/tests/rules/strict-enums.test.ts @@ -0,0 +1,1135 @@ +import { + InvalidTestCase, + ValidTestCase, +} from '@typescript-eslint/utils/src/ts-eslint'; +import rule, { MessageIds } from '../../src/rules/strict-enums'; +import { getFixturesRootDir, RuleTester } from '../RuleTester'; + +const rootDir = getFixturesRootDir(); +const ruleTester = new RuleTester({ + parserOptions: { + ecmaVersion: 2015, + tsconfigRootDir: rootDir, + project: './tsconfig.json', + }, + parser: '@typescript-eslint/parser', +}); + +const valid: ValidTestCase[] = []; +const invalid: InvalidTestCase[] = []; + +/** A number enum. */ +const fruitEnumDefinition = ` +enum Fruit { + Apple, + Banana, + Pear, +} +`; + +/** + * A string enum. + * + * String enums are only used for comparison tests, since the TypeScript + * compiler does a good job of ensuring safety for variable assignment and usage + * in functions. + */ +const vegetableEnumDefinition = ` +enum Vegetable { + Lettuce = 'lettuce', + Carrot = 'carrot', + Celery = 'celery', +} +`; + +/** A different number enum. */ +const fruit2EnumDefinition = ` +enum Fruit2 { + Apple2, + Banana2, + Pear2, +} +`; + +/** A different string enum. */ +const vegetable2EnumDefinition = ` +enum Vegetable2 { + Lettuce2 = 'lettuce2', + Carrot2 = 'carrot2', + Celery2 = 'celery2', +} +`; + +/** A function that takes a number enum. */ +const fruitFunctionDefinition = + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit) {} +`; + +/** A function that takes a number enum literal. */ +const fruitLiteralFunctionDefinition = + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple) {} +`; + +/** A function that takes a number enum with a default argument. */ +const fruitFunctionWithDefaultArgDefinition = + fruitEnumDefinition + + ` +function useFruit(fruit = Fruit.Apple) {} +`; + +/** A function that takes a number enum literal with a default argument. */ +const fruitLiteralFunctionWithDefaultArgDefinition = + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} +`; + +/** A function that takes a number enum with a union. */ +const fruitFunctionWithUnionDefinition = + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit | null) {} +`; + +/** A function that takes a number enum with a union and a default argument. */ +const fruitFunctionWithUnionAndDefaultDefinition = + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit | null = Fruit.Apple) {} +`; + +/** A function that takes a number enum literal with a union. */ +const fruitLiteralFunctionWithUnionDefinition = + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | null) {} +`; + +/** A function that takes a number enum literal with a union and a default argument. */ +const fruitLiteralFunctionWithUnionAndDefaultDefinition = + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} +`; + +/** A function that takes a number enum literal with a union including two enum types. */ +const fruitLiteralFunctionWithComplexUnionDefinition = + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} +`; + +// ----------------- +// DECLARATION TESTS +// ----------------- + +valid.push({ + name: 'Declaring an enum with an empty initializer', + code: + fruitEnumDefinition + + ` +let fruit: Fruit; +if (true) { + fruit = Fruit.Apple; +} else { + fruit = Fruit.Banana; +} + `, +}); + +// ---------------- +// ASSIGNMENT TESTS +// ---------------- + +valid.push({ + name: 'Assigning a number enum literal to a number enum (with type-inference)', + code: + fruitEnumDefinition + + ` +const fruit = Fruit.Apple; + `, +}); + +valid.push({ + name: 'Assigning a number enum literal to a number enum (without type-inference)', + code: + fruitEnumDefinition + + ` +const fruit: Fruit = Fruit.Apple; + `, +}); + +valid.push({ + name: 'Assigning a number enum value to a variable of the same type with const', + code: + fruitEnumDefinition + + ` +const apple = Fruit.Apple; +const fruit: Fruit = apple; + `, +}); + +invalid.push({ + name: 'Assigning a number literal to a number enum with const', + code: + fruitEnumDefinition + + ` +const fruit: Fruit = 0; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +valid.push({ + name: 'Assigning a number enum value to a variable of the same type with let', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Apple; +fruit = Fruit.Banana; + `, +}); + +invalid.push({ + name: 'Assigning a number literal to a number enum with let', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Apple; +fruit = 1; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +invalid.push({ + name: 'Assigning an enum parent to a number enum', + code: + fruitEnumDefinition + + ` +const fruit: Fruit = Fruit; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +invalid.push({ + name: 'Assigning a mismatched enum value to a number enum', + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` +const fruit: Fruit = Fruit2.Apple2; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +valid.push({ + name: 'Assigning a number enum literal to a variable with a union type of "number enum | null" with const', + code: + fruitEnumDefinition + + ` +const fruit: Fruit | null = Fruit.Apple; + `, +}); + +valid.push({ + name: 'Assigning a null value to a variable with a union type of "number enum | null" with const', + code: + fruitEnumDefinition + + ` +const fruit: Fruit | null = null; + `, +}); + +invalid.push({ + name: 'Assigning a number literal to a variable with a union type of "number enum | null" with const', + code: + fruitEnumDefinition + + ` +const fruit: Fruit | null = 0; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +valid.push({ + name: 'Assigning a number enum literal to a variable with a union type of "number enum | null" with let', + code: + fruitEnumDefinition + + ` +let fruit: Fruit | null = null; +fruit = Fruit.Apple; + `, +}); + +valid.push({ + name: 'Assigning a null value to a variable with a union type of "number enum | null" with let', + code: + fruitEnumDefinition + + ` +let fruit: Fruit | null = Fruit.Apple; +fruit = null; + `, +}); + +invalid.push({ + name: 'Assigning a number literal to a variable with a union type of "number enum | null" with let', + code: + fruitEnumDefinition + + ` +let fruit: Fruit | null = null; +fruit = 0; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +invalid.push({ + name: 'Assigning a enum literal to a variable with a union type of "number enum | number"', + code: + fruitEnumDefinition + + ` +declare const fruit: Fruit | number; +const fruitCopy: Fruit = fruit; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +valid.push({ + name: 'Assignment to variables with a composition type that includes individual enum values', + code: ` +enum Foo { + A = 1, + B = 2, + C = 3, + D = 4, +} + +declare const foo: Foo; +declare const fooSubset: Foo.A | Foo.B | Foo.C; +const x: Foo = fooSubset; +const y: Foo.A | Foo.B | Foo.C = fooSubset; +const z: Foo.A | Foo.B | Foo.C | Foo.D = foo; + `, +}); + +/** + * Intersection enum types are not checked by this rule. Even though doing this + * would almost certainly be a bad idea, a programmer would have to go to great + * lengths to do this, so we assume that the programmer knows what they are + * doing and allow it. + */ +valid.push({ + name: 'Assignment to a variable with a intersection enum type', + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` +const foo: Fruit & Fruit2 = Fruit.Apple; + `, +}); + +// ------------------ +// INCREMENTING TESTS +// ------------------ + +valid.push({ + name: 'Incrementing a number (postfix)', + code: + fruitEnumDefinition + + ` +let fruit = 0; +fruit++; + `, +}); + +invalid.push({ + name: 'Incrementing a number enum value (postfix)', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Apple; +fruit++; + `, + errors: [{ messageId: 'incorrectIncrement' }], +}); + +valid.push({ + name: 'Decrementing a number (postfix)', + code: + fruitEnumDefinition + + ` +let fruit = 1; +fruit--; + `, +}); + +invalid.push({ + name: 'Decrementing a number enum value (postfix)', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Banana; +fruit--; + `, + errors: [{ messageId: 'incorrectIncrement' }], +}); + +valid.push({ + name: 'Incrementing a number (prefix)', + code: + fruitEnumDefinition + + ` +let fruit = 0; +++fruit; + `, +}); + +invalid.push({ + name: 'Incrementing a number enum value (prefix)', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Apple; +++fruit; + `, + errors: [{ messageId: 'incorrectIncrement' }], +}); + +valid.push({ + name: 'Decrementing a number (prefix)', + code: + fruitEnumDefinition + + ` +let fruit = 1; +--fruit + `, +}); + +invalid.push({ + name: 'Decrementing a number enum value (prefix)', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Banana; +--fruit; + `, + errors: [{ messageId: 'incorrectIncrement' }], +}); + +valid.push({ + name: 'Incrementing a number (assignment operator)', + code: + fruitEnumDefinition + + ` +let fruit = 0; +fruit += 1; + `, +}); + +invalid.push({ + name: 'Incrementing a number enum value (assignment operator)', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Apple; +fruit += 1; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +valid.push({ + name: 'Decrementing a number (assignment operator)', + code: + fruitEnumDefinition + + ` +let fruit = 1; +fruit -= 1; + `, +}); + +invalid.push({ + name: 'Decrementing a number enum value (assignment operator)', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Banana; +fruit -= 1; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +// ---------------- +// COMPARISON TESTS +// ---------------- + +valid.push({ + name: 'Comparing a number with a number', + code: + fruitEnumDefinition + + ` +if (1 === 2) { +} + `, +}); + +valid.push({ + name: 'Comparing a number enum literal with an enum literal of the same type', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple === Fruit.Banana) { +} + `, +}); + +valid.push({ + name: 'Comparing a number enum value with an enum literal of the same type', + code: + fruitEnumDefinition + + ` +const fruit = Fruit.Apple; +if (fruit === Fruit.Banana) { +} + `, +}); + +valid.push({ + name: 'Comparing a string enum value with an enum literal of the same type', + code: + vegetableEnumDefinition + + ` +const vegetable = Vegetable.Lettuce; +if (vegetable === Vegetable.Carrot) { +} + `, +}); + +valid.push({ + name: 'Comparing a number enum value with a value of the same type', + code: + fruitEnumDefinition + + ` +const fruit1 = Fruit.Apple; +const fruit2 = Fruit.Banana; +if (fruit1 === fruit2) { +} + `, +}); + +valid.push({ + name: 'Comparing a string enum value with a value of the same type', + code: + vegetableEnumDefinition + + ` +const vegetable1 = Vegetable.Lettuce; +const vegetable2 = Vegetable.Carrot; +if (vegetable1 === vegetable2) { +} + `, +}); + +invalid.push({ + name: 'Comparing a number enum literal with a number literal', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple === 1) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a string enum literal with a string literal', + code: + vegetableEnumDefinition + + ` +if (Vegetable.Lettuce === 'carrot') { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a number literal with a number enum literal', + code: + fruitEnumDefinition + + ` +if (1 === Fruit.Apple) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a string literal with a string enum literal', + code: + vegetableEnumDefinition + + ` +if ('carrot' === Vegetable.Lettuce) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a number enum value with a number literal', + code: + fruitEnumDefinition + + ` +const fruit = Fruit.Apple; +if (fruit === 1) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a string enum value with a string literal', + code: + vegetableEnumDefinition + + ` +const vegetable = Vegetable.Lettuce; +if (vegetable === 'carrot') { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a number literal with an enum value', + code: + fruitEnumDefinition + + ` +const fruit = Fruit.Apple; +if (1 === fruit) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a string literal with an enum value', + code: + vegetableEnumDefinition + + ` +const vegetable = Vegetable.Lettuce; +if ('carrot' === vegetable) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a number enum literal with a different enum literal', + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` +if (Fruit.Apple === Fruit2.Apple2) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a string enum literal with a different enum literal', + code: + vegetableEnumDefinition + + vegetable2EnumDefinition + + ` +if (Vegetable.Lettuce === Vegetable2.Lettuce2) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a number enum value with a different enum literal', + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` +const fruit = Fruit.Apple; +if (fruit === Fruit2.Apple2) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a string enum value with a different enum literal', + code: + vegetableEnumDefinition + + vegetable2EnumDefinition + + ` +const vegetable = Vegetable.Lettuce; +if (vegetable === Vegetable2.Lettuce2) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +valid.push({ + name: 'Comparing a number enum literal value to an enum literal value of the same type (with strict inequality)', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple !== Fruit.Banana) { +} + `, +}); + +valid.push({ + name: 'Comparing a string enum literal value to an enum literal value of the same type (with strict inequality)', + code: + vegetableEnumDefinition + + ` +if (Vegetable.Lettuce !== Vegetable.Carrot) { +} + `, +}); + +invalid.push({ + name: 'Comparing a number enum literal value to an enum literal value of the same type (with loose equality)', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple == Fruit.Banana) { +} + `, + errors: [{ messageId: 'incorrectComparisonOperator' }], +}); + +invalid.push({ + name: 'Comparing a string enum literal value to an enum literal value of the same type (with loose equality)', + code: + vegetableEnumDefinition + + ` +if (Vegetable.Lettuce == Vegetable.Carrot) { +} + `, + errors: [{ messageId: 'incorrectComparisonOperator' }], +}); + +invalid.push({ + name: 'Comparing a number enum literal value to an enum literal value of the same type (with loose inequality)', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple != Fruit.Banana) { +} + `, + errors: [{ messageId: 'incorrectComparisonOperator' }], +}); + +invalid.push({ + name: 'Comparing a string enum literal value to an enum literal value of the same type (with loose inequality)', + code: + vegetableEnumDefinition + + ` +if (Vegetable.Lettuce != Vegetable.Carrot) { +} + `, + errors: [{ messageId: 'incorrectComparisonOperator' }], +}); + +invalid.push({ + name: 'Comparing a number enum literal value to an enum literal value of the same type (with greater than)', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple > Fruit.Banana) { +} + `, + errors: [{ messageId: 'incorrectComparisonOperator' }], +}); + +invalid.push({ + name: 'Comparing a number enum literal value to an enum literal value of the same type (with less than)', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple < Fruit.Banana) { +} + `, + errors: [{ messageId: 'incorrectComparisonOperator' }], +}); + +// -------------- +// FUNCTION TESTS +// -------------- + +valid.push({ + name: 'Using a normal function without any enums', + code: ` +function useNumber(num: number) {} +useNumber(0); + `, +}); + +valid.push({ + name: 'Using a number enum literal as a function argument', + code: + fruitFunctionDefinition + + ` +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value as a function argument', + code: + fruitFunctionDefinition + + ` +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal as a function argument', + code: + fruitFunctionDefinition + + ` + useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal as a function argument (with an "enum literal" argument type)', + code: + fruitLiteralFunctionDefinition + + ` + useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value as a function argument (with an "enum literal" argument type)', + code: + fruitLiteralFunctionDefinition + + ` +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal as a function argument (with an "enum literal" argument type)', + code: + fruitLiteralFunctionDefinition + + ` +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal as a function argument (with a default function argument)', + code: + fruitFunctionWithDefaultArgDefinition + + ` +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value as a function argument (with a default function argument)', + code: + fruitFunctionWithDefaultArgDefinition + + ` +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal as a function argument (with a default function argument)', + code: + fruitFunctionWithDefaultArgDefinition + + ` +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal as a function argument (with a "number literal" arument type + default)', + code: + fruitLiteralFunctionWithDefaultArgDefinition + + ` +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value as a function argument (with a "number literal" arument type + default)', + code: + fruitLiteralFunctionWithDefaultArgDefinition + + ` +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal as a function argument (with a "number literal" arument type + default)', + code: + fruitLiteralFunctionWithDefaultArgDefinition + + ` +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal as a function argument (with a "number enum | null" argument type)', + code: + fruitFunctionWithUnionDefinition + + ` +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value as a function argument (with a "number enum | null" argument type)', + code: + fruitFunctionWithUnionDefinition + + ` +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +valid.push({ + name: 'Using a null literal as a function argument (with a "number enum | null" argument type)', + code: + fruitFunctionWithUnionDefinition + + ` +useFruit(null); + `, +}); + +valid.push({ + name: 'Using a null value as a function argument (with a "number enum | null" argument type)', + code: + fruitFunctionWithUnionDefinition + + ` +const fruit = null; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal as a function argument (with a "number enum | null" function argument)', + code: + fruitFunctionWithUnionDefinition + + ` +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal as a function argument (with a "number enum | null" argument type + default)', + code: + fruitFunctionWithUnionAndDefaultDefinition + + ` +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value as a function argument (with a "number enum | null" argument type + default)', + code: + fruitFunctionWithUnionAndDefaultDefinition + + ` +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +valid.push({ + name: 'Using a null literal as a function argument (with a "number enum | null" argument type + default)', + code: + fruitFunctionWithUnionAndDefaultDefinition + + ` +useFruit(null); + `, +}); + +valid.push({ + name: 'Using a null value as a function argument (with a "number enum | null" argument type + default)', + code: + fruitFunctionWithUnionAndDefaultDefinition + + ` +const fruit = null; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal as a function argument (with a "number enum | null" function argument + default)', + code: + fruitFunctionWithUnionAndDefaultDefinition + + ` +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal as a function argument (with a "number enum literal | null" argument type)', + code: + fruitLiteralFunctionWithUnionDefinition + + ` +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value as a function argument (with a "number enum literal | null" argument type)', + code: + fruitLiteralFunctionWithUnionDefinition + + ` +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +valid.push({ + name: 'Using a null literal as a function argument (with a "number enum literal | null" argument type)', + code: + fruitLiteralFunctionWithUnionDefinition + + ` +useFruit(null); + `, +}); + +valid.push({ + name: 'Using a null value as a function argument (with a "number enum literal | null" argument type)', + code: + fruitLiteralFunctionWithUnionDefinition + + ` +const fruit = null; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal as a function argument (with a "number enum literal | null" function argument)', + code: + fruitLiteralFunctionWithUnionDefinition + + ` +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal as a function argument (with a "number enum literal | null" argument type + default)', + code: + fruitLiteralFunctionWithUnionAndDefaultDefinition + + ` +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value as a function argument (with a "number enum literal | null" argument type + default)', + code: + fruitLiteralFunctionWithUnionAndDefaultDefinition + + ` +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +valid.push({ + name: 'Using a null literal as a function argument (with a "number enum literal | null" argument type + default)', + code: + fruitLiteralFunctionWithUnionAndDefaultDefinition + + ` +useFruit(null); + `, +}); + +valid.push({ + name: 'Using a null value as a function argument (with a "number enum literal | null" argument type + default)', + code: + fruitLiteralFunctionWithUnionAndDefaultDefinition + + ` +const fruit = null; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal as a function argument (with a "number enum literal | null" function argument + default)', + code: + fruitLiteralFunctionWithUnionAndDefaultDefinition + + ` +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal as a function argument (with a "number enum literal | number enum literal | null" argument type)', + code: + fruitLiteralFunctionWithComplexUnionDefinition + + ` +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value as a function argument (with a "number enum literal | number enum literal | null" argument type)', + code: + fruitLiteralFunctionWithComplexUnionDefinition + + ` +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +valid.push({ + name: 'Using a null literal as a function argument (with a "number enum literal | number enum literal | null" argument type)', + code: + fruitLiteralFunctionWithComplexUnionDefinition + + ` +useFruit(null); + `, +}); + +valid.push({ + name: 'Using a null value as a function argument (with a "number enum literal | number enum literal | null" argument type)', + code: + fruitLiteralFunctionWithComplexUnionDefinition + + ` +const fruit = null; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal as a function argument (with a "number enum literal | number enum literal | null" argument type)', + code: + fruitLiteralFunctionWithComplexUnionDefinition + + ` +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +// --------- +// END TESTS +// --------- + +ruleTester.run('strict-enums', rule, { + valid, + invalid, +}); From 094c90e59bec74a7d86d2fbe3c0de03719c346fd Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Thu, 28 Apr 2022 13:55:43 -0400 Subject: [PATCH 02/88] feat(eslint-plugin): [strict-enums] adding check for null/undefined --- .../eslint-plugin/src/rules/strict-enums.ts | 37 +++++++++++-------- .../tests/rules/strict-enums.test.ts | 20 ++++++++++ 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 82a2ee3b1d52..de5f6efb149d 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -175,20 +175,6 @@ export default util.createRule({ return enumTypes.size > 0; } - function typeIncludesNull(type: ts.Type): boolean { - return typeIncludesTypeName(type, 'null'); - } - - function typeIncludesTypeName(type: ts.Type, typeName: string): boolean { - const subTypes = unionTypeParts(type); - const subTypeNames = subTypes.map(subType => getTypeName(subType)); - return subTypeNames.includes(typeName); - } - - function typeIncludesUndefined(type: ts.Type): boolean { - return typeIncludesTypeName(type, 'undefined'); - } - function typeSetHasEnum(typeSet: Set): boolean { for (const type of typeSet.values()) { const subTypes = unionTypeParts(type); @@ -217,7 +203,7 @@ export default util.createRule({ * circumstances, since the TypeScript compiler should properly type-check * this. */ - if (typeIncludesNull(rightType) || typeIncludesUndefined(rightType)) { + if (isNullOrUndefined(rightType)) { return false; } @@ -233,6 +219,16 @@ export default util.createRule({ return isTypeFlagSet(type, ts.TypeFlags.EnumLiteral); } + /** + * Returns true if one or more of the provided types are null or undefined. + */ + function isNullOrUndefined(...types: ts.Type[]): boolean { + return types.some(type => { + const typeName = getTypeName(type); + return typeName === 'null' || typeName === 'undefined'; + }); + } + function isMismatchedEnumFunctionArgument( i: number, type: ts.Type, @@ -340,6 +336,17 @@ export default util.createRule({ return; } + /** + * As a special exception, allow comparisons to literal null or literal + * undefined. + * + * The TypeScript compiler should handle these cases properly, so the + * lint rule is unneeded. + */ + if (isNullOrUndefined(leftType, rightType)) { + return; + } + /** * Disallow mismatched comparisons, like the following: * diff --git a/packages/eslint-plugin/tests/rules/strict-enums.test.ts b/packages/eslint-plugin/tests/rules/strict-enums.test.ts index 28c1020a579b..075f54b7ee89 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums.test.ts @@ -486,6 +486,26 @@ if (1 === 2) { `, }); +valid.push({ + name: 'Comparing a number enum literal to literal undefined', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple === undefined) { +} + `, +}); + +valid.push({ + name: 'Comparing a number enum literal to literal null', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple === null) { +} + `, +}); + valid.push({ name: 'Comparing a number enum literal with an enum literal of the same type', code: From 311b1f8e257f82be6b01049700ee4f356d76d6b4 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Thu, 28 Apr 2022 14:58:58 -0400 Subject: [PATCH 03/88] feat(eslint-plugin): [strict-enums] refactoring tests to separate files --- .../rules/strict-enums-assignment.test.ts | 202 +++ .../rules/strict-enums-comparison.test.ts | 356 +++++ .../rules/strict-enums-declaration.test.ts | 41 + .../rules/strict-enums-functions.test.ts | 441 +++++++ .../rules/strict-enums-incrementing.test.ts | 140 ++ .../tests/rules/strict-enums.test.ts | 1168 ----------------- .../eslint-plugin/tests/rules/strict-enums.ts | 29 + 7 files changed, 1209 insertions(+), 1168 deletions(-) create mode 100644 packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts create mode 100644 packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts create mode 100644 packages/eslint-plugin/tests/rules/strict-enums-declaration.test.ts create mode 100644 packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts create mode 100644 packages/eslint-plugin/tests/rules/strict-enums-incrementing.test.ts delete mode 100644 packages/eslint-plugin/tests/rules/strict-enums.test.ts create mode 100644 packages/eslint-plugin/tests/rules/strict-enums.ts diff --git a/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts new file mode 100644 index 000000000000..92d5bf69d74d --- /dev/null +++ b/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts @@ -0,0 +1,202 @@ +import { + InvalidTestCase, + ValidTestCase, +} from '@typescript-eslint/utils/src/ts-eslint'; +import rule, { MessageIds } from '../../src/rules/strict-enums'; +import { + fruit2EnumDefinition, + fruitEnumDefinition, + ruleTester, +} from './strict-enums'; + +const valid: ValidTestCase[] = []; +const invalid: InvalidTestCase[] = []; + +valid.push({ + name: 'Assigning a number enum literal to a number enum (with type-inference)', + code: + fruitEnumDefinition + + ` +const fruit = Fruit.Apple; + `, +}); + +valid.push({ + name: 'Assigning a number enum literal to a number enum (without type-inference)', + code: + fruitEnumDefinition + + ` +const fruit: Fruit = Fruit.Apple; + `, +}); + +valid.push({ + name: 'Assigning a number enum value to a variable of the same type with const', + code: + fruitEnumDefinition + + ` +const apple = Fruit.Apple; +const fruit: Fruit = apple; + `, +}); + +invalid.push({ + name: 'Assigning a number literal to a number enum with const', + code: + fruitEnumDefinition + + ` +const fruit: Fruit = 0; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +valid.push({ + name: 'Assigning a number enum value to a variable of the same type with let', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Apple; +fruit = Fruit.Banana; + `, +}); + +invalid.push({ + name: 'Assigning a number literal to a number enum with let', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Apple; +fruit = 1; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +invalid.push({ + name: 'Assigning an enum parent to a number enum', + code: + fruitEnumDefinition + + ` +const fruit: Fruit = Fruit; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +invalid.push({ + name: 'Assigning a mismatched enum value to a number enum', + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` +const fruit: Fruit = Fruit2.Apple2; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +valid.push({ + name: 'Assigning a number enum literal to a variable with a union type of "number enum | null" with const', + code: + fruitEnumDefinition + + ` +const fruit: Fruit | null = Fruit.Apple; + `, +}); + +valid.push({ + name: 'Assigning a null value to a variable with a union type of "number enum | null" with const', + code: + fruitEnumDefinition + + ` +const fruit: Fruit | null = null; + `, +}); + +invalid.push({ + name: 'Assigning a number literal to a variable with a union type of "number enum | null" with const', + code: + fruitEnumDefinition + + ` +const fruit: Fruit | null = 0; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +valid.push({ + name: 'Assigning a number enum literal to a variable with a union type of "number enum | null" with let', + code: + fruitEnumDefinition + + ` +let fruit: Fruit | null = null; +fruit = Fruit.Apple; + `, +}); + +valid.push({ + name: 'Assigning a null value to a variable with a union type of "number enum | null" with let', + code: + fruitEnumDefinition + + ` +let fruit: Fruit | null = Fruit.Apple; +fruit = null; + `, +}); + +invalid.push({ + name: 'Assigning a number literal to a variable with a union type of "number enum | null" with let', + code: + fruitEnumDefinition + + ` +let fruit: Fruit | null = null; +fruit = 0; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +invalid.push({ + name: 'Assigning a enum literal to a variable with a union type of "number enum | number"', + code: + fruitEnumDefinition + + ` +declare const fruit: Fruit | number; +const fruitCopy: Fruit = fruit; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +valid.push({ + name: 'Assignment to variables with a composition type that includes individual enum values', + code: ` +enum Foo { + A = 1, + B = 2, + C = 3, + D = 4, +} + +declare const foo: Foo; +declare const fooSubset: Foo.A | Foo.B | Foo.C; +const x: Foo = fooSubset; +const y: Foo.A | Foo.B | Foo.C = fooSubset; +const z: Foo.A | Foo.B | Foo.C | Foo.D = foo; + `, +}); + +/** + * Intersection enum types are not checked by this rule. Even though doing this + * would almost certainly be a bad idea, a programmer would have to go to great + * lengths to do this, so we assume that the programmer knows what they are + * doing and allow it. + */ +valid.push({ + name: 'Assignment to a variable with a intersection enum type', + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` +const foo: Fruit & Fruit2 = Fruit.Apple; + `, +}); + +ruleTester.run('strict-enums-assignment', rule, { + valid, + invalid, +}); diff --git a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts new file mode 100644 index 000000000000..ce99a547387b --- /dev/null +++ b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts @@ -0,0 +1,356 @@ +import { + InvalidTestCase, + ValidTestCase, +} from '@typescript-eslint/utils/src/ts-eslint'; +import rule, { MessageIds } from '../../src/rules/strict-enums'; +import { + fruit2EnumDefinition, + fruitEnumDefinition, + ruleTester, +} from './strict-enums'; + +const valid: ValidTestCase[] = []; +const invalid: InvalidTestCase[] = []; + +/** + * A string enum. + * + * String enums are only used for comparison tests, since the TypeScript + * compiler does a good job of ensuring safety for string enum variable + * assignment and usage in functions. + */ +const vegetableEnumDefinition = ` + enum Vegetable { + Lettuce = 'lettuce', + Carrot = 'carrot', + Celery = 'celery', + } + `; + +/** A different string enum. */ +const vegetable2EnumDefinition = ` +enum Vegetable2 { + Lettuce2 = 'lettuce2', + Carrot2 = 'carrot2', + Celery2 = 'celery2', +} +`; + +valid.push({ + name: 'Comparing a number with a number', + code: + fruitEnumDefinition + + ` +if (1 === 2) { +} + `, +}); + +valid.push({ + name: 'Comparing a number enum literal to literal undefined', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple === undefined) { +} + `, +}); + +valid.push({ + name: 'Comparing a number enum literal to literal null', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple === null) { +} + `, +}); + +valid.push({ + name: 'Comparing a number enum literal with an enum literal of the same type', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple === Fruit.Banana) { +} + `, +}); + +valid.push({ + name: 'Comparing a number enum value with an enum literal of the same type', + code: + fruitEnumDefinition + + ` +const fruit = Fruit.Apple; +if (fruit === Fruit.Banana) { +} + `, +}); + +valid.push({ + name: 'Comparing a string enum value with an enum literal of the same type', + code: + vegetableEnumDefinition + + ` +const vegetable = Vegetable.Lettuce; +if (vegetable === Vegetable.Carrot) { +} + `, +}); + +valid.push({ + name: 'Comparing a number enum value with a value of the same type', + code: + fruitEnumDefinition + + ` +const fruit1 = Fruit.Apple; +const fruit2 = Fruit.Banana; +if (fruit1 === fruit2) { +} + `, +}); + +valid.push({ + name: 'Comparing a string enum value with a value of the same type', + code: + vegetableEnumDefinition + + ` +const vegetable1 = Vegetable.Lettuce; +const vegetable2 = Vegetable.Carrot; +if (vegetable1 === vegetable2) { +} + `, +}); + +invalid.push({ + name: 'Comparing a number enum literal with a number literal', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple === 1) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a string enum literal with a string literal', + code: + vegetableEnumDefinition + + ` +if (Vegetable.Lettuce === 'carrot') { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a number literal with a number enum literal', + code: + fruitEnumDefinition + + ` +if (1 === Fruit.Apple) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a string literal with a string enum literal', + code: + vegetableEnumDefinition + + ` +if ('carrot' === Vegetable.Lettuce) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a number enum value with a number literal', + code: + fruitEnumDefinition + + ` +const fruit = Fruit.Apple; +if (fruit === 1) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a string enum value with a string literal', + code: + vegetableEnumDefinition + + ` +const vegetable = Vegetable.Lettuce; +if (vegetable === 'carrot') { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a number literal with an enum value', + code: + fruitEnumDefinition + + ` +const fruit = Fruit.Apple; +if (1 === fruit) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a string literal with an enum value', + code: + vegetableEnumDefinition + + ` +const vegetable = Vegetable.Lettuce; +if ('carrot' === vegetable) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a number enum literal with a different enum literal', + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` +if (Fruit.Apple === Fruit2.Apple2) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a string enum literal with a different enum literal', + code: + vegetableEnumDefinition + + vegetable2EnumDefinition + + ` +if (Vegetable.Lettuce === Vegetable2.Lettuce2) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a number enum value with a different enum literal', + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` +const fruit = Fruit.Apple; +if (fruit === Fruit2.Apple2) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a string enum value with a different enum literal', + code: + vegetableEnumDefinition + + vegetable2EnumDefinition + + ` +const vegetable = Vegetable.Lettuce; +if (vegetable === Vegetable2.Lettuce2) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +valid.push({ + name: 'Comparing a number enum literal value to an enum literal value of the same type (with strict inequality)', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple !== Fruit.Banana) { +} + `, +}); + +valid.push({ + name: 'Comparing a string enum literal value to an enum literal value of the same type (with strict inequality)', + code: + vegetableEnumDefinition + + ` +if (Vegetable.Lettuce !== Vegetable.Carrot) { +} + `, +}); + +invalid.push({ + name: 'Comparing a number enum literal value to an enum literal value of the same type (with loose equality)', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple == Fruit.Banana) { +} + `, + errors: [{ messageId: 'incorrectComparisonOperator' }], +}); + +invalid.push({ + name: 'Comparing a string enum literal value to an enum literal value of the same type (with loose equality)', + code: + vegetableEnumDefinition + + ` +if (Vegetable.Lettuce == Vegetable.Carrot) { +} + `, + errors: [{ messageId: 'incorrectComparisonOperator' }], +}); + +invalid.push({ + name: 'Comparing a number enum literal value to an enum literal value of the same type (with loose inequality)', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple != Fruit.Banana) { +} + `, + errors: [{ messageId: 'incorrectComparisonOperator' }], +}); + +invalid.push({ + name: 'Comparing a string enum literal value to an enum literal value of the same type (with loose inequality)', + code: + vegetableEnumDefinition + + ` +if (Vegetable.Lettuce != Vegetable.Carrot) { +} + `, + errors: [{ messageId: 'incorrectComparisonOperator' }], +}); + +invalid.push({ + name: 'Comparing a number enum literal value to an enum literal value of the same type (with greater than)', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple > Fruit.Banana) { +} + `, + errors: [{ messageId: 'incorrectComparisonOperator' }], +}); + +invalid.push({ + name: 'Comparing a number enum literal value to an enum literal value of the same type (with less than)', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple < Fruit.Banana) { +} + `, + errors: [{ messageId: 'incorrectComparisonOperator' }], +}); + +ruleTester.run('strict-enums-comparison', rule, { + valid, + invalid, +}); diff --git a/packages/eslint-plugin/tests/rules/strict-enums-declaration.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-declaration.test.ts new file mode 100644 index 000000000000..9fcb387a2e8e --- /dev/null +++ b/packages/eslint-plugin/tests/rules/strict-enums-declaration.test.ts @@ -0,0 +1,41 @@ +import { + InvalidTestCase, + ValidTestCase, +} from '@typescript-eslint/utils/src/ts-eslint'; +import rule, { MessageIds } from '../../src/rules/strict-enums'; +import { fruitEnumDefinition, ruleTester } from './strict-enums'; + +const valid: ValidTestCase[] = []; +const invalid: InvalidTestCase[] = []; + +valid.push({ + name: 'Declaring an enum with an empty initializer', + code: + fruitEnumDefinition + + ` + let fruit: Fruit; + if (true) { + fruit = Fruit.Apple; + } else { + fruit = Fruit.Banana; + } + `, +}); + +/** + * In development, this would trigger run-time errors due to the + * `typeChecker.getTypeAtLocation` method being buggy and not having a proper + * function signature. + */ +valid.push({ + name: 'Declaring an "empty" variable with array destructuring', + code: ` + const myArray = [1]; + const [firstElement] = myArray; + `, +}); + +ruleTester.run('strict-enums-declaration', rule, { + valid, + invalid, +}); diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts new file mode 100644 index 000000000000..67e1b95bef27 --- /dev/null +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -0,0 +1,441 @@ +import { + InvalidTestCase, + ValidTestCase, +} from '@typescript-eslint/utils/src/ts-eslint'; +import rule, { MessageIds } from '../../src/rules/strict-enums'; +import { fruitEnumDefinition, ruleTester } from './strict-enums'; + +const valid: ValidTestCase[] = []; +const invalid: InvalidTestCase[] = []; + +/** A function that takes a number enum. */ +const fruitFunctionDefinition = + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit) {} +`; + +/** A function that takes a number enum literal. */ +const fruitLiteralFunctionDefinition = + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple) {} +`; + +/** A function that takes a number enum with a default argument. */ +const fruitFunctionWithDefaultArgDefinition = + fruitEnumDefinition + + ` +function useFruit(fruit = Fruit.Apple) {} +`; + +/** A function that takes a number enum literal with a default argument. */ +const fruitLiteralFunctionWithDefaultArgDefinition = + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} +`; + +/** A function that takes a number enum with a union. */ +const fruitFunctionWithUnionDefinition = + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit | null) {} +`; + +/** A function that takes a number enum with a union and a default argument. */ +const fruitFunctionWithUnionAndDefaultDefinition = + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit | null = Fruit.Apple) {} +`; + +/** A function that takes a number enum literal with a union. */ +const fruitLiteralFunctionWithUnionDefinition = + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | null) {} +`; + +/** A function that takes a number enum literal with a union and a default argument. */ +const fruitLiteralFunctionWithUnionAndDefaultDefinition = + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} +`; + +/** A function that takes a number enum literal with a union including two enum types. */ +const fruitLiteralFunctionWithComplexUnionDefinition = + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} +`; + +valid.push({ + name: 'Using a normal function without any enums', + code: ` +function useNumber(num: number) {} +useNumber(0); + `, +}); + +valid.push({ + name: 'Using a number enum literal as a function argument', + code: + fruitFunctionDefinition + + ` +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value as a function argument', + code: + fruitFunctionDefinition + + ` +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal as a function argument', + code: + fruitFunctionDefinition + + ` + useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal as a function argument (with an "enum literal" argument type)', + code: + fruitLiteralFunctionDefinition + + ` + useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value as a function argument (with an "enum literal" argument type)', + code: + fruitLiteralFunctionDefinition + + ` +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal as a function argument (with an "enum literal" argument type)', + code: + fruitLiteralFunctionDefinition + + ` +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal as a function argument (with a default function argument)', + code: + fruitFunctionWithDefaultArgDefinition + + ` +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value as a function argument (with a default function argument)', + code: + fruitFunctionWithDefaultArgDefinition + + ` +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal as a function argument (with a default function argument)', + code: + fruitFunctionWithDefaultArgDefinition + + ` +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal as a function argument (with a "number literal" arument type + default)', + code: + fruitLiteralFunctionWithDefaultArgDefinition + + ` +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value as a function argument (with a "number literal" arument type + default)', + code: + fruitLiteralFunctionWithDefaultArgDefinition + + ` +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal as a function argument (with a "number literal" arument type + default)', + code: + fruitLiteralFunctionWithDefaultArgDefinition + + ` +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal as a function argument (with a "number enum | null" argument type)', + code: + fruitFunctionWithUnionDefinition + + ` +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value as a function argument (with a "number enum | null" argument type)', + code: + fruitFunctionWithUnionDefinition + + ` +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +valid.push({ + name: 'Using a null literal as a function argument (with a "number enum | null" argument type)', + code: + fruitFunctionWithUnionDefinition + + ` +useFruit(null); + `, +}); + +valid.push({ + name: 'Using a null value as a function argument (with a "number enum | null" argument type)', + code: + fruitFunctionWithUnionDefinition + + ` +const fruit = null; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal as a function argument (with a "number enum | null" function argument)', + code: + fruitFunctionWithUnionDefinition + + ` +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal as a function argument (with a "number enum | null" argument type + default)', + code: + fruitFunctionWithUnionAndDefaultDefinition + + ` +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value as a function argument (with a "number enum | null" argument type + default)', + code: + fruitFunctionWithUnionAndDefaultDefinition + + ` +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +valid.push({ + name: 'Using a null literal as a function argument (with a "number enum | null" argument type + default)', + code: + fruitFunctionWithUnionAndDefaultDefinition + + ` +useFruit(null); + `, +}); + +valid.push({ + name: 'Using a null value as a function argument (with a "number enum | null" argument type + default)', + code: + fruitFunctionWithUnionAndDefaultDefinition + + ` +const fruit = null; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal as a function argument (with a "number enum | null" function argument + default)', + code: + fruitFunctionWithUnionAndDefaultDefinition + + ` +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal as a function argument (with a "number enum literal | null" argument type)', + code: + fruitLiteralFunctionWithUnionDefinition + + ` +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value as a function argument (with a "number enum literal | null" argument type)', + code: + fruitLiteralFunctionWithUnionDefinition + + ` +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +valid.push({ + name: 'Using a null literal as a function argument (with a "number enum literal | null" argument type)', + code: + fruitLiteralFunctionWithUnionDefinition + + ` +useFruit(null); + `, +}); + +valid.push({ + name: 'Using a null value as a function argument (with a "number enum literal | null" argument type)', + code: + fruitLiteralFunctionWithUnionDefinition + + ` +const fruit = null; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal as a function argument (with a "number enum literal | null" function argument)', + code: + fruitLiteralFunctionWithUnionDefinition + + ` +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal as a function argument (with a "number enum literal | null" argument type + default)', + code: + fruitLiteralFunctionWithUnionAndDefaultDefinition + + ` +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value as a function argument (with a "number enum literal | null" argument type + default)', + code: + fruitLiteralFunctionWithUnionAndDefaultDefinition + + ` +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +valid.push({ + name: 'Using a null literal as a function argument (with a "number enum literal | null" argument type + default)', + code: + fruitLiteralFunctionWithUnionAndDefaultDefinition + + ` +useFruit(null); + `, +}); + +valid.push({ + name: 'Using a null value as a function argument (with a "number enum literal | null" argument type + default)', + code: + fruitLiteralFunctionWithUnionAndDefaultDefinition + + ` +const fruit = null; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal as a function argument (with a "number enum literal | null" function argument + default)', + code: + fruitLiteralFunctionWithUnionAndDefaultDefinition + + ` +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal as a function argument (with a "number enum literal | number enum literal | null" argument type)', + code: + fruitLiteralFunctionWithComplexUnionDefinition + + ` +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value as a function argument (with a "number enum literal | number enum literal | null" argument type)', + code: + fruitLiteralFunctionWithComplexUnionDefinition + + ` +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +valid.push({ + name: 'Using a null literal as a function argument (with a "number enum literal | number enum literal | null" argument type)', + code: + fruitLiteralFunctionWithComplexUnionDefinition + + ` +useFruit(null); + `, +}); + +valid.push({ + name: 'Using a null value as a function argument (with a "number enum literal | number enum literal | null" argument type)', + code: + fruitLiteralFunctionWithComplexUnionDefinition + + ` +const fruit = null; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal as a function argument (with a "number enum literal | number enum literal | null" argument type)', + code: + fruitLiteralFunctionWithComplexUnionDefinition + + ` +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +ruleTester.run('strict-enums-comparison', rule, { + valid, + invalid, +}); diff --git a/packages/eslint-plugin/tests/rules/strict-enums-incrementing.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-incrementing.test.ts new file mode 100644 index 000000000000..dab139550333 --- /dev/null +++ b/packages/eslint-plugin/tests/rules/strict-enums-incrementing.test.ts @@ -0,0 +1,140 @@ +import { + InvalidTestCase, + ValidTestCase, +} from '@typescript-eslint/utils/src/ts-eslint'; +import rule, { MessageIds } from '../../src/rules/strict-enums'; +import { fruitEnumDefinition, ruleTester } from './strict-enums'; + +const valid: ValidTestCase[] = []; +const invalid: InvalidTestCase[] = []; + +valid.push({ + name: 'Incrementing a number (postfix)', + code: + fruitEnumDefinition + + ` +let fruit = 0; +fruit++; + `, +}); + +invalid.push({ + name: 'Incrementing a number enum value (postfix)', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Apple; +fruit++; + `, + errors: [{ messageId: 'incorrectIncrement' }], +}); + +valid.push({ + name: 'Decrementing a number (postfix)', + code: + fruitEnumDefinition + + ` +let fruit = 1; +fruit--; + `, +}); + +invalid.push({ + name: 'Decrementing a number enum value (postfix)', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Banana; +fruit--; + `, + errors: [{ messageId: 'incorrectIncrement' }], +}); + +valid.push({ + name: 'Incrementing a number (prefix)', + code: + fruitEnumDefinition + + ` +let fruit = 0; +++fruit; + `, +}); + +invalid.push({ + name: 'Incrementing a number enum value (prefix)', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Apple; +++fruit; + `, + errors: [{ messageId: 'incorrectIncrement' }], +}); + +valid.push({ + name: 'Decrementing a number (prefix)', + code: + fruitEnumDefinition + + ` +let fruit = 1; +--fruit + `, +}); + +invalid.push({ + name: 'Decrementing a number enum value (prefix)', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Banana; +--fruit; + `, + errors: [{ messageId: 'incorrectIncrement' }], +}); + +valid.push({ + name: 'Incrementing a number (assignment operator)', + code: + fruitEnumDefinition + + ` +let fruit = 0; +fruit += 1; + `, +}); + +invalid.push({ + name: 'Incrementing a number enum value (assignment operator)', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Apple; +fruit += 1; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +valid.push({ + name: 'Decrementing a number (assignment operator)', + code: + fruitEnumDefinition + + ` +let fruit = 1; +fruit -= 1; + `, +}); + +invalid.push({ + name: 'Decrementing a number enum value (assignment operator)', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Banana; +fruit -= 1; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +ruleTester.run('strict-enums-incrementing', rule, { + valid, + invalid, +}); diff --git a/packages/eslint-plugin/tests/rules/strict-enums.test.ts b/packages/eslint-plugin/tests/rules/strict-enums.test.ts deleted file mode 100644 index 075f54b7ee89..000000000000 --- a/packages/eslint-plugin/tests/rules/strict-enums.test.ts +++ /dev/null @@ -1,1168 +0,0 @@ -import { - InvalidTestCase, - ValidTestCase, -} from '@typescript-eslint/utils/src/ts-eslint'; -import rule, { MessageIds } from '../../src/rules/strict-enums'; -import { getFixturesRootDir, RuleTester } from '../RuleTester'; - -const rootDir = getFixturesRootDir(); -const ruleTester = new RuleTester({ - parserOptions: { - ecmaVersion: 2015, - tsconfigRootDir: rootDir, - project: './tsconfig.json', - }, - parser: '@typescript-eslint/parser', -}); - -const valid: ValidTestCase[] = []; -const invalid: InvalidTestCase[] = []; - -/** A number enum. */ -const fruitEnumDefinition = ` -enum Fruit { - Apple, - Banana, - Pear, -} -`; - -/** - * A string enum. - * - * String enums are only used for comparison tests, since the TypeScript - * compiler does a good job of ensuring safety for variable assignment and usage - * in functions. - */ -const vegetableEnumDefinition = ` -enum Vegetable { - Lettuce = 'lettuce', - Carrot = 'carrot', - Celery = 'celery', -} -`; - -/** A different number enum. */ -const fruit2EnumDefinition = ` -enum Fruit2 { - Apple2, - Banana2, - Pear2, -} -`; - -/** A different string enum. */ -const vegetable2EnumDefinition = ` -enum Vegetable2 { - Lettuce2 = 'lettuce2', - Carrot2 = 'carrot2', - Celery2 = 'celery2', -} -`; - -/** A function that takes a number enum. */ -const fruitFunctionDefinition = - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit) {} -`; - -/** A function that takes a number enum literal. */ -const fruitLiteralFunctionDefinition = - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple) {} -`; - -/** A function that takes a number enum with a default argument. */ -const fruitFunctionWithDefaultArgDefinition = - fruitEnumDefinition + - ` -function useFruit(fruit = Fruit.Apple) {} -`; - -/** A function that takes a number enum literal with a default argument. */ -const fruitLiteralFunctionWithDefaultArgDefinition = - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} -`; - -/** A function that takes a number enum with a union. */ -const fruitFunctionWithUnionDefinition = - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null) {} -`; - -/** A function that takes a number enum with a union and a default argument. */ -const fruitFunctionWithUnionAndDefaultDefinition = - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null = Fruit.Apple) {} -`; - -/** A function that takes a number enum literal with a union. */ -const fruitLiteralFunctionWithUnionDefinition = - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null) {} -`; - -/** A function that takes a number enum literal with a union and a default argument. */ -const fruitLiteralFunctionWithUnionAndDefaultDefinition = - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} -`; - -/** A function that takes a number enum literal with a union including two enum types. */ -const fruitLiteralFunctionWithComplexUnionDefinition = - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} -`; - -// ----------------- -// DECLARATION TESTS -// ----------------- - -valid.push({ - name: 'Declaring an enum with an empty initializer', - code: - fruitEnumDefinition + - ` -let fruit: Fruit; -if (true) { - fruit = Fruit.Apple; -} else { - fruit = Fruit.Banana; -} - `, -}); - -/** - * In development, this would trigger run-time errors in Jest due to the - * `typeChecker.getTypeAtLocation` method being buggy and not having a proper - * function signature. - */ -valid.push({ - name: 'Declaring an "empty" variable with array destructuring', - code: ` -const myArray = [1]; -const [firstElement] = myArray; - `, -}); - -// ---------------- -// ASSIGNMENT TESTS -// ---------------- - -valid.push({ - name: 'Assigning a number enum literal to a number enum (with type-inference)', - code: - fruitEnumDefinition + - ` -const fruit = Fruit.Apple; - `, -}); - -valid.push({ - name: 'Assigning a number enum literal to a number enum (without type-inference)', - code: - fruitEnumDefinition + - ` -const fruit: Fruit = Fruit.Apple; - `, -}); - -valid.push({ - name: 'Assigning a number enum value to a variable of the same type with const', - code: - fruitEnumDefinition + - ` -const apple = Fruit.Apple; -const fruit: Fruit = apple; - `, -}); - -invalid.push({ - name: 'Assigning a number literal to a number enum with const', - code: - fruitEnumDefinition + - ` -const fruit: Fruit = 0; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -valid.push({ - name: 'Assigning a number enum value to a variable of the same type with let', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Apple; -fruit = Fruit.Banana; - `, -}); - -invalid.push({ - name: 'Assigning a number literal to a number enum with let', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Apple; -fruit = 1; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -invalid.push({ - name: 'Assigning an enum parent to a number enum', - code: - fruitEnumDefinition + - ` -const fruit: Fruit = Fruit; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -invalid.push({ - name: 'Assigning a mismatched enum value to a number enum', - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` -const fruit: Fruit = Fruit2.Apple2; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -valid.push({ - name: 'Assigning a number enum literal to a variable with a union type of "number enum | null" with const', - code: - fruitEnumDefinition + - ` -const fruit: Fruit | null = Fruit.Apple; - `, -}); - -valid.push({ - name: 'Assigning a null value to a variable with a union type of "number enum | null" with const', - code: - fruitEnumDefinition + - ` -const fruit: Fruit | null = null; - `, -}); - -invalid.push({ - name: 'Assigning a number literal to a variable with a union type of "number enum | null" with const', - code: - fruitEnumDefinition + - ` -const fruit: Fruit | null = 0; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -valid.push({ - name: 'Assigning a number enum literal to a variable with a union type of "number enum | null" with let', - code: - fruitEnumDefinition + - ` -let fruit: Fruit | null = null; -fruit = Fruit.Apple; - `, -}); - -valid.push({ - name: 'Assigning a null value to a variable with a union type of "number enum | null" with let', - code: - fruitEnumDefinition + - ` -let fruit: Fruit | null = Fruit.Apple; -fruit = null; - `, -}); - -invalid.push({ - name: 'Assigning a number literal to a variable with a union type of "number enum | null" with let', - code: - fruitEnumDefinition + - ` -let fruit: Fruit | null = null; -fruit = 0; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -invalid.push({ - name: 'Assigning a enum literal to a variable with a union type of "number enum | number"', - code: - fruitEnumDefinition + - ` -declare const fruit: Fruit | number; -const fruitCopy: Fruit = fruit; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -valid.push({ - name: 'Assignment to variables with a composition type that includes individual enum values', - code: ` -enum Foo { - A = 1, - B = 2, - C = 3, - D = 4, -} - -declare const foo: Foo; -declare const fooSubset: Foo.A | Foo.B | Foo.C; -const x: Foo = fooSubset; -const y: Foo.A | Foo.B | Foo.C = fooSubset; -const z: Foo.A | Foo.B | Foo.C | Foo.D = foo; - `, -}); - -/** - * Intersection enum types are not checked by this rule. Even though doing this - * would almost certainly be a bad idea, a programmer would have to go to great - * lengths to do this, so we assume that the programmer knows what they are - * doing and allow it. - */ -valid.push({ - name: 'Assignment to a variable with a intersection enum type', - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` -const foo: Fruit & Fruit2 = Fruit.Apple; - `, -}); - -// ------------------ -// INCREMENTING TESTS -// ------------------ - -valid.push({ - name: 'Incrementing a number (postfix)', - code: - fruitEnumDefinition + - ` -let fruit = 0; -fruit++; - `, -}); - -invalid.push({ - name: 'Incrementing a number enum value (postfix)', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Apple; -fruit++; - `, - errors: [{ messageId: 'incorrectIncrement' }], -}); - -valid.push({ - name: 'Decrementing a number (postfix)', - code: - fruitEnumDefinition + - ` -let fruit = 1; -fruit--; - `, -}); - -invalid.push({ - name: 'Decrementing a number enum value (postfix)', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Banana; -fruit--; - `, - errors: [{ messageId: 'incorrectIncrement' }], -}); - -valid.push({ - name: 'Incrementing a number (prefix)', - code: - fruitEnumDefinition + - ` -let fruit = 0; -++fruit; - `, -}); - -invalid.push({ - name: 'Incrementing a number enum value (prefix)', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Apple; -++fruit; - `, - errors: [{ messageId: 'incorrectIncrement' }], -}); - -valid.push({ - name: 'Decrementing a number (prefix)', - code: - fruitEnumDefinition + - ` -let fruit = 1; ---fruit - `, -}); - -invalid.push({ - name: 'Decrementing a number enum value (prefix)', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Banana; ---fruit; - `, - errors: [{ messageId: 'incorrectIncrement' }], -}); - -valid.push({ - name: 'Incrementing a number (assignment operator)', - code: - fruitEnumDefinition + - ` -let fruit = 0; -fruit += 1; - `, -}); - -invalid.push({ - name: 'Incrementing a number enum value (assignment operator)', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Apple; -fruit += 1; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -valid.push({ - name: 'Decrementing a number (assignment operator)', - code: - fruitEnumDefinition + - ` -let fruit = 1; -fruit -= 1; - `, -}); - -invalid.push({ - name: 'Decrementing a number enum value (assignment operator)', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Banana; -fruit -= 1; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -// ---------------- -// COMPARISON TESTS -// ---------------- - -valid.push({ - name: 'Comparing a number with a number', - code: - fruitEnumDefinition + - ` -if (1 === 2) { -} - `, -}); - -valid.push({ - name: 'Comparing a number enum literal to literal undefined', - code: - fruitEnumDefinition + - ` -if (Fruit.Apple === undefined) { -} - `, -}); - -valid.push({ - name: 'Comparing a number enum literal to literal null', - code: - fruitEnumDefinition + - ` -if (Fruit.Apple === null) { -} - `, -}); - -valid.push({ - name: 'Comparing a number enum literal with an enum literal of the same type', - code: - fruitEnumDefinition + - ` -if (Fruit.Apple === Fruit.Banana) { -} - `, -}); - -valid.push({ - name: 'Comparing a number enum value with an enum literal of the same type', - code: - fruitEnumDefinition + - ` -const fruit = Fruit.Apple; -if (fruit === Fruit.Banana) { -} - `, -}); - -valid.push({ - name: 'Comparing a string enum value with an enum literal of the same type', - code: - vegetableEnumDefinition + - ` -const vegetable = Vegetable.Lettuce; -if (vegetable === Vegetable.Carrot) { -} - `, -}); - -valid.push({ - name: 'Comparing a number enum value with a value of the same type', - code: - fruitEnumDefinition + - ` -const fruit1 = Fruit.Apple; -const fruit2 = Fruit.Banana; -if (fruit1 === fruit2) { -} - `, -}); - -valid.push({ - name: 'Comparing a string enum value with a value of the same type', - code: - vegetableEnumDefinition + - ` -const vegetable1 = Vegetable.Lettuce; -const vegetable2 = Vegetable.Carrot; -if (vegetable1 === vegetable2) { -} - `, -}); - -invalid.push({ - name: 'Comparing a number enum literal with a number literal', - code: - fruitEnumDefinition + - ` -if (Fruit.Apple === 1) { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a string enum literal with a string literal', - code: - vegetableEnumDefinition + - ` -if (Vegetable.Lettuce === 'carrot') { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a number literal with a number enum literal', - code: - fruitEnumDefinition + - ` -if (1 === Fruit.Apple) { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a string literal with a string enum literal', - code: - vegetableEnumDefinition + - ` -if ('carrot' === Vegetable.Lettuce) { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a number enum value with a number literal', - code: - fruitEnumDefinition + - ` -const fruit = Fruit.Apple; -if (fruit === 1) { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a string enum value with a string literal', - code: - vegetableEnumDefinition + - ` -const vegetable = Vegetable.Lettuce; -if (vegetable === 'carrot') { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a number literal with an enum value', - code: - fruitEnumDefinition + - ` -const fruit = Fruit.Apple; -if (1 === fruit) { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a string literal with an enum value', - code: - vegetableEnumDefinition + - ` -const vegetable = Vegetable.Lettuce; -if ('carrot' === vegetable) { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a number enum literal with a different enum literal', - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` -if (Fruit.Apple === Fruit2.Apple2) { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a string enum literal with a different enum literal', - code: - vegetableEnumDefinition + - vegetable2EnumDefinition + - ` -if (Vegetable.Lettuce === Vegetable2.Lettuce2) { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a number enum value with a different enum literal', - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` -const fruit = Fruit.Apple; -if (fruit === Fruit2.Apple2) { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a string enum value with a different enum literal', - code: - vegetableEnumDefinition + - vegetable2EnumDefinition + - ` -const vegetable = Vegetable.Lettuce; -if (vegetable === Vegetable2.Lettuce2) { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -valid.push({ - name: 'Comparing a number enum literal value to an enum literal value of the same type (with strict inequality)', - code: - fruitEnumDefinition + - ` -if (Fruit.Apple !== Fruit.Banana) { -} - `, -}); - -valid.push({ - name: 'Comparing a string enum literal value to an enum literal value of the same type (with strict inequality)', - code: - vegetableEnumDefinition + - ` -if (Vegetable.Lettuce !== Vegetable.Carrot) { -} - `, -}); - -invalid.push({ - name: 'Comparing a number enum literal value to an enum literal value of the same type (with loose equality)', - code: - fruitEnumDefinition + - ` -if (Fruit.Apple == Fruit.Banana) { -} - `, - errors: [{ messageId: 'incorrectComparisonOperator' }], -}); - -invalid.push({ - name: 'Comparing a string enum literal value to an enum literal value of the same type (with loose equality)', - code: - vegetableEnumDefinition + - ` -if (Vegetable.Lettuce == Vegetable.Carrot) { -} - `, - errors: [{ messageId: 'incorrectComparisonOperator' }], -}); - -invalid.push({ - name: 'Comparing a number enum literal value to an enum literal value of the same type (with loose inequality)', - code: - fruitEnumDefinition + - ` -if (Fruit.Apple != Fruit.Banana) { -} - `, - errors: [{ messageId: 'incorrectComparisonOperator' }], -}); - -invalid.push({ - name: 'Comparing a string enum literal value to an enum literal value of the same type (with loose inequality)', - code: - vegetableEnumDefinition + - ` -if (Vegetable.Lettuce != Vegetable.Carrot) { -} - `, - errors: [{ messageId: 'incorrectComparisonOperator' }], -}); - -invalid.push({ - name: 'Comparing a number enum literal value to an enum literal value of the same type (with greater than)', - code: - fruitEnumDefinition + - ` -if (Fruit.Apple > Fruit.Banana) { -} - `, - errors: [{ messageId: 'incorrectComparisonOperator' }], -}); - -invalid.push({ - name: 'Comparing a number enum literal value to an enum literal value of the same type (with less than)', - code: - fruitEnumDefinition + - ` -if (Fruit.Apple < Fruit.Banana) { -} - `, - errors: [{ messageId: 'incorrectComparisonOperator' }], -}); - -// -------------- -// FUNCTION TESTS -// -------------- - -valid.push({ - name: 'Using a normal function without any enums', - code: ` -function useNumber(num: number) {} -useNumber(0); - `, -}); - -valid.push({ - name: 'Using a number enum literal as a function argument', - code: - fruitFunctionDefinition + - ` -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value as a function argument', - code: - fruitFunctionDefinition + - ` -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal as a function argument', - code: - fruitFunctionDefinition + - ` - useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal as a function argument (with an "enum literal" argument type)', - code: - fruitLiteralFunctionDefinition + - ` - useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value as a function argument (with an "enum literal" argument type)', - code: - fruitLiteralFunctionDefinition + - ` -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal as a function argument (with an "enum literal" argument type)', - code: - fruitLiteralFunctionDefinition + - ` -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal as a function argument (with a default function argument)', - code: - fruitFunctionWithDefaultArgDefinition + - ` -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value as a function argument (with a default function argument)', - code: - fruitFunctionWithDefaultArgDefinition + - ` -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal as a function argument (with a default function argument)', - code: - fruitFunctionWithDefaultArgDefinition + - ` -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal as a function argument (with a "number literal" arument type + default)', - code: - fruitLiteralFunctionWithDefaultArgDefinition + - ` -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value as a function argument (with a "number literal" arument type + default)', - code: - fruitLiteralFunctionWithDefaultArgDefinition + - ` -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal as a function argument (with a "number literal" arument type + default)', - code: - fruitLiteralFunctionWithDefaultArgDefinition + - ` -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal as a function argument (with a "number enum | null" argument type)', - code: - fruitFunctionWithUnionDefinition + - ` -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value as a function argument (with a "number enum | null" argument type)', - code: - fruitFunctionWithUnionDefinition + - ` -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -valid.push({ - name: 'Using a null literal as a function argument (with a "number enum | null" argument type)', - code: - fruitFunctionWithUnionDefinition + - ` -useFruit(null); - `, -}); - -valid.push({ - name: 'Using a null value as a function argument (with a "number enum | null" argument type)', - code: - fruitFunctionWithUnionDefinition + - ` -const fruit = null; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal as a function argument (with a "number enum | null" function argument)', - code: - fruitFunctionWithUnionDefinition + - ` -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal as a function argument (with a "number enum | null" argument type + default)', - code: - fruitFunctionWithUnionAndDefaultDefinition + - ` -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value as a function argument (with a "number enum | null" argument type + default)', - code: - fruitFunctionWithUnionAndDefaultDefinition + - ` -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -valid.push({ - name: 'Using a null literal as a function argument (with a "number enum | null" argument type + default)', - code: - fruitFunctionWithUnionAndDefaultDefinition + - ` -useFruit(null); - `, -}); - -valid.push({ - name: 'Using a null value as a function argument (with a "number enum | null" argument type + default)', - code: - fruitFunctionWithUnionAndDefaultDefinition + - ` -const fruit = null; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal as a function argument (with a "number enum | null" function argument + default)', - code: - fruitFunctionWithUnionAndDefaultDefinition + - ` -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal as a function argument (with a "number enum literal | null" argument type)', - code: - fruitLiteralFunctionWithUnionDefinition + - ` -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value as a function argument (with a "number enum literal | null" argument type)', - code: - fruitLiteralFunctionWithUnionDefinition + - ` -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -valid.push({ - name: 'Using a null literal as a function argument (with a "number enum literal | null" argument type)', - code: - fruitLiteralFunctionWithUnionDefinition + - ` -useFruit(null); - `, -}); - -valid.push({ - name: 'Using a null value as a function argument (with a "number enum literal | null" argument type)', - code: - fruitLiteralFunctionWithUnionDefinition + - ` -const fruit = null; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal as a function argument (with a "number enum literal | null" function argument)', - code: - fruitLiteralFunctionWithUnionDefinition + - ` -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal as a function argument (with a "number enum literal | null" argument type + default)', - code: - fruitLiteralFunctionWithUnionAndDefaultDefinition + - ` -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value as a function argument (with a "number enum literal | null" argument type + default)', - code: - fruitLiteralFunctionWithUnionAndDefaultDefinition + - ` -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -valid.push({ - name: 'Using a null literal as a function argument (with a "number enum literal | null" argument type + default)', - code: - fruitLiteralFunctionWithUnionAndDefaultDefinition + - ` -useFruit(null); - `, -}); - -valid.push({ - name: 'Using a null value as a function argument (with a "number enum literal | null" argument type + default)', - code: - fruitLiteralFunctionWithUnionAndDefaultDefinition + - ` -const fruit = null; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal as a function argument (with a "number enum literal | null" function argument + default)', - code: - fruitLiteralFunctionWithUnionAndDefaultDefinition + - ` -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal as a function argument (with a "number enum literal | number enum literal | null" argument type)', - code: - fruitLiteralFunctionWithComplexUnionDefinition + - ` -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value as a function argument (with a "number enum literal | number enum literal | null" argument type)', - code: - fruitLiteralFunctionWithComplexUnionDefinition + - ` -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -valid.push({ - name: 'Using a null literal as a function argument (with a "number enum literal | number enum literal | null" argument type)', - code: - fruitLiteralFunctionWithComplexUnionDefinition + - ` -useFruit(null); - `, -}); - -valid.push({ - name: 'Using a null value as a function argument (with a "number enum literal | number enum literal | null" argument type)', - code: - fruitLiteralFunctionWithComplexUnionDefinition + - ` -const fruit = null; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal as a function argument (with a "number enum literal | number enum literal | null" argument type)', - code: - fruitLiteralFunctionWithComplexUnionDefinition + - ` -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -// --------- -// END TESTS -// --------- - -ruleTester.run('strict-enums', rule, { - valid, - invalid, -}); diff --git a/packages/eslint-plugin/tests/rules/strict-enums.ts b/packages/eslint-plugin/tests/rules/strict-enums.ts new file mode 100644 index 000000000000..7acd31ed99d3 --- /dev/null +++ b/packages/eslint-plugin/tests/rules/strict-enums.ts @@ -0,0 +1,29 @@ +import { getFixturesRootDir, RuleTester } from '../RuleTester'; + +const rootDir = getFixturesRootDir(); +export const ruleTester = new RuleTester({ + parserOptions: { + ecmaVersion: 2015, + tsconfigRootDir: rootDir, + project: './tsconfig.json', + }, + parser: '@typescript-eslint/parser', +}); + +/** A number enum. */ +export const fruitEnumDefinition = ` +enum Fruit { + Apple, + Banana, + Pear, +} +`; + +/** A different number enum. */ +export const fruit2EnumDefinition = ` +enum Fruit2 { + Apple2, + Banana2, + Pear2, +} +`; From ac5e6d92d30278c522cf7ed65c2e962583168a8e Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Thu, 28 Apr 2022 15:42:23 -0400 Subject: [PATCH 04/88] feat(eslint-plugin): [strict-enums] allowing more operators --- .../eslint-plugin/src/rules/strict-enums.ts | 11 +++--- .../rules/strict-enums-comparison.test.ts | 4 +++ .../rules/strict-enums-functions.test.ts | 35 +++++++++++++++++++ 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index de5f6efb149d..9aa6d87cb97c 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -8,6 +8,8 @@ import { import * as ts from 'typescript'; import { TSESTree } from '@typescript-eslint/utils'; +const ALLOWED_ENUM_COMPARISON_OPERATORS = new Set(['===', '!==', '&', '|']); + export type Options = []; export type MessageIds = | 'incorrectComparisonOperator' @@ -27,7 +29,7 @@ export default util.createRule({ }, messages: { incorrectComparisonOperator: - 'You can only compare enum values (or variables that potentially have enum values) with the strict equality (===) and the strict inequality (!==) operators. (Enums are supposed to be resilient to reorganization, so you should only explicitly compare them.)', + 'You can only compare enum values (or variables that potentially have enum values) with the "===", "!==", "&", or "|" operators. (Enums are supposed to be resilient to reorganization, so you should only explicitly compare them.)', incorrectIncrement: 'You cannot increment or decrement an enum type. (Enums are supposed to be resilient to reorganization, so you should explicitly assign a new value instead.)', mismatchedAssignment: @@ -362,11 +364,8 @@ export default util.createRule({ context.report({ node, messageId: 'mismatchedComparison' }); } - /** - * Only allow the strict equality and strict inequality operators for - * enums comparisons. - */ - if (node.operator !== '===' && node.operator !== '!==') { + /** Only allow certain specific operators for enum comparisons. */ + if (!ALLOWED_ENUM_COMPARISON_OPERATORS.has(node.operator)) { context.report({ node, messageId: 'incorrectComparisonOperator' }); } }, diff --git a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts index ce99a547387b..e6bdb6eb25a8 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts @@ -264,6 +264,10 @@ if (vegetable === Vegetable2.Lettuce2) { errors: [{ messageId: 'mismatchedComparison' }], }); +// -------------- +// OPERATOR TESTS +// -------------- + valid.push({ name: 'Comparing a number enum literal value to an enum literal value of the same type (with strict inequality)', code: diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index 67e1b95bef27..b8e1101d0a00 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -435,6 +435,41 @@ useFruit(0); errors: [{ messageId: 'mismatchedFunctionArgument' }], }); +valid.push({ + name: 'Using an enum from a composition type as a function argument', + code: + fruitFunctionDefinition + + ` +interface BaseNode { + type: Fruit; +} + +interface AppleNode extends BaseNode { + type: Fruit.Apple; + apple: number; +} + +interface BananaNode extends BaseNode { + type: Fruit.Apple; + banana: Number; +} + +type Node = AppleNode | BananaNode; + +const fruitNodesSet = new Set([ + Fruit.Apple, + Fruit.Banana, +]); + +const appleNode: AppleNode = { + type: Fruit.Apple, + apple: 1, +}; + +fruitNodesSet.has(appleNode.type); + `, +}); + ruleTester.run('strict-enums-comparison', rule, { valid, invalid, From 7d55248ba3421a9cf3b84d8adc8cc2b0746ee540 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Fri, 29 Apr 2022 05:24:01 -0400 Subject: [PATCH 05/88] fix(eslint-plugin): [strict-enums] adding union test --- .../eslint-plugin/src/rules/strict-enums.ts | 125 ++++++++++-------- .../rules/strict-enums-functions.test.ts | 25 +++- 2 files changed, 95 insertions(+), 55 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 9aa6d87cb97c..b81cec00e381 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -114,7 +114,11 @@ export default util.createRule({ * parameter/argument types of the "real" foo function (as opposed to * looking at the arguments of the call expression itself). * + * Note that this function breaks apart types with a union for the purposes + * of inserting each union member in the set. + * * @returns A `Map` of argument index number to a `Set` of one or more + * types. */ function getRealFunctionParameterTypes( node: TSESTree.CallExpression, @@ -146,13 +150,16 @@ export default util.createRule({ parameter.valueDeclaration, ); - let typeSet = paramNumToTypesMap.get(i); - if (typeSet === undefined) { - typeSet = new Set(); - paramNumToTypesMap.set(i, typeSet); + let paramTypeSet = paramNumToTypesMap.get(i); + if (paramTypeSet === undefined) { + paramTypeSet = new Set(); + paramNumToTypesMap.set(i, paramTypeSet); } - typeSet.add(parameterType); + const parameterSubTypes = unionTypeParts(parameterType); + for (const parameterSubType of parameterSubTypes) { + paramTypeSet.add(parameterSubType); + } } } @@ -177,19 +184,6 @@ export default util.createRule({ return enumTypes.size > 0; } - function typeSetHasEnum(typeSet: Set): boolean { - for (const type of typeSet.values()) { - const subTypes = unionTypeParts(type); - for (const subType of subTypes) { - if (isEnum(subType)) { - return true; - } - } - } - - return false; - } - function isAssigningNonEnumValueToEnumVariable( leftType: ts.Type, rightType: ts.Type, @@ -232,21 +226,26 @@ export default util.createRule({ } function isMismatchedEnumFunctionArgument( - i: number, - type: ts.Type, - paramNumToTypesMap: Map>, + argumentType: ts.Type, // From the function call + paramTypeSet: Set, // From the function itself ): boolean { - const typeSet = paramNumToTypesMap.get(i); - if (typeSet === undefined) { - // This should never happen - return false; - } + const argumentEnumTypes = getEnumTypes(argumentType); - // First, ignore all function arguments that don't have any enum types - if (!typeSetHasEnum(typeSet)) { + /** + * First, allow function calls that have nothing to do with enums, like + * the following: + * + * ```ts + * function useNumber(num: number) {} + * useNumber(0); + * ``` + */ + if (argumentEnumTypes.size === 0 && !typeSetHasEnum(paramTypeSet)) { return false; } + const argumentSubTypes = unionTypeParts(argumentType); + /** * Allow function calls that exactly match the function type, like the * following: @@ -255,8 +254,16 @@ export default util.createRule({ * function useApple(apple: Fruit.Apple) {} * useApple(Fruit.Apple); * ``` + * + * Additionally, allow function calls that match one of the types in a + * union, like the following: + * + * ```ts + * function useApple(apple: Fruit.Apple | null) {} + * useApple(null); + * ``` */ - if (typeSet.has(type)) { + if (setHasAnyElement(paramTypeSet, ...argumentSubTypes)) { return false; } @@ -269,8 +276,7 @@ export default util.createRule({ * useFruit(Fruit.Apple); * ``` */ - const baseEnumType = getBaseEnumType(type); - if (typeSet.has(baseEnumType)) { + if (setHasAnyElementFromSet(paramTypeSet, argumentEnumTypes)) { return false; } @@ -283,31 +289,45 @@ export default util.createRule({ * useFruit(Fruit.Apple); * ``` */ - for (const paramType of typeSet.values()) { + for (const paramType of paramTypeSet.values()) { if (!paramType.isUnion()) { continue; } - /** - * Naively, you would expect the parts of a "Fruit | null" type to be: - * [Fruit, null] - * - * Instead, they are actually: - * [Fruit.Apple, Fruit.Banana, Fruit.Pear, null] - * - * Thus, we must get the base types. - */ - const subTypes = unionTypeParts(paramType); + const paramEnumTypes = getEnumTypes(paramType); + if (setHasAnyElementFromSet(paramEnumTypes, argumentEnumTypes)) { + return false; + } + } + + return true; + } + + function setHasAnyElement(set: Set, ...elements: T[]): boolean { + return elements.some(element => set.has(element)); + } + + function setHasAnyElementFromSet(set1: Set, set2: Set): boolean { + for (const value of set2.values()) { + if (set1.has(value)) { + return true; + } + } + + return false; + } + function typeSetHasEnum(typeSet: Set): boolean { + for (const type of typeSet.values()) { + const subTypes = unionTypeParts(type); for (const subType of subTypes) { - const baseEnumTypeSubType = getBaseEnumType(subType); - if (baseEnumType === baseEnumTypeSubType) { - return false; + if (isEnum(subType)) { + return true; } } } - return true; + return false; } // ------------------ @@ -381,6 +401,11 @@ export default util.createRule({ for (let i = 0; i < node.arguments.length; i++) { const argument = node.arguments[i]; const argumentType = getTypeFromNode(argument); + const paramTypeSet = paramNumToTypesMap.get(i); + if (paramTypeSet === undefined) { + // This should never happen + continue; + } /** * Disallow mismatched function calls, like the following: @@ -390,13 +415,7 @@ export default util.createRule({ * useFruit(0); * ``` */ - if ( - isMismatchedEnumFunctionArgument( - i, - argumentType, - paramNumToTypesMap, - ) - ) { + if (isMismatchedEnumFunctionArgument(argumentType, paramTypeSet)) { context.report({ node, messageId: 'mismatchedFunctionArgument' }); } } diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index b8e1101d0a00..6cbf49afd99e 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -103,7 +103,7 @@ invalid.push({ code: fruitFunctionDefinition + ` - useFruit(0); +useFruit(0); `, errors: [{ messageId: 'mismatchedFunctionArgument' }], }); @@ -113,7 +113,7 @@ valid.push({ code: fruitLiteralFunctionDefinition + ` - useFruit(Fruit.Apple); +useFruit(Fruit.Apple); `, }); @@ -214,6 +214,7 @@ useFruit(fruit); `, }); +// TODO: name valid.push({ name: 'Using a null literal as a function argument (with a "number enum | null" argument type)', code: @@ -470,6 +471,26 @@ fruitNodesSet.has(appleNode.type); `, }); +valid.push({ + name: 'Using a partial union type as a function argument', + code: + fruitFunctionDefinition + + ` +declare const fruitUnion: Fruit.Apple | Fruit.Banana; +useFruit(fruitUnion); +`, +}); + +valid.push({ + name: 'Using a full union type as a function argument', + code: + fruitFunctionDefinition + + ` +declare const fruitUnion: Fruit.Apple | Fruit.Banana | Fruit.Pear; +useFruit(fruitUnion); +`, +}); + ruleTester.run('strict-enums-comparison', rule, { valid, invalid, From 74af3d1517532283a6c1c732d9f764b071a91d9e Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Fri, 29 Apr 2022 06:20:35 -0400 Subject: [PATCH 06/88] fix(eslint-plugin): [strict-enums] refactoring + adding failing class test --- .../src/rules/no-empty-interface.ts | 3 +- .../eslint-plugin/src/rules/strict-enums.ts | 184 ++++++++++-------- .../rules/strict-enums-assignment.test.ts | 4 +- .../rules/strict-enums-comparison.test.ts | 21 +- .../rules/strict-enums-declaration.test.ts | 4 +- .../rules/strict-enums-functions.test.ts | 5 +- .../rules/strict-enums-incrementing.test.ts | 4 +- .../eslint-plugin/tests/rules/strict-enums.ts | 2 +- 8 files changed, 132 insertions(+), 95 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-empty-interface.ts b/packages/eslint-plugin/src/rules/no-empty-interface.ts index e89859190915..fe5229f5470b 100644 --- a/packages/eslint-plugin/src/rules/no-empty-interface.ts +++ b/packages/eslint-plugin/src/rules/no-empty-interface.ts @@ -1,5 +1,6 @@ import * as util from '../util'; import { TSESLint } from '@typescript-eslint/utils'; +import { ScopeType } from '@typescript-eslint/scope-manager'; type Options = [ { @@ -78,7 +79,7 @@ export default util.createRule({ let useAutoFix = true; if (util.isDefinitionFile(filename)) { const scope = context.getScope(); - if (scope.type === 'tsModule' && scope.block.declare) { + if (scope.type === ScopeType.tsModule && scope.block.declare) { useAutoFix = false; } } diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index b81cec00e381..b06431ef4f6c 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -109,6 +109,69 @@ export default util.createRule({ return new Set(intersectingValues); } + function getTypeFromNode(node: TSESTree.Node): ts.Type { + const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); + return getTypeFromTSNode(tsNode); + } + + function getTypeFromTSNode(tsNode: ts.Node): ts.Type { + return typeChecker.getTypeAtLocation(tsNode); + } + + function getTypeName(type: ts.Type): string { + return util.getTypeName(typeChecker, type); + } + + function hasEnumTypes(type: ts.Type): boolean { + const enumTypes = getEnumTypes(type); + return enumTypes.size > 0; + } + + function isEnum(type: ts.Type): boolean { + return isTypeFlagSet(type, ts.TypeFlags.EnumLiteral); + } + + /** + * Returns true if one or more of the provided types are null or undefined. + */ + function isNullOrUndefined(...types: ts.Type[]): boolean { + return types.some(type => { + const typeName = getTypeName(type); + return typeName === 'null' || typeName === 'undefined'; + }); + } + + function setHasAnyElement(set: Set, ...elements: T[]): boolean { + return elements.some(element => set.has(element)); + } + + function setHasAnyElementFromSet(set1: Set, set2: Set): boolean { + for (const value of set2.values()) { + if (set1.has(value)) { + return true; + } + } + + return false; + } + + function typeSetHasEnum(typeSet: Set): boolean { + for (const type of typeSet.values()) { + const subTypes = unionTypeParts(type); + for (const subType of subTypes) { + if (isEnum(subType)) { + return true; + } + } + } + + return false; + } + + // -------------- + // Main functions + // -------------- + /** * Given a call expression like `foo(1)`, derive the corresponding * parameter/argument types of the "real" foo function (as opposed to @@ -166,24 +229,6 @@ export default util.createRule({ return paramNumToTypesMap; } - function getTypeFromNode(node: TSESTree.Node): ts.Type { - const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); - return getTypeFromTSNode(tsNode); - } - - function getTypeFromTSNode(tsNode: ts.Node): ts.Type { - return typeChecker.getTypeAtLocation(tsNode); - } - - function getTypeName(type: ts.Type): string { - return util.getTypeName(typeChecker, type); - } - - function hasEnumTypes(type: ts.Type): boolean { - const enumTypes = getEnumTypes(type); - return enumTypes.size > 0; - } - function isAssigningNonEnumValueToEnumVariable( leftType: ts.Type, rightType: ts.Type, @@ -211,18 +256,35 @@ export default util.createRule({ return intersectingTypes.size === 0; } - function isEnum(type: ts.Type): boolean { - return isTypeFlagSet(type, ts.TypeFlags.EnumLiteral); - } + function isMismatchedEnumComparison( + leftType: ts.Type, + rightType: ts.Type, + leftEnumTypes: Set, + rightEnumTypes: Set, + ): boolean { + /** + * As a special exception, allow comparisons to literal null or literal + * undefined. + * + * The TypeScript compiler should handle these cases properly, so the + * lint rule is unneeded. + */ + if (isNullOrUndefined(leftType, rightType)) { + return false; + } - /** - * Returns true if one or more of the provided types are null or undefined. - */ - function isNullOrUndefined(...types: ts.Type[]): boolean { - return types.some(type => { - const typeName = getTypeName(type); - return typeName === 'null' || typeName === 'undefined'; - }); + /** + * Disallow mismatched comparisons, like the following: + * + * ```ts + * if (fruit === 0) {} + * ``` + */ + const intersectingTypes = getIntersectingSet( + leftEnumTypes, + rightEnumTypes, + ); + return intersectingTypes.size === 0; } function isMismatchedEnumFunctionArgument( @@ -303,33 +365,6 @@ export default util.createRule({ return true; } - function setHasAnyElement(set: Set, ...elements: T[]): boolean { - return elements.some(element => set.has(element)); - } - - function setHasAnyElementFromSet(set1: Set, set2: Set): boolean { - for (const value of set2.values()) { - if (set1.has(value)) { - return true; - } - } - - return false; - } - - function typeSetHasEnum(typeSet: Set): boolean { - for (const type of typeSet.values()) { - const subTypes = unionTypeParts(type); - for (const subType of subTypes) { - if (isEnum(subType)) { - return true; - } - } - } - - return false; - } - // ------------------ // AST node callbacks // ------------------ @@ -358,36 +393,21 @@ export default util.createRule({ return; } - /** - * As a special exception, allow comparisons to literal null or literal - * undefined. - * - * The TypeScript compiler should handle these cases properly, so the - * lint rule is unneeded. - */ - if (isNullOrUndefined(leftType, rightType)) { - return; - } - - /** - * Disallow mismatched comparisons, like the following: - * - * ```ts - * if (fruit === 0) {} - * ``` - */ - const intersectingTypes = getIntersectingSet( - leftEnumTypes, - rightEnumTypes, - ); - if (intersectingTypes.size === 0) { - context.report({ node, messageId: 'mismatchedComparison' }); - } - /** Only allow certain specific operators for enum comparisons. */ if (!ALLOWED_ENUM_COMPARISON_OPERATORS.has(node.operator)) { context.report({ node, messageId: 'incorrectComparisonOperator' }); } + + if ( + isMismatchedEnumComparison( + leftType, + rightType, + leftEnumTypes, + rightEnumTypes, + ) + ) { + context.report({ node, messageId: 'mismatchedComparison' }); + } }, /** When a function is invoked. */ diff --git a/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts index 92d5bf69d74d..28a39b26985d 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts @@ -6,7 +6,7 @@ import rule, { MessageIds } from '../../src/rules/strict-enums'; import { fruit2EnumDefinition, fruitEnumDefinition, - ruleTester, + strictEnumsRuleTester, } from './strict-enums'; const valid: ValidTestCase[] = []; @@ -196,7 +196,7 @@ const foo: Fruit & Fruit2 = Fruit.Apple; `, }); -ruleTester.run('strict-enums-assignment', rule, { +strictEnumsRuleTester.run('strict-enums-assignment', rule, { valid, invalid, }); diff --git a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts index e6bdb6eb25a8..98c956af9665 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts @@ -6,7 +6,7 @@ import rule, { MessageIds } from '../../src/rules/strict-enums'; import { fruit2EnumDefinition, fruitEnumDefinition, - ruleTester, + strictEnumsRuleTester, } from './strict-enums'; const valid: ValidTestCase[] = []; @@ -36,6 +36,10 @@ enum Vegetable2 { } `; +// ---------------------- +// COMPARISON TYPES TESTS +// ---------------------- + valid.push({ name: 'Comparing a number with a number', code: @@ -264,6 +268,19 @@ if (vegetable === Vegetable2.Lettuce2) { errors: [{ messageId: 'mismatchedComparison' }], }); +valid.push({ + name: 'Comparing a generic enum extension value with a number enum literal', + code: + fruitEnumDefinition + + ` +class FruitClass { + constructor(type: FruitType) { + if (type === Fruit.Apple) {} + } +} + `, +}); + // -------------- // OPERATOR TESTS // -------------- @@ -354,7 +371,7 @@ if (Fruit.Apple < Fruit.Banana) { errors: [{ messageId: 'incorrectComparisonOperator' }], }); -ruleTester.run('strict-enums-comparison', rule, { +strictEnumsRuleTester.run('strict-enums-comparison', rule, { valid, invalid, }); diff --git a/packages/eslint-plugin/tests/rules/strict-enums-declaration.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-declaration.test.ts index 9fcb387a2e8e..f9135bb87c5b 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-declaration.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-declaration.test.ts @@ -3,7 +3,7 @@ import { ValidTestCase, } from '@typescript-eslint/utils/src/ts-eslint'; import rule, { MessageIds } from '../../src/rules/strict-enums'; -import { fruitEnumDefinition, ruleTester } from './strict-enums'; +import { fruitEnumDefinition, strictEnumsRuleTester } from './strict-enums'; const valid: ValidTestCase[] = []; const invalid: InvalidTestCase[] = []; @@ -35,7 +35,7 @@ valid.push({ `, }); -ruleTester.run('strict-enums-declaration', rule, { +strictEnumsRuleTester.run('strict-enums-declaration', rule, { valid, invalid, }); diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index 6cbf49afd99e..08b118cdbb5c 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -3,7 +3,7 @@ import { ValidTestCase, } from '@typescript-eslint/utils/src/ts-eslint'; import rule, { MessageIds } from '../../src/rules/strict-enums'; -import { fruitEnumDefinition, ruleTester } from './strict-enums'; +import { fruitEnumDefinition, strictEnumsRuleTester } from './strict-enums'; const valid: ValidTestCase[] = []; const invalid: InvalidTestCase[] = []; @@ -214,7 +214,6 @@ useFruit(fruit); `, }); -// TODO: name valid.push({ name: 'Using a null literal as a function argument (with a "number enum | null" argument type)', code: @@ -491,7 +490,7 @@ useFruit(fruitUnion); `, }); -ruleTester.run('strict-enums-comparison', rule, { +strictEnumsRuleTester.run('strict-enums-comparison', rule, { valid, invalid, }); diff --git a/packages/eslint-plugin/tests/rules/strict-enums-incrementing.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-incrementing.test.ts index dab139550333..eaf586b8b667 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-incrementing.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-incrementing.test.ts @@ -3,7 +3,7 @@ import { ValidTestCase, } from '@typescript-eslint/utils/src/ts-eslint'; import rule, { MessageIds } from '../../src/rules/strict-enums'; -import { fruitEnumDefinition, ruleTester } from './strict-enums'; +import { fruitEnumDefinition, strictEnumsRuleTester } from './strict-enums'; const valid: ValidTestCase[] = []; const invalid: InvalidTestCase[] = []; @@ -134,7 +134,7 @@ fruit -= 1; errors: [{ messageId: 'mismatchedAssignment' }], }); -ruleTester.run('strict-enums-incrementing', rule, { +strictEnumsRuleTester.run('strict-enums-incrementing', rule, { valid, invalid, }); diff --git a/packages/eslint-plugin/tests/rules/strict-enums.ts b/packages/eslint-plugin/tests/rules/strict-enums.ts index 7acd31ed99d3..1ee7975fa59e 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums.ts @@ -1,7 +1,7 @@ import { getFixturesRootDir, RuleTester } from '../RuleTester'; const rootDir = getFixturesRootDir(); -export const ruleTester = new RuleTester({ +export const strictEnumsRuleTester = new RuleTester({ parserOptions: { ecmaVersion: 2015, tsconfigRootDir: rootDir, From 1eb70eec08c1e81224438e263be1330c2805bd10 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Fri, 29 Apr 2022 07:29:24 -0400 Subject: [PATCH 07/88] fix(eslint-plugin): [strict-enums] adding constraint code --- .../eslint-plugin/src/rules/strict-enums.ts | 34 +++++++++++++++++-- .../rules/strict-enums-functions.test.ts | 13 +++++++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index b06431ef4f6c..2e484377624f 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -59,6 +59,10 @@ export default util.createRule({ /** * If passed an enum member, returns the type of the parent. Otherwise, * returns itself. + * + * For example: + * - `Fruit` --> `Fruit` + * - `Fruit.Apple` --> `Fruit` */ function getBaseEnumType(type: ts.Type): ts.Type { const symbol = type.getSymbol(); @@ -90,10 +94,30 @@ export default util.createRule({ * - Fruit.Apple --> [Fruit] * - Fruit.Apple | Vegetable.Lettuce --> [Fruit, Vegetable] * - Fruit.Apple | Vegetable.Lettuce | 123 --> [Fruit, Vegetable] + * - T extends Fruit --> [Fruit] */ function getEnumTypes(type: ts.Type): Set { + /** + * First, we get all the parts of the union. For non-union types, this + * will be an array with the type in it. For example: + * - Fruit --> [Fruit] + * - Fruit | Vegetable --> [Fruit, Vegetable] + */ const subTypes = unionTypeParts(type); - const enumSubTypes = subTypes.filter(subType => isEnum(subType)); + + /** + * Next, we must resolve generic types with constraints. For example: + * - Fruit --> Fruit + * - T extends Fruit --> Fruit + */ + const subTypesConstraints = subTypes.map(subType => { + const constraint = subType.getConstraint(); + return constraint === undefined ? subType : constraint; + }); + + const enumSubTypes = subTypesConstraints.filter(subType => + isEnum(subType), + ); const baseEnumSubTypes = enumSubTypes.map(subType => getBaseEnumType(subType), ); @@ -480,8 +504,12 @@ export default util.createRule({ continue; } - // We have to use "leftTSNode.name" instead of "leftTSNode" to avoid - // runtime errors for reasons that I don't understand + /** + * We have to use `leftTSNode.name` instead of `leftTSNode` to avoid + * runtime errors because the `typeChecker.getTypeAtLocation` method + * expects a `ts.BindingName` instead of a`ts.VariableDeclaration`. + * https://github.com/microsoft/TypeScript/issues/48878 + */ const leftType = getTypeFromTSNode(leftTSNode.name); if (leftType === undefined) { continue; diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index 08b118cdbb5c..b8f2d3b6742c 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -490,6 +490,19 @@ useFruit(fruitUnion); `, }); +valid.push({ + name: 'Using a number enum as a function argument with an enum extension type', + code: + fruitEnumDefinition + + ` +class FruitClass { + constructor(type: FruitType) { + } +} +const fruitClass = new FruitClass(Fruit.Apple); + `, +}); + strictEnumsRuleTester.run('strict-enums-comparison', rule, { valid, invalid, From cf006fda462bda7c64415173a585e8f8cad8f177 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Fri, 29 Apr 2022 08:29:21 -0400 Subject: [PATCH 08/88] fix(eslint-plugin): [strict-enums] better eslint messages --- .../eslint-plugin/docs/rules/strict-enums.md | 25 +++++++-- .../eslint-plugin/src/rules/strict-enums.ts | 55 ++++++++++++++++--- .../eslint-plugin/src/rules/unbound-method.ts | 2 +- .../src/util/collectUnusedVariables.ts | 7 ++- .../rules/strict-enums-functions.test.ts | 16 ++++++ 5 files changed, 87 insertions(+), 18 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/strict-enums.md b/packages/eslint-plugin/docs/rules/strict-enums.md index 1b1c24524b1d..c328783203d4 100644 --- a/packages/eslint-plugin/docs/rules/strict-enums.md +++ b/packages/eslint-plugin/docs/rules/strict-enums.md @@ -30,11 +30,11 @@ Subsequently, this rule bans potentially-dangerous patterns that you might alrea This rule bans: -1. Mismatched enum declarations -1. Mismatched enum assignments -1. Enum incrementing/decrementing -1. Mismatched enum comparisons -1. Mismatched enum function arguments +1. Comparing enums with unsafe operators - `incorrectComparisonOperator` +1. Enum incrementing/decrementing - `incorrectIncrement` +1. Mismatched enum declarations/assignments - `mismatchedAssignment` +1. Mismatched enum comparisons - `mismatchedComparison` +1. Mismatched enum function arguments - `mismatchedFunctionArgument` @@ -104,6 +104,19 @@ function useFruit(fruit: Fruit) {} useFruit(Fruit.Apple); ``` +## Error Information + +- `incorrectComparisonOperator` - You cannot compare enums with the "{{ operator }}" operator. You can only compare with the "===", "!==", "&", or "|" operators. + - Enums are supposed to be resilient to reorganization, so you should only explicitly compare them. For example, if you used a greater than sign to compare a number enum, and then someone reassigned/reordered the values of the enum, then it could potentially break your code. +- `incorrectIncrement` - You cannot increment or decrement an enum type. + - Enums are supposed to be resilient to reorganization, so you should explicitly assign a new value instead. For example, if someone someone reassigned/reordered the values of the enum, then it could potentially break your code. +- `mismatchedAssignment` - The type of the assignment does not match the declared enum type of the variable. + - In other words, you are trying to assign a `Foo` enum value to a variable with a `Bar` type. Enums are supposed to be resilient to reorganization, so these kinds of assignments can be dangerous. +- `mismatchedComparison` - The two things in the comparison do not have a shared enum type. + - You might be trying to compare using a number literal, like `Foo.Value1 === 1`. Or, you might be trying to compare use a disparate enum type, like `Foo.Value1 === Bar.Value1`. Either way, you need to use a value that corresponds to the correct enum, like `foo === Foo.Value1`, where `foo` is type `Foo`. Enums are supposed to be resilient to reorganization, so these types of comparisons can be dangerous. +- `mismatchedFunctionArgument` - The argument in the function call does not match the declared enum type of the function signature. + - You might be trying to use a number literal, like `useFoo(1)`. Or, you might be trying to use a disparate enum type, like `useFoo(Bar.Value1)`. Either way, you need to use a value that corresponds to the correct enum, like `useFoo(Foo.Value1)`. Enums are supposed to be resilient to reorganization, so non-exact function calls like this can be dangerous. + ## Number Enums vs String Enums Surprisingly, the TypeScript compiler deals with string enums in a safer way than it does with number enums. If we duplicate the first example above by using a string enum, the TypeScript compiler will correctly throw an error: @@ -115,7 +128,7 @@ enum Vegetable { } let vegetable = Vegetable.Lettuce; -vegetable = 'tomato'; // Type '"tomato"' is not assignable to type 'Vegetable'. +vegetable = 'definatelyNotAVegetable'; // Type '"definatelyNotAVegetable"' is not assignable to type 'Vegetable'. // Even "valid" strings will not work, which is good! vegetable = 'carrot'; // Type '"carrot"' is not assignable to type 'Vegetable'. diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 2e484377624f..f5e95df14fe2 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -29,15 +29,14 @@ export default util.createRule({ }, messages: { incorrectComparisonOperator: - 'You can only compare enum values (or variables that potentially have enum values) with the "===", "!==", "&", or "|" operators. (Enums are supposed to be resilient to reorganization, so you should only explicitly compare them.)', - incorrectIncrement: - 'You cannot increment or decrement an enum type. (Enums are supposed to be resilient to reorganization, so you should explicitly assign a new value instead.)', + 'You cannot compare enums with the "{{ operator }}" operator. You can only compare with the "===", "!==", "&", or "|" operators.', + incorrectIncrement: 'You cannot increment or decrement an enum type.', mismatchedAssignment: - 'The type of the assignment does not match the declared enum type of the variable. In other words, you are trying to assign a Foo enum value to a variable with a Bar type. (Enums are supposed to be resilient to reorganization, so this kind of code can be dangerous.)', + 'The type of the enum assignment ({{ assignmentType }}) does not match the declared enum type ({{ declaredType }}) of the variable.', mismatchedComparison: - 'The two things in the comparison do not have a shared enum type. You might be trying to use a number literal, like `Foo.Value1 === 1`. Or, you might be trying to use a disparate enum type, like `Foo.Value1 === Bar.Value1`. Either way, you need to use a value that corresponds to the correct enum, like `foo === Foo.Value1`, where `foo` is type `Foo`. (Enums are supposed to be resilient to reorganization, so this kind of code can be dangerous.)', + 'The two things in the comparison do not have a shared enum type.', mismatchedFunctionArgument: - 'The argument in the function call does not match the declared enum type of the function signature. You might be trying to use a number literal, like `useFoo(1);`. Or, you might be trying to use a disparate enum type, like `useFoo(Bar.Value1)`. Either way, you need to use a value that corresponds to the correct enum, like `useFoo(Foo.Value1)`. (Enums are supposed to be resilient to reorganization, so this kind of code can be dangerous.)', + 'The {{ ordinal }} argument in the function call does not match the declared enum type of the function signature.', }, schema: [ { @@ -133,6 +132,25 @@ export default util.createRule({ return new Set(intersectingValues); } + /** + * From: + * https://stackoverflow.com/questions/13627308/add-st-nd-rd-and-th-ordinal-suffix-to-a-number + */ + function getOrdinalSuffix(i: number): string { + const j = i % 10; + const k = i % 100; + if (j == 1 && k != 11) { + return `${i}st`; + } + if (j == 2 && k != 12) { + return `${i}nd`; + } + if (j == 3 && k != 13) { + return `${i}rd`; + } + return `${i}th`; + } + function getTypeFromNode(node: TSESTree.Node): ts.Type { const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); return getTypeFromTSNode(tsNode); @@ -400,7 +418,14 @@ export default util.createRule({ const rightType = getTypeFromNode(node.right); if (isAssigningNonEnumValueToEnumVariable(leftType, rightType)) { - context.report({ node, messageId: 'mismatchedAssignment' }); + context.report({ + node, + messageId: 'mismatchedAssignment', + data: { + assignmentType: getTypeName(leftType), + declaredType: getTypeName(rightType), + }, + }); } }, @@ -419,7 +444,13 @@ export default util.createRule({ /** Only allow certain specific operators for enum comparisons. */ if (!ALLOWED_ENUM_COMPARISON_OPERATORS.has(node.operator)) { - context.report({ node, messageId: 'incorrectComparisonOperator' }); + context.report({ + node, + messageId: 'incorrectComparisonOperator', + data: { + operator: node.operator, + }, + }); } if ( @@ -460,7 +491,13 @@ export default util.createRule({ * ``` */ if (isMismatchedEnumFunctionArgument(argumentType, paramTypeSet)) { - context.report({ node, messageId: 'mismatchedFunctionArgument' }); + context.report({ + node, + messageId: 'mismatchedFunctionArgument', + data: { + ordinal: getOrdinalSuffix(i), + }, + }); } } }, diff --git a/packages/eslint-plugin/src/rules/unbound-method.ts b/packages/eslint-plugin/src/rules/unbound-method.ts index 2dd6aafaebf1..f9462c5147d3 100644 --- a/packages/eslint-plugin/src/rules/unbound-method.ts +++ b/packages/eslint-plugin/src/rules/unbound-method.ts @@ -272,7 +272,7 @@ function checkMethod( const firstParam = decl.parameters[0]; const firstParamIsThis = firstParam?.name.kind === ts.SyntaxKind.Identifier && - firstParam?.name.escapedText === 'this'; + firstParam?.name.escapedText === ts.InternalSymbolName.This; const thisArgIsVoid = firstParamIsThis && firstParam?.type?.kind === ts.SyntaxKind.VoidKeyword; diff --git a/packages/eslint-plugin/src/util/collectUnusedVariables.ts b/packages/eslint-plugin/src/util/collectUnusedVariables.ts index 6fe14b0d2725..9aacb36c5e49 100644 --- a/packages/eslint-plugin/src/util/collectUnusedVariables.ts +++ b/packages/eslint-plugin/src/util/collectUnusedVariables.ts @@ -5,7 +5,10 @@ import { TSESTree, ESLintUtils, } from '@typescript-eslint/utils'; -import { ImplicitLibVariable } from '@typescript-eslint/scope-manager'; +import { + ImplicitLibVariable, + ScopeType, +} from '@typescript-eslint/scope-manager'; import { Visitor } from '@typescript-eslint/scope-manager/dist/referencer/Visitor'; class UnusedVarsVisitor< @@ -98,7 +101,7 @@ class UnusedVarsVisitor< const scope = this.#scopeManager.acquire(node, inner); if (scope) { - if (scope.type === 'function-expression-name') { + if (scope.type === ScopeType.functionExpressionName) { return scope.childScopes[0] as T; } return scope as T; diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index b8f2d3b6742c..67a09ca4c2a5 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -490,6 +490,22 @@ useFruit(fruitUnion); `, }); +valid.push({ + name: 'Using a partial union type as a function argument (from a type narrowing switch statement)', + code: + fruitFunctionDefinition + + ` +function foo(fruit: Fruit) { + switch (fruit) { + case Fruit.Apple: + case Fruit.Banana: { + useFruit(fruit); + } + } +} +`, +}); + valid.push({ name: 'Using a number enum as a function argument with an enum extension type', code: From 2bbc2b76be83d2e71d31af917e1724290c290b85 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Fri, 29 Apr 2022 09:02:07 -0400 Subject: [PATCH 09/88] fix(eslint-plugin): [strict-enums] removing vscode setting changes --- .vscode/settings.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 349f0ec5b481..c33f13702f89 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,8 +1,5 @@ { - // This matches the value in the Prettier config - "editor.rulers": [80], - // An array of language ids which should be validated by ESLint "eslint.validate": [ "javascript", From 3976fdcfeac27d8be57ee1fe55804e6d9ac24a26 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Fri, 29 Apr 2022 11:06:57 -0400 Subject: [PATCH 10/88] fix: changing function definition to reflect reality --- .../src/rules/strict-boolean-expressions.ts | 6 +- .../eslint-plugin/src/rules/strict-enums.ts | 42 +++++++++++- .../rules/strict-enums-assignment.test.ts | 14 ++++ .../rules/strict-enums-functions.test.ts | 68 ++++++++++++------- packages/type-utils/src/typeFlagUtils.ts | 7 +- 5 files changed, 105 insertions(+), 32 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts index 0a91b2fca950..9994d887d0a7 100644 --- a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts +++ b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts @@ -730,7 +730,7 @@ export default util.createRule({ if ( types.some(type => - tsutils.isTypeFlagSet( + util.isTypeFlagSet( type, ts.TypeFlags.Null | ts.TypeFlags.Undefined | ts.TypeFlags.VoidLike, ), @@ -767,7 +767,7 @@ export default util.createRule({ } const numbers = types.filter(type => - tsutils.isTypeFlagSet( + util.isTypeFlagSet( type, ts.TypeFlags.NumberLike | ts.TypeFlags.BigIntLike, ), @@ -783,7 +783,7 @@ export default util.createRule({ if ( types.some( type => - !tsutils.isTypeFlagSet( + !util.isTypeFlagSet( type, ts.TypeFlags.Null | ts.TypeFlags.Undefined | diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index f5e95df14fe2..a5a796358131 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -8,7 +8,12 @@ import { import * as ts from 'typescript'; import { TSESTree } from '@typescript-eslint/utils'; -const ALLOWED_ENUM_COMPARISON_OPERATORS = new Set(['===', '!==', '&', '|']); +const ALLOWED_ENUM_BINARY_COMPARISON_OPERATORS = new Set(['&', '|']); +const ALLOWED_ENUM_NON_BINARY_COMPARISON_OPERATORS = new Set(['===', '!==']); +const ALLOWED_ENUM_COMPARISON_OPERATORS = new Set([ + ...ALLOWED_ENUM_BINARY_COMPARISON_OPERATORS.values(), + ...ALLOWED_ENUM_NON_BINARY_COMPARISON_OPERATORS.values(), +]); export type Options = []; export type MessageIds = @@ -299,11 +304,27 @@ export default util.createRule({ } function isMismatchedEnumComparison( + operator: string, leftType: ts.Type, rightType: ts.Type, leftEnumTypes: Set, rightEnumTypes: Set, ): boolean { + /** + * Allow composing a variable based on enum literals using binary + * operators, like the following: + * + * ```ts + * const flags = Flag.Value1 | Flag.Value2; + * ``` + * + * (Even though this is an assignment, it still matches the + * `BinaryExpression` node type.) + */ + if (ALLOWED_ENUM_BINARY_COMPARISON_OPERATORS.has(operator)) { + return false; + } + /** * As a special exception, allow comparisons to literal null or literal * undefined. @@ -348,6 +369,22 @@ export default util.createRule({ return false; } + /** + * Allow passing enum values into functions that take in `number`, like + * the following: + * + * ```ts + * function useNumber(num: number) {} + * useNumber(Fruit.Apple); + * ``` + */ + for (const paramType of paramTypeSet.values()) { + const paramTypeName = getTypeName(paramType); + if (paramTypeName === 'number') { + return false; + } + } + const argumentSubTypes = unionTypeParts(argumentType); /** @@ -455,6 +492,7 @@ export default util.createRule({ if ( isMismatchedEnumComparison( + node.operator, leftType, rightType, leftEnumTypes, @@ -495,7 +533,7 @@ export default util.createRule({ node, messageId: 'mismatchedFunctionArgument', data: { - ordinal: getOrdinalSuffix(i), + ordinal: getOrdinalSuffix(i + 1), // e.g. 0 --> 1st }, }); } diff --git a/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts index 28a39b26985d..5596298d4c25 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts @@ -196,6 +196,20 @@ const foo: Fruit & Fruit2 = Fruit.Apple; `, }); +valid.push({ + name: 'Assignment to a variable with a composition of binary flags', + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` +enum Flag { + Value1 = 1 << 0, + Value2 = 1 << 1, +} +const flags = Flag.Value1 | Flag.Value2; + `, +}); + strictEnumsRuleTester.run('strict-enums-assignment', rule, { valid, invalid, diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index 67a09ca4c2a5..72117c74bd52 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -109,7 +109,7 @@ useFruit(0); }); valid.push({ - name: 'Using a number enum literal as a function argument (with an "enum literal" argument type)', + name: 'Using a number enum literal as a function argument (with an "enum literal" parameter type)', code: fruitLiteralFunctionDefinition + ` @@ -118,7 +118,7 @@ useFruit(Fruit.Apple); }); valid.push({ - name: 'Using a number enum value as a function argument (with an "enum literal" argument type)', + name: 'Using a number enum value as a function argument (with an "enum literal" parameter type)', code: fruitLiteralFunctionDefinition + ` @@ -128,7 +128,7 @@ useFruit(fruit); }); invalid.push({ - name: 'Using a number literal as a function argument (with an "enum literal" argument type)', + name: 'Using a number literal as a function argument (with an "enum literal" parameter type)', code: fruitLiteralFunctionDefinition + ` @@ -196,7 +196,7 @@ useFruit(0); }); valid.push({ - name: 'Using a number enum literal as a function argument (with a "number enum | null" argument type)', + name: 'Using a number enum literal as a function argument (with a "number enum | null" parameter type)', code: fruitFunctionWithUnionDefinition + ` @@ -205,7 +205,7 @@ useFruit(Fruit.Apple); }); valid.push({ - name: 'Using a number enum value as a function argument (with a "number enum | null" argument type)', + name: 'Using a number enum value as a function argument (with a "number enum | null" parameter type)', code: fruitFunctionWithUnionDefinition + ` @@ -215,7 +215,7 @@ useFruit(fruit); }); valid.push({ - name: 'Using a null literal as a function argument (with a "number enum | null" argument type)', + name: 'Using a null literal as a function argument (with a "number enum | null" parameter type)', code: fruitFunctionWithUnionDefinition + ` @@ -224,7 +224,7 @@ useFruit(null); }); valid.push({ - name: 'Using a null value as a function argument (with a "number enum | null" argument type)', + name: 'Using a null value as a function argument (with a "number enum | null" parameter type)', code: fruitFunctionWithUnionDefinition + ` @@ -244,7 +244,7 @@ useFruit(0); }); valid.push({ - name: 'Using a number enum literal as a function argument (with a "number enum | null" argument type + default)', + name: 'Using a number enum literal as a function argument (with a "number enum | null" parameter type + default)', code: fruitFunctionWithUnionAndDefaultDefinition + ` @@ -253,7 +253,7 @@ useFruit(Fruit.Apple); }); valid.push({ - name: 'Using a number enum value as a function argument (with a "number enum | null" argument type + default)', + name: 'Using a number enum value as a function argument (with a "number enum | null" parameter type + default)', code: fruitFunctionWithUnionAndDefaultDefinition + ` @@ -263,7 +263,7 @@ useFruit(fruit); }); valid.push({ - name: 'Using a null literal as a function argument (with a "number enum | null" argument type + default)', + name: 'Using a null literal as a function argument (with a "number enum | null" parameter type + default)', code: fruitFunctionWithUnionAndDefaultDefinition + ` @@ -272,7 +272,7 @@ useFruit(null); }); valid.push({ - name: 'Using a null value as a function argument (with a "number enum | null" argument type + default)', + name: 'Using a null value as a function argument (with a "number enum | null" parameter type + default)', code: fruitFunctionWithUnionAndDefaultDefinition + ` @@ -292,7 +292,7 @@ useFruit(0); }); valid.push({ - name: 'Using a number enum literal as a function argument (with a "number enum literal | null" argument type)', + name: 'Using a number enum literal as a function argument (with a "number enum literal | null" parameter type)', code: fruitLiteralFunctionWithUnionDefinition + ` @@ -301,7 +301,7 @@ useFruit(Fruit.Apple); }); valid.push({ - name: 'Using a number enum value as a function argument (with a "number enum literal | null" argument type)', + name: 'Using a number enum value as a function argument (with a "number enum literal | null" parameter type)', code: fruitLiteralFunctionWithUnionDefinition + ` @@ -311,7 +311,7 @@ useFruit(fruit); }); valid.push({ - name: 'Using a null literal as a function argument (with a "number enum literal | null" argument type)', + name: 'Using a null literal as a function argument (with a "number enum literal | null" parameter type)', code: fruitLiteralFunctionWithUnionDefinition + ` @@ -320,7 +320,7 @@ useFruit(null); }); valid.push({ - name: 'Using a null value as a function argument (with a "number enum literal | null" argument type)', + name: 'Using a null value as a function argument (with a "number enum literal | null" parameter type)', code: fruitLiteralFunctionWithUnionDefinition + ` @@ -340,7 +340,7 @@ useFruit(0); }); valid.push({ - name: 'Using a number enum literal as a function argument (with a "number enum literal | null" argument type + default)', + name: 'Using a number enum literal as a function argument (with a "number enum literal | null" parameter type + default)', code: fruitLiteralFunctionWithUnionAndDefaultDefinition + ` @@ -349,7 +349,7 @@ useFruit(Fruit.Apple); }); valid.push({ - name: 'Using a number enum value as a function argument (with a "number enum literal | null" argument type + default)', + name: 'Using a number enum value as a function argument (with a "number enum literal | null" parameter type + default)', code: fruitLiteralFunctionWithUnionAndDefaultDefinition + ` @@ -359,7 +359,7 @@ useFruit(fruit); }); valid.push({ - name: 'Using a null literal as a function argument (with a "number enum literal | null" argument type + default)', + name: 'Using a null literal as a function argument (with a "number enum literal | null" parameter type + default)', code: fruitLiteralFunctionWithUnionAndDefaultDefinition + ` @@ -368,7 +368,7 @@ useFruit(null); }); valid.push({ - name: 'Using a null value as a function argument (with a "number enum literal | null" argument type + default)', + name: 'Using a null value as a function argument (with a "number enum literal | null" parameter type + default)', code: fruitLiteralFunctionWithUnionAndDefaultDefinition + ` @@ -388,7 +388,7 @@ useFruit(0); }); valid.push({ - name: 'Using a number enum literal as a function argument (with a "number enum literal | number enum literal | null" argument type)', + name: 'Using a number enum literal as a function argument (with a "number enum literal | number enum literal | null" parameter type)', code: fruitLiteralFunctionWithComplexUnionDefinition + ` @@ -397,7 +397,7 @@ useFruit(Fruit.Apple); }); valid.push({ - name: 'Using a number enum value as a function argument (with a "number enum literal | number enum literal | null" argument type)', + name: 'Using a number enum value as a function argument (with a "number enum literal | number enum literal | null" parameter type)', code: fruitLiteralFunctionWithComplexUnionDefinition + ` @@ -407,7 +407,7 @@ useFruit(fruit); }); valid.push({ - name: 'Using a null literal as a function argument (with a "number enum literal | number enum literal | null" argument type)', + name: 'Using a null literal as a function argument (with a "number enum literal | number enum literal | null" parameter type)', code: fruitLiteralFunctionWithComplexUnionDefinition + ` @@ -416,7 +416,7 @@ useFruit(null); }); valid.push({ - name: 'Using a null value as a function argument (with a "number enum literal | number enum literal | null" argument type)', + name: 'Using a null value as a function argument (with a "number enum literal | number enum literal | null" parameter type)', code: fruitLiteralFunctionWithComplexUnionDefinition + ` @@ -426,7 +426,7 @@ useFruit(fruit); }); invalid.push({ - name: 'Using a number literal as a function argument (with a "number enum literal | number enum literal | null" argument type)', + name: 'Using a number literal as a function argument (with a "number enum literal | number enum literal | null" parameter type)', code: fruitLiteralFunctionWithComplexUnionDefinition + ` @@ -519,6 +519,26 @@ const fruitClass = new FruitClass(Fruit.Apple); `, }); +valid.push({ + name: 'Using a number enum array as a function argument with an number enum array type', + code: + fruitEnumDefinition + + ` +function useFruitArray(fruitArray: Fruit[]) {} +useFruitArray([Fruit.Apple, Fruit.Banana]); + `, +}); + +valid.push({ + name: 'Using a number enum literal for a function with type parameter of number', + code: + fruitEnumDefinition + + ` +function useNumber(num: number) {} +useNumber(Fruit.Apple); + `, +}); + strictEnumsRuleTester.run('strict-enums-comparison', rule, { valid, invalid, diff --git a/packages/type-utils/src/typeFlagUtils.ts b/packages/type-utils/src/typeFlagUtils.ts index 134fdcf4ece1..cff36fa94c10 100644 --- a/packages/type-utils/src/typeFlagUtils.ts +++ b/packages/type-utils/src/typeFlagUtils.ts @@ -4,8 +4,8 @@ import * as ts from 'typescript'; /** * Gets all of the type flags in a type, iterating through unions automatically */ -export function getTypeFlags(type: ts.Type): ts.TypeFlags { - let flags: ts.TypeFlags = 0; +export function getTypeFlags(type: ts.Type): number { + let flags = 0; for (const t of unionTypeParts(type)) { flags |= t.flags; } @@ -14,11 +14,12 @@ export function getTypeFlags(type: ts.Type): ts.TypeFlags { /** * Checks if the given type is (or accepts) the given flags + * @param flagsToCheck composition of one or more `ts.TypeFlags` * @param isReceiver true if the type is a receiving type (i.e. the type of a called function's parameter) */ export function isTypeFlagSet( type: ts.Type, - flagsToCheck: ts.TypeFlags, + flagsToCheck: number, isReceiver?: boolean, ): boolean { const flags = getTypeFlags(type); From 2406d0379d56972d895076f42628c51fe897f8da Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Fri, 29 Apr 2022 11:43:14 -0400 Subject: [PATCH 11/88] fix: pass string enum literal into function that take string --- packages/eslint-plugin/src/rules/semi.ts | 45 ++++++++++--------- .../sort-type-union-intersection-members.ts | 2 +- .../eslint-plugin/src/rules/strict-enums.ts | 6 +-- .../rules/strict-enums-comparison.test.ts | 26 +---------- .../rules/strict-enums-functions.test.ts | 16 ++++++- .../eslint-plugin/tests/rules/strict-enums.ts | 24 ++++++++++ packages/typescript-estree/src/node-utils.ts | 12 +++++ 7 files changed, 82 insertions(+), 49 deletions(-) diff --git a/packages/eslint-plugin/src/rules/semi.ts b/packages/eslint-plugin/src/rules/semi.ts index 8df56137311f..1d77e7283f92 100644 --- a/packages/eslint-plugin/src/rules/semi.ts +++ b/packages/eslint-plugin/src/rules/semi.ts @@ -2,6 +2,24 @@ import { TSESTree, TSESLint, AST_NODE_TYPES } from '@typescript-eslint/utils'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; import * as util from '../util'; +/** + * The following nodes are handled by the `member-delimiter-style` rule: + * - AST_NODE_TYPES.TSCallSignatureDeclaration + * - AST_NODE_TYPES.TSConstructSignatureDeclaration + * - AST_NODE_TYPES.TSIndexSignature + * - AST_NODE_TYPES.TSMethodSignature + * - AST_NODE_TYPES.TSPropertySignature + */ +const SEMI_AST_NODE_TYPES = [ + AST_NODE_TYPES.PropertyDefinition, + AST_NODE_TYPES.TSAbstractPropertyDefinition, + AST_NODE_TYPES.TSDeclareFunction, + AST_NODE_TYPES.TSExportAssignment, + AST_NODE_TYPES.TSImportEqualsDeclaration, + AST_NODE_TYPES.TSTypeAliasDeclaration, + AST_NODE_TYPES.TSEmptyBodyFunctionExpression, +]; + const baseRule = getESLintCoreRule('semi'); export type Options = util.InferOptionsTypeFromRule; @@ -38,26 +56,13 @@ export default util.createRule({ const checkForSemicolon = rules.ExpressionStatement as TSESLint.RuleFunction; - /* - The following nodes are handled by the member-delimiter-style rule - AST_NODE_TYPES.TSCallSignatureDeclaration, - AST_NODE_TYPES.TSConstructSignatureDeclaration, - AST_NODE_TYPES.TSIndexSignature, - AST_NODE_TYPES.TSMethodSignature, - AST_NODE_TYPES.TSPropertySignature, - */ - const nodesToCheck = [ - AST_NODE_TYPES.PropertyDefinition, - AST_NODE_TYPES.TSAbstractPropertyDefinition, - AST_NODE_TYPES.TSDeclareFunction, - AST_NODE_TYPES.TSExportAssignment, - AST_NODE_TYPES.TSImportEqualsDeclaration, - AST_NODE_TYPES.TSTypeAliasDeclaration, - AST_NODE_TYPES.TSEmptyBodyFunctionExpression, - ].reduce((acc, node) => { - acc[node as string] = checkForSemicolon; - return acc; - }, {}); + const nodesToCheck = SEMI_AST_NODE_TYPES.reduce( + (accumulator, node) => { + accumulator[node as string] = checkForSemicolon; + return accumulator; + }, + {}, + ); return { ...rules, diff --git a/packages/eslint-plugin/src/rules/sort-type-union-intersection-members.ts b/packages/eslint-plugin/src/rules/sort-type-union-intersection-members.ts index fe7f698949c7..6d6321d6ec6d 100644 --- a/packages/eslint-plugin/src/rules/sort-type-union-intersection-members.ts +++ b/packages/eslint-plugin/src/rules/sort-type-union-intersection-members.ts @@ -95,7 +95,7 @@ export type Options = [ { checkIntersections?: boolean; checkUnions?: boolean; - groupOrder?: string[]; + groupOrder?: Group[]; }, ]; export type MessageIds = 'notSorted' | 'notSortedNamed' | 'suggestFix'; diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index a5a796358131..6acac896bf9c 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -370,8 +370,8 @@ export default util.createRule({ } /** - * Allow passing enum values into functions that take in `number`, like - * the following: + * Allow passing enum values into functions that take in `number` or + * `string`, like the following: * * ```ts * function useNumber(num: number) {} @@ -380,7 +380,7 @@ export default util.createRule({ */ for (const paramType of paramTypeSet.values()) { const paramTypeName = getTypeName(paramType); - if (paramTypeName === 'number') { + if (paramTypeName === 'number' || paramTypeName === 'string') { return false; } } diff --git a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts index 98c956af9665..16bb8bfb1ef4 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts @@ -7,35 +7,13 @@ import { fruit2EnumDefinition, fruitEnumDefinition, strictEnumsRuleTester, + vegetable2EnumDefinition, + vegetableEnumDefinition, } from './strict-enums'; const valid: ValidTestCase[] = []; const invalid: InvalidTestCase[] = []; -/** - * A string enum. - * - * String enums are only used for comparison tests, since the TypeScript - * compiler does a good job of ensuring safety for string enum variable - * assignment and usage in functions. - */ -const vegetableEnumDefinition = ` - enum Vegetable { - Lettuce = 'lettuce', - Carrot = 'carrot', - Celery = 'celery', - } - `; - -/** A different string enum. */ -const vegetable2EnumDefinition = ` -enum Vegetable2 { - Lettuce2 = 'lettuce2', - Carrot2 = 'carrot2', - Celery2 = 'celery2', -} -`; - // ---------------------- // COMPARISON TYPES TESTS // ---------------------- diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index 72117c74bd52..39673aca8891 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -3,7 +3,11 @@ import { ValidTestCase, } from '@typescript-eslint/utils/src/ts-eslint'; import rule, { MessageIds } from '../../src/rules/strict-enums'; -import { fruitEnumDefinition, strictEnumsRuleTester } from './strict-enums'; +import { + fruitEnumDefinition, + strictEnumsRuleTester, + vegetableEnumDefinition, +} from './strict-enums'; const valid: ValidTestCase[] = []; const invalid: InvalidTestCase[] = []; @@ -539,6 +543,16 @@ useNumber(Fruit.Apple); `, }); +valid.push({ + name: 'Using a string enum literal for a function with type parameter of string', + code: + vegetableEnumDefinition + + ` +function useString(str: string) {} +useString(Vegetable.Lettuce); + `, +}); + strictEnumsRuleTester.run('strict-enums-comparison', rule, { valid, invalid, diff --git a/packages/eslint-plugin/tests/rules/strict-enums.ts b/packages/eslint-plugin/tests/rules/strict-enums.ts index 1ee7975fa59e..53453a3085f2 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums.ts @@ -27,3 +27,27 @@ enum Fruit2 { Pear2, } `; + +/** + * A string enum. + * + * String enums are almost exclusively used for comparison tests, since the + * TypeScript compiler does a good job of ensuring safety for string enum + * variable assignment and usage in functions. + */ +export const vegetableEnumDefinition = ` + enum Vegetable { + Lettuce = 'lettuce', + Carrot = 'carrot', + Celery = 'celery', + } + `; + +/** A different string enum. */ +export const vegetable2EnumDefinition = ` +enum Vegetable2 { + Lettuce2 = 'lettuce2', + Carrot2 = 'carrot2', + Celery2 = 'celery2', +} +`; diff --git a/packages/typescript-estree/src/node-utils.ts b/packages/typescript-estree/src/node-utils.ts index d8182aa5655e..4055f3dfcb22 100644 --- a/packages/typescript-estree/src/node-utils.ts +++ b/packages/typescript-estree/src/node-utils.ts @@ -32,7 +32,9 @@ export function isAssignmentOperator( operator: ts.Token, ): boolean { return ( + // eslint-disable-next-line @typescript-eslint/strict-enums operator.kind >= SyntaxKind.FirstAssignment && + // eslint-disable-next-line @typescript-eslint/strict-enums operator.kind <= SyntaxKind.LastAssignment ); } @@ -234,6 +236,7 @@ export function getRange(node: ts.Node, ast: ts.SourceFile): [number, number] { */ export function isToken(node: ts.Node): node is ts.Token { return ( + // eslint-disable-next-line @typescript-eslint/strict-enums node.kind >= SyntaxKind.FirstToken && node.kind <= SyntaxKind.LastToken ); } @@ -245,6 +248,7 @@ export function isToken(node: ts.Node): node is ts.Token { */ export function isJSXToken(node: ts.Node): boolean { return ( + // eslint-disable-next-line @typescript-eslint/strict-enums node.kind >= SyntaxKind.JsxElement && node.kind <= SyntaxKind.JsxAttribute ); } @@ -439,7 +443,9 @@ export function getTokenType( if (token.originalKeywordKind === SyntaxKind.NullKeyword) { return AST_TOKEN_TYPES.Null; } else if ( + // eslint-disable-next-line @typescript-eslint/strict-enums token.originalKeywordKind >= SyntaxKind.FirstFutureReservedWord && + // eslint-disable-next-line @typescript-eslint/strict-enums token.originalKeywordKind <= SyntaxKind.LastKeyword ) { return AST_TOKEN_TYPES.Identifier; @@ -448,7 +454,9 @@ export function getTokenType( } if ( + // eslint-disable-next-line @typescript-eslint/strict-enums token.kind >= SyntaxKind.FirstKeyword && + // eslint-disable-next-line @typescript-eslint/strict-enums token.kind <= SyntaxKind.LastFutureReservedWord ) { if ( @@ -462,14 +470,18 @@ export function getTokenType( } if ( + // eslint-disable-next-line @typescript-eslint/strict-enums token.kind >= SyntaxKind.FirstPunctuation && + // eslint-disable-next-line @typescript-eslint/strict-enums token.kind <= SyntaxKind.LastPunctuation ) { return AST_TOKEN_TYPES.Punctuator; } if ( + // eslint-disable-next-line @typescript-eslint/strict-enums token.kind >= SyntaxKind.NoSubstitutionTemplateLiteral && + // eslint-disable-next-line @typescript-eslint/strict-enums token.kind <= SyntaxKind.TemplateTail ) { return AST_TOKEN_TYPES.Template; From 4244376a82888162c0616c452f0b22569fdb8fcc Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Fri, 29 Apr 2022 11:51:08 -0400 Subject: [PATCH 12/88] fix: allow passing enums to functions with any/unknown --- .../src/rules/prefer-optional-chain.ts | 1 + .../eslint-plugin/src/rules/return-await.ts | 2 ++ .../eslint-plugin/src/rules/strict-enums.ts | 13 +++++++++--- .../rules/strict-enums-functions.test.ts | 20 +++++++++++++++++++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/packages/eslint-plugin/src/rules/prefer-optional-chain.ts b/packages/eslint-plugin/src/rules/prefer-optional-chain.ts index b3815e09ef97..d5f812ce71a3 100644 --- a/packages/eslint-plugin/src/rules/prefer-optional-chain.ts +++ b/packages/eslint-plugin/src/rules/prefer-optional-chain.ts @@ -82,6 +82,7 @@ export default util.createRule({ operator, ); + // eslint-disable-next-line @typescript-eslint/strict-enums return leftPrecedence < util.OperatorPrecedence.LeftHandSide; } context.report({ diff --git a/packages/eslint-plugin/src/rules/return-await.ts b/packages/eslint-plugin/src/rules/return-await.ts index d388d84c4809..703912bb89ae 100644 --- a/packages/eslint-plugin/src/rules/return-await.ts +++ b/packages/eslint-plugin/src/rules/return-await.ts @@ -172,6 +172,8 @@ export default util.createRule({ ts.SyntaxKind.AwaitExpression, ts.SyntaxKind.Unknown, ); + + // eslint-disable-next-line @typescript-eslint/strict-enums return nodePrecedence > awaitPrecedence; } diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 6acac896bf9c..afb15f46babb 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -8,6 +8,13 @@ import { import * as ts from 'typescript'; import { TSESTree } from '@typescript-eslint/utils'; +const ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT = new Set([ + 'any', + 'unknown', + 'number', + 'string', +]); + const ALLOWED_ENUM_BINARY_COMPARISON_OPERATORS = new Set(['&', '|']); const ALLOWED_ENUM_NON_BINARY_COMPARISON_OPERATORS = new Set(['===', '!==']); const ALLOWED_ENUM_COMPARISON_OPERATORS = new Set([ @@ -370,8 +377,8 @@ export default util.createRule({ } /** - * Allow passing enum values into functions that take in `number` or - * `string`, like the following: + * Allow passing enum values into functions that take in generic types + * that should basically match any enum, like the following: * * ```ts * function useNumber(num: number) {} @@ -380,7 +387,7 @@ export default util.createRule({ */ for (const paramType of paramTypeSet.values()) { const paramTypeName = getTypeName(paramType); - if (paramTypeName === 'number' || paramTypeName === 'string') { + if (ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT.has(paramTypeName)) { return false; } } diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index 39673aca8891..6ca4a2135035 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -553,6 +553,26 @@ useString(Vegetable.Lettuce); `, }); +valid.push({ + name: 'Using a number enum literal for a function with type parameter of any', + code: + fruitEnumDefinition + + ` +function useSomething(something: any) {} +useSomething(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum literal for a function with type parameter of unknown', + code: + fruitEnumDefinition + + ` +function useSomething(something: unknown) {} +useSomething(Fruit.Apple); + `, +}); + strictEnumsRuleTester.run('strict-enums-comparison', rule, { valid, invalid, From 8b4dcdcf78f2fdbad8b0cc69964fd8f72e47154b Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Fri, 29 Apr 2022 12:17:29 -0400 Subject: [PATCH 13/88] fix: using flags instead of names also fixes for codebase --- .../src/rules/no-confusing-void-expression.ts | 3 +- .../src/rules/no-misused-promises.ts | 2 +- .../no-unnecessary-boolean-literal-compare.ts | 8 +--- .../src/rules/no-unnecessary-condition.ts | 2 +- .../src/rules/no-use-before-define.ts | 2 +- .../non-nullable-type-assertion-style.ts | 4 +- .../src/rules/strict-boolean-expressions.ts | 6 +-- .../eslint-plugin/src/rules/strict-enums.ts | 47 ++++++++----------- packages/type-utils/src/isTypeReadonly.ts | 44 ++++++++--------- 9 files changed, 51 insertions(+), 67 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts b/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts index 0fed18413bd8..e3f3e8eaf3d1 100644 --- a/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts +++ b/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts @@ -1,5 +1,4 @@ import { AST_NODE_TYPES, TSESLint, TSESTree } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -82,7 +81,7 @@ export default util.createRule({ const checker = parserServices.program.getTypeChecker(); const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); const type = util.getConstrainedTypeAtLocation(checker, tsNode); - if (!tsutils.isTypeFlagSet(type, ts.TypeFlags.VoidLike)) { + if (!util.isTypeFlagSet(type, ts.TypeFlags.VoidLike)) { // not a void expression return; } diff --git a/packages/eslint-plugin/src/rules/no-misused-promises.ts b/packages/eslint-plugin/src/rules/no-misused-promises.ts index 03b166ec49b0..55e8c1d005a4 100644 --- a/packages/eslint-plugin/src/rules/no-misused-promises.ts +++ b/packages/eslint-plugin/src/rules/no-misused-promises.ts @@ -549,7 +549,7 @@ function isVoidReturningFunctionType( return false; } - hadVoidReturn ||= tsutils.isTypeFlagSet(returnType, ts.TypeFlags.Void); + hadVoidReturn ||= util.isTypeFlagSet(returnType, ts.TypeFlags.Void); } } diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts b/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts index e3768b28aa06..ae01754294b1 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts @@ -1,5 +1,4 @@ import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -107,7 +106,7 @@ export default util.createRule({ } function isBooleanType(expressionType: ts.Type): boolean { - return tsutils.isTypeFlagSet( + return util.isTypeFlagSet( expressionType, ts.TypeFlags.Boolean | ts.TypeFlags.BooleanLiteral, ); @@ -128,10 +127,7 @@ export default util.createRule({ const nonNullishTypes = types.filter( type => - !tsutils.isTypeFlagSet( - type, - ts.TypeFlags.Undefined | ts.TypeFlags.Null, - ), + !util.isTypeFlagSet(type, ts.TypeFlags.Undefined | ts.TypeFlags.Null), ); const hasNonNullishType = nonNullishTypes.length > 0; diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts index 4e18a9f631e4..ead9a6bea7d2 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts @@ -328,7 +328,7 @@ export default createRule({ if (isStrictNullChecks) { const UNDEFINED = ts.TypeFlags.Undefined; const NULL = ts.TypeFlags.Null; - const isComparable = (type: ts.Type, flag: ts.TypeFlags): boolean => { + const isComparable = (type: ts.Type, flag: number): boolean => { // Allow comparison to `any`, `unknown` or a naked type parameter. flag |= ts.TypeFlags.Any | 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 3a5b51938b79..fb709d7de9d3 100644 --- a/packages/eslint-plugin/src/rules/no-use-before-define.ts +++ b/packages/eslint-plugin/src/rules/no-use-before-define.ts @@ -59,7 +59,7 @@ function isOuterEnum( reference: TSESLint.Scope.Reference, ): boolean { return ( - variable.defs[0].type == DefinitionType.TSEnumName && + variable.defs[0].type === DefinitionType.TSEnumName && variable.scope.variableScope !== reference.from.variableScope ); } diff --git a/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts b/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts index b0649d05745d..c7e7ed1141eb 100644 --- a/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts +++ b/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts @@ -34,9 +34,7 @@ export default util.createRule({ parserServices.esTreeNodeToTSNodeMap.get(node), ); - if ( - tsutils.isTypeFlagSet(type, ts.TypeFlags.Any | ts.TypeFlags.Unknown) - ) { + if (util.isTypeFlagSet(type, ts.TypeFlags.Any | ts.TypeFlags.Unknown)) { return undefined; } diff --git a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts index 9994d887d0a7..4d44f267959e 100644 --- a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts +++ b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts @@ -739,7 +739,7 @@ export default util.createRule({ variantTypes.add('nullish'); } const booleans = types.filter(type => - tsutils.isTypeFlagSet(type, ts.TypeFlags.BooleanLike), + util.isTypeFlagSet(type, ts.TypeFlags.BooleanLike), ); // If incoming type is either "true" or "false", there will be one type @@ -755,7 +755,7 @@ export default util.createRule({ } const strings = types.filter(type => - tsutils.isTypeFlagSet(type, ts.TypeFlags.StringLike), + util.isTypeFlagSet(type, ts.TypeFlags.StringLike), ); if (strings.length) { @@ -815,7 +815,7 @@ export default util.createRule({ variantTypes.add('any'); } - if (types.some(type => tsutils.isTypeFlagSet(type, ts.TypeFlags.Never))) { + if (types.some(type => util.isTypeFlagSet(type, ts.TypeFlags.Never))) { variantTypes.add('never'); } diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index afb15f46babb..908fda991e07 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -1,19 +1,15 @@ import * as util from '../util'; -import { - getCallSignaturesOfType, - isSymbolFlagSet, - isTypeFlagSet, - unionTypeParts, -} from 'tsutils'; +import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import { TSESTree } from '@typescript-eslint/utils'; -const ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT = new Set([ - 'any', - 'unknown', - 'number', - 'string', -]); +const NULL_OR_UNDEFINED = ts.TypeFlags.Null | ts.TypeFlags.Undefined; + +const ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT = + ts.TypeFlags.Any | + ts.TypeFlags.Unknown | + ts.TypeFlags.Number | + ts.TypeFlags.String; const ALLOWED_ENUM_BINARY_COMPARISON_OPERATORS = new Set(['&', '|']); const ALLOWED_ENUM_NON_BINARY_COMPARISON_OPERATORS = new Set(['===', '!==']); @@ -81,7 +77,7 @@ export default util.createRule({ return type; } - if (!isSymbolFlagSet(symbol, ts.SymbolFlags.EnumMember)) { + if (!tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.EnumMember)) { return type; } @@ -114,7 +110,7 @@ export default util.createRule({ * - Fruit --> [Fruit] * - Fruit | Vegetable --> [Fruit, Vegetable] */ - const subTypes = unionTypeParts(type); + const subTypes = tsutils.unionTypeParts(type); /** * Next, we must resolve generic types with constraints. For example: @@ -182,17 +178,11 @@ export default util.createRule({ } function isEnum(type: ts.Type): boolean { - return isTypeFlagSet(type, ts.TypeFlags.EnumLiteral); + return util.isTypeFlagSet(type, ts.TypeFlags.EnumLiteral); } - /** - * Returns true if one or more of the provided types are null or undefined. - */ function isNullOrUndefined(...types: ts.Type[]): boolean { - return types.some(type => { - const typeName = getTypeName(type); - return typeName === 'null' || typeName === 'undefined'; - }); + return types.some(type => util.isTypeFlagSet(type, NULL_OR_UNDEFINED)); } function setHasAnyElement(set: Set, ...elements: T[]): boolean { @@ -211,7 +201,7 @@ export default util.createRule({ function typeSetHasEnum(typeSet: Set): boolean { for (const type of typeSet.values()) { - const subTypes = unionTypeParts(type); + const subTypes = tsutils.unionTypeParts(type); for (const subType of subTypes) { if (isEnum(subType)) { return true; @@ -247,7 +237,7 @@ export default util.createRule({ * There can be potentially multiple signatures for the same function, so * we have to iterate over all of them. */ - const signatures = getCallSignaturesOfType(functionType); + const signatures = tsutils.getCallSignaturesOfType(functionType); /** * Indexed by parameter number. For example, the first function parameter @@ -273,7 +263,7 @@ export default util.createRule({ paramNumToTypesMap.set(i, paramTypeSet); } - const parameterSubTypes = unionTypeParts(parameterType); + const parameterSubTypes = tsutils.unionTypeParts(parameterType); for (const parameterSubType of parameterSubTypes) { paramTypeSet.add(parameterSubType); } @@ -386,13 +376,14 @@ export default util.createRule({ * ``` */ for (const paramType of paramTypeSet.values()) { - const paramTypeName = getTypeName(paramType); - if (ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT.has(paramTypeName)) { + if ( + util.isTypeFlagSet(paramType, ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT) + ) { return false; } } - const argumentSubTypes = unionTypeParts(argumentType); + const argumentSubTypes = tsutils.unionTypeParts(argumentType); /** * Allow function calls that exactly match the function type, like the diff --git a/packages/type-utils/src/isTypeReadonly.ts b/packages/type-utils/src/isTypeReadonly.ts index 3098df3c4359..8b033cf5f524 100644 --- a/packages/type-utils/src/isTypeReadonly.ts +++ b/packages/type-utils/src/isTypeReadonly.ts @@ -1,13 +1,5 @@ import { ESLintUtils } from '@typescript-eslint/utils'; -import { - isConditionalType, - isObjectType, - isUnionType, - unionTypeParts, - isPropertyReadonlyInType, - isSymbolFlagSet, - isIntersectionType, -} from 'tsutils'; +import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import { getTypeOfPropertyOfType } from './propertyTypes'; @@ -131,7 +123,7 @@ function isTypeReadonlyObject( if ( property.valueDeclaration !== undefined && hasSymbol(property.valueDeclaration) && - isSymbolFlagSet( + tsutils.isSymbolFlagSet( property.valueDeclaration.symbol, ts.SymbolFlags.Method, ) @@ -147,13 +139,19 @@ function isTypeReadonlyObject( if ( lastDeclaration !== undefined && hasSymbol(lastDeclaration) && - isSymbolFlagSet(lastDeclaration.symbol, ts.SymbolFlags.Method) + tsutils.isSymbolFlagSet(lastDeclaration.symbol, ts.SymbolFlags.Method) ) { continue; } } - if (isPropertyReadonlyInType(type, property.getEscapedName(), checker)) { + if ( + tsutils.isPropertyReadonlyInType( + type, + property.getEscapedName(), + checker, + ) + ) { continue; } @@ -217,19 +215,21 @@ function isTypeReadonlyRecurser( ): Readonlyness.Readonly | Readonlyness.Mutable { seenTypes.add(type); - if (isUnionType(type)) { + if (tsutils.isUnionType(type)) { // all types in the union must be readonly - const result = unionTypeParts(type).every( - t => - seenTypes.has(t) || - isTypeReadonlyRecurser(checker, t, options, seenTypes) === - Readonlyness.Readonly, - ); + const result = tsutils + .unionTypeParts(type) + .every( + t => + seenTypes.has(t) || + isTypeReadonlyRecurser(checker, t, options, seenTypes) === + Readonlyness.Readonly, + ); const readonlyness = result ? Readonlyness.Readonly : Readonlyness.Mutable; return readonlyness; } - if (isIntersectionType(type)) { + if (tsutils.isIntersectionType(type)) { // Special case for handling arrays/tuples (as readonly arrays/tuples always have mutable methods). if ( type.types.some(t => checker.isArrayType(t) || checker.isTupleType(t)) @@ -255,7 +255,7 @@ function isTypeReadonlyRecurser( } } - if (isConditionalType(type)) { + if (tsutils.isConditionalType(type)) { const result = [type.root.node.trueType, type.root.node.falseType] .map(checker.getTypeFromTypeNode) .every( @@ -271,7 +271,7 @@ function isTypeReadonlyRecurser( // all non-object, non-intersection types are readonly. // this should only be primitive types - if (!isObjectType(type)) { + if (!tsutils.isObjectType(type)) { return Readonlyness.Readonly; } From 12f8120302e6816bf32f08f73136519c3970df7c Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Fri, 29 Apr 2022 13:05:19 -0400 Subject: [PATCH 14/88] fix: adding test that breaks the rule --- .../eslint-plugin/src/rules/strict-enums.ts | 29 +++++++++++++++++-- .../rules/strict-enums-functions.test.ts | 20 +++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 908fda991e07..2893a7d3ed9e 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -3,6 +3,7 @@ import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import { TSESTree } from '@typescript-eslint/utils'; +const TYPE_NAME_TRUNCATION_THRESHOLD = 40; const NULL_OR_UNDEFINED = ts.TypeFlags.Null | ts.TypeFlags.Undefined; const ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT = @@ -44,7 +45,7 @@ export default util.createRule({ mismatchedComparison: 'The two things in the comparison do not have a shared enum type.', mismatchedFunctionArgument: - 'The {{ ordinal }} argument in the function call does not match the declared enum type of the function signature.', + 'The {{ ordinal }} argument in the function call ({{ argumentType}}) does not match the declared enum type of the function signature ({{ parameterType }}).', }, schema: [ { @@ -102,6 +103,7 @@ export default util.createRule({ * - Fruit.Apple | Vegetable.Lettuce --> [Fruit, Vegetable] * - Fruit.Apple | Vegetable.Lettuce | 123 --> [Fruit, Vegetable] * - T extends Fruit --> [Fruit] + * - Array --> [Fruit] */ function getEnumTypes(type: ts.Type): Set { /** @@ -168,8 +170,23 @@ export default util.createRule({ return typeChecker.getTypeAtLocation(tsNode); } - function getTypeName(type: ts.Type): string { - return util.getTypeName(typeChecker, type); + function getTypeName(...types: ts.Type[]): string { + const typeNamesArray = types.map(type => + util.getTypeName(typeChecker, type), + ); + const typeNames = typeNamesArray.join(', '); + if ( + typeNames.length <= TYPE_NAME_TRUNCATION_THRESHOLD || + insideJestTest() // Never truncate in tests + ) { + return typeNames; + } + + const truncatedTypeNames = typeNames.substring( + 0, + TYPE_NAME_TRUNCATION_THRESHOLD, + ); + return `${truncatedTypeNames} [snip]`; } function hasEnumTypes(type: ts.Type): boolean { @@ -177,6 +194,10 @@ export default util.createRule({ return enumTypes.size > 0; } + function insideJestTest(): boolean { + return process.env.JEST_WORKER_ID !== undefined; + } + function isEnum(type: ts.Type): boolean { return util.isTypeFlagSet(type, ts.TypeFlags.EnumLiteral); } @@ -532,6 +553,8 @@ export default util.createRule({ messageId: 'mismatchedFunctionArgument', data: { ordinal: getOrdinalSuffix(i + 1), // e.g. 0 --> 1st + argumentType: getTypeName(argumentType), + parameterType: getTypeName(...paramTypeSet.values()), }, }); } diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index 6ca4a2135035..1c1535e882dc 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -573,6 +573,26 @@ useSomething(Fruit.Apple); `, }); +valid.push({ + name: 'Using a number enum literal for a function with type parameter of enum | enum array', + code: + fruitEnumDefinition + + ` +function useFruitOrFruitArray(fruitOrFruitArray: Fruit | Fruit[]) {} +useFruitOrFruitArray(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum array for a function with type parameter of enum | enum array', + code: + fruitEnumDefinition + + ` +function useFruitOrFruitArray(fruitOrFruitArray: Fruit | Fruit[]) {} +useFruitOrFruitArray([Fruit.Apple]); + `, +}); + strictEnumsRuleTester.run('strict-enums-comparison', rule, { valid, invalid, From e638718e43cbde4ac4d8e73675100f9d71557644 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Fri, 29 Apr 2022 13:54:17 -0400 Subject: [PATCH 15/88] fix: adding test for variadic functions --- .../eslint-plugin/src/rules/no-redeclare.ts | 3 +- .../eslint-plugin/src/rules/strict-enums.ts | 30 ++++++++++++++++++- .../rules/strict-enums-functions.test.ts | 10 +++++++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-redeclare.ts b/packages/eslint-plugin/src/rules/no-redeclare.ts index d81c5225d08b..fbb0ecd170b2 100644 --- a/packages/eslint-plugin/src/rules/no-redeclare.ts +++ b/packages/eslint-plugin/src/rules/no-redeclare.ts @@ -1,3 +1,4 @@ +import { ScopeType } from '@typescript-eslint/scope-manager'; import { TSESTree, TSESLint, AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as util from '../util'; @@ -254,7 +255,7 @@ export default util.createRule({ // Node.js or ES modules has a special scope. if ( - scope.type === 'global' && + scope.type === ScopeType.global && scope.childScopes[0] && // The special scope's block is the Program node. scope.block === scope.childScopes[0].block diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 2893a7d3ed9e..d09c49a50ef6 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -103,7 +103,6 @@ export default util.createRule({ * - Fruit.Apple | Vegetable.Lettuce --> [Fruit, Vegetable] * - Fruit.Apple | Vegetable.Lettuce | 123 --> [Fruit, Vegetable] * - T extends Fruit --> [Fruit] - * - Array --> [Fruit] */ function getEnumTypes(type: ts.Type): Set { /** @@ -198,6 +197,12 @@ export default util.createRule({ return process.env.JEST_WORKER_ID !== undefined; } + function isArray( + type: ts.Type, + ): type is ts.TypeReference | ts.TupleTypeReference { + return typeChecker.isArrayType(type) || typeChecker.isTupleType(type); + } + function isEnum(type: ts.Type): boolean { return util.isTypeFlagSet(type, ts.TypeFlags.EnumLiteral); } @@ -460,6 +465,29 @@ export default util.createRule({ } } + /** + * Allow function calls that have an enum array that "matches" the array + * on the other end, like the following: + * + * ```ts + * function useFruitOrFruitArray(fruitOrFruitArray: Fruit | Fruit[]) {} + * useFruitOrFruitArray([Fruit.Apple]); + * ``` + */ + if (isArray(argumentType)) { + const arrayTypes = typeChecker.getTypeArguments(argumentType); + for (const arrayType of arrayTypes) { + const arrayEnumTypes = getEnumTypes(arrayType); + + for (const paramType of paramTypeSet.values()) { + const paramEnumTypes = getEnumTypes(paramType); + if (setHasAnyElementFromSet(paramEnumTypes, arrayEnumTypes)) { + return false; + } + } + } + } + return true; } diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index 1c1535e882dc..73e973156cdc 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -593,6 +593,16 @@ useFruitOrFruitArray([Fruit.Apple]); `, }); +valid.push({ + name: 'Adding a number enum literal to a number enum array', + code: + fruitEnumDefinition + + ` +const fruits: Fruit[] = []; +fruits.push(Fruit.Apple); + `, +}); + strictEnumsRuleTester.run('strict-enums-comparison', rule, { valid, invalid, From aef971aede14faa857df39564964b78e7d1de2f6 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Fri, 29 Apr 2022 16:27:20 -0400 Subject: [PATCH 16/88] fix: adding isSymbolFlagSet internally --- .../eslint-plugin/src/rules/dot-notation.ts | 4 +- .../src/rules/no-implied-eval.ts | 3 +- .../src/rules/no-unnecessary-qualifier.ts | 3 +- .../rules/no-unnecessary-type-arguments.ts | 3 +- .../eslint-plugin/src/rules/strict-enums.ts | 55 +++++++++++++++++-- .../rules/strict-enums-functions.test.ts | 14 ++--- packages/type-utils/src/isTypeReadonly.ts | 5 +- packages/type-utils/src/typeFlagUtils.ts | 22 +++++++- 8 files changed, 83 insertions(+), 26 deletions(-) diff --git a/packages/eslint-plugin/src/rules/dot-notation.ts b/packages/eslint-plugin/src/rules/dot-notation.ts index 29db2f3fe1e2..5288f9a5b6dc 100644 --- a/packages/eslint-plugin/src/rules/dot-notation.ts +++ b/packages/eslint-plugin/src/rules/dot-notation.ts @@ -99,9 +99,9 @@ export default createRule({ propertySymbol?.getDeclarations()?.[0]?.modifiers?.[0].kind; if ( (allowPrivateClassPropertyAccess && - modifierKind == ts.SyntaxKind.PrivateKeyword) || + modifierKind === ts.SyntaxKind.PrivateKeyword) || (allowProtectedClassPropertyAccess && - modifierKind == ts.SyntaxKind.ProtectedKeyword) + modifierKind === ts.SyntaxKind.ProtectedKeyword) ) { return; } diff --git a/packages/eslint-plugin/src/rules/no-implied-eval.ts b/packages/eslint-plugin/src/rules/no-implied-eval.ts index 54938b9fd490..b4c623deb800 100644 --- a/packages/eslint-plugin/src/rules/no-implied-eval.ts +++ b/packages/eslint-plugin/src/rules/no-implied-eval.ts @@ -1,6 +1,5 @@ import * as ts from 'typescript'; import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; import * as util from '../util'; const FUNCTION_CONSTRUCTOR = 'Function'; @@ -69,7 +68,7 @@ export default util.createRule({ if ( symbol && - tsutils.isSymbolFlagSet( + util.isSymbolFlagSet( symbol, ts.SymbolFlags.Function | ts.SymbolFlags.Method, ) diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts b/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts index dae21746efc8..559c07edee28 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts @@ -1,6 +1,5 @@ import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils'; import * as ts from 'typescript'; -import * as tsutils from 'tsutils'; import * as util from '../util'; export default util.createRule({ @@ -33,7 +32,7 @@ export default util.createRule({ symbol: ts.Symbol, checker: ts.TypeChecker, ): ts.Symbol | null { - return tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.Alias) + return util.isSymbolFlagSet(symbol, ts.SymbolFlags.Alias) ? checker.getAliasedSymbol(symbol) : null; } diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts b/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts index 294adf554adb..6aeda98759d8 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts @@ -1,5 +1,4 @@ import { TSESTree } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; import { findFirstResult } from '../util'; @@ -179,7 +178,7 @@ function getAliasedSymbol( symbol: ts.Symbol, checker: ts.TypeChecker, ): ts.Symbol { - return tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.Alias) + return util.isSymbolFlagSet(symbol, ts.SymbolFlags.Alias) ? checker.getAliasedSymbol(symbol) : symbol; } diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index d09c49a50ef6..a2902b107128 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -78,7 +78,7 @@ export default util.createRule({ return type; } - if (!tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.EnumMember)) { + if (!util.isSymbolFlagSet(symbol, ts.SymbolFlags.EnumMember)) { return type; } @@ -211,6 +211,24 @@ export default util.createRule({ return types.some(type => util.isTypeFlagSet(type, NULL_OR_UNDEFINED)); } + function isRestParameter(parameter: ts.Symbol): boolean { + const declarations = parameter.getDeclarations(); + if (declarations === undefined) { + return false; + } + + for (const declaration of declarations) { + if ( + ts.isParameter(declaration) && + declaration.dotDotDotToken !== undefined + ) { + return true; + } + } + + return false; + } + function setHasAnyElement(set: Set, ...elements: T[]): boolean { return elements.some(element => set.has(element)); } @@ -272,8 +290,9 @@ export default util.createRule({ const paramNumToTypesMap = new Map>(); for (const signature of signatures) { - for (let i = 0; i < signature.parameters.length; i++) { - const parameter = signature.parameters[i]; + const parameters = signature.getParameters(); + for (let i = 0; i < parameters.length; i++) { + const parameter = parameters[i]; if (parameter.valueDeclaration === undefined) { continue; } @@ -283,15 +302,29 @@ export default util.createRule({ parameter.valueDeclaration, ); + /** + * Annoyingly, the type of variadic functions is `Fruit[]` instead of + * `Fruit`, so we must manually convert it. + */ + let parameterTypesToUse: readonly ts.Type[]; + if (isRestParameter(parameter) && isArray(parameterType)) { + parameterTypesToUse = typeChecker.getTypeArguments(parameterType); + } else { + parameterTypesToUse = [parameterType]; + } + let paramTypeSet = paramNumToTypesMap.get(i); if (paramTypeSet === undefined) { paramTypeSet = new Set(); paramNumToTypesMap.set(i, paramTypeSet); } - const parameterSubTypes = tsutils.unionTypeParts(parameterType); - for (const parameterSubType of parameterSubTypes) { - paramTypeSet.add(parameterSubType); + for (const parameterTypeToUse of parameterTypesToUse) { + const parameterSubTypes = + tsutils.unionTypeParts(parameterTypeToUse); + for (const parameterSubType of parameterSubTypes) { + paramTypeSet.add(parameterSubType); + } } } } @@ -488,6 +521,16 @@ export default util.createRule({ } } + /** + * Allow variadic function calls that "match" the array on the other end, + * like the following: + * + * ```ts + * function useFruits(...fruits: Fruit[]) {} + * useFruits(Fruit.Apple); + * ``` + */ + return true; } diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index 73e973156cdc..84340f483f67 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -558,8 +558,8 @@ valid.push({ code: fruitEnumDefinition + ` -function useSomething(something: any) {} -useSomething(Fruit.Apple); +function useAnything(something: any) {} +useAnything(Fruit.Apple); `, }); @@ -568,8 +568,8 @@ valid.push({ code: fruitEnumDefinition + ` -function useSomething(something: unknown) {} -useSomething(Fruit.Apple); +function useUnknown(something: unknown) {} +useUnknown(Fruit.Apple); `, }); @@ -594,12 +594,12 @@ useFruitOrFruitArray([Fruit.Apple]); }); valid.push({ - name: 'Adding a number enum literal to a number enum array', + name: 'Using a number enum literal for a variadic function', code: fruitEnumDefinition + ` -const fruits: Fruit[] = []; -fruits.push(Fruit.Apple); +function useFruits(...fruits: Fruit[]) {} +useFruits(Fruit.Apple); `, }); diff --git a/packages/type-utils/src/isTypeReadonly.ts b/packages/type-utils/src/isTypeReadonly.ts index 8b033cf5f524..c5bc12e6d278 100644 --- a/packages/type-utils/src/isTypeReadonly.ts +++ b/packages/type-utils/src/isTypeReadonly.ts @@ -2,6 +2,7 @@ import { ESLintUtils } from '@typescript-eslint/utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import { getTypeOfPropertyOfType } from './propertyTypes'; +import { isSymbolFlagSet } from './typeFlagUtils'; const enum Readonlyness { /** the type cannot be handled by the function */ @@ -123,7 +124,7 @@ function isTypeReadonlyObject( if ( property.valueDeclaration !== undefined && hasSymbol(property.valueDeclaration) && - tsutils.isSymbolFlagSet( + isSymbolFlagSet( property.valueDeclaration.symbol, ts.SymbolFlags.Method, ) @@ -139,7 +140,7 @@ function isTypeReadonlyObject( if ( lastDeclaration !== undefined && hasSymbol(lastDeclaration) && - tsutils.isSymbolFlagSet(lastDeclaration.symbol, ts.SymbolFlags.Method) + isSymbolFlagSet(lastDeclaration.symbol, ts.SymbolFlags.Method) ) { continue; } diff --git a/packages/type-utils/src/typeFlagUtils.ts b/packages/type-utils/src/typeFlagUtils.ts index cff36fa94c10..cc3e71ea0309 100644 --- a/packages/type-utils/src/typeFlagUtils.ts +++ b/packages/type-utils/src/typeFlagUtils.ts @@ -1,6 +1,12 @@ import { unionTypeParts } from 'tsutils'; import * as ts from 'typescript'; +const ANY_OR_UNKNOWN = ts.TypeFlags.Any | ts.TypeFlags.Unknown; + +function isFlagSet(flags: number, flag: number): boolean { + return (flags & flag) !== 0; +} + /** * Gets all of the type flags in a type, iterating through unions automatically */ @@ -14,7 +20,7 @@ export function getTypeFlags(type: ts.Type): number { /** * Checks if the given type is (or accepts) the given flags - * @param flagsToCheck composition of one or more `ts.TypeFlags` + * @param flagsToCheck The composition of one or more `ts.TypeFlags` * @param isReceiver true if the type is a receiving type (i.e. the type of a called function's parameter) */ export function isTypeFlagSet( @@ -24,9 +30,19 @@ export function isTypeFlagSet( ): boolean { const flags = getTypeFlags(type); - if (isReceiver && flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) { + if (isReceiver && isFlagSet(flags, ANY_OR_UNKNOWN)) { return true; } - return (flags & flagsToCheck) !== 0; + return isFlagSet(flags, flagsToCheck); +} + +/** + * @param flagsToCheck The composition of one or more `ts.SymbolFlags` + */ +export function isSymbolFlagSet( + symbol: ts.Symbol, + flagsToCheck: number, +): boolean { + return isFlagSet(symbol.flags, flagsToCheck); } From 75f60b993f74c69dd8a1a565abebd14f8ad588fe Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Sat, 30 Apr 2022 06:24:05 -0400 Subject: [PATCH 17/88] fix: adding ignoring for remaining lint failures --- .../src/rules/consistent-type-exports.ts | 1 + .../src/rules/no-implied-eval.ts | 1 + .../rules/no-redundant-type-constituents.ts | 3 ++ .../no-unnecessary-boolean-literal-compare.ts | 11 +++-- .../non-nullable-type-assertion-style.ts | 5 ++- packages/eslint-plugin/src/rules/semi.ts | 1 + packages/type-utils/src/typeFlagUtils.ts | 40 ++++++++++++++----- 7 files changed, 45 insertions(+), 17 deletions(-) diff --git a/packages/eslint-plugin/src/rules/consistent-type-exports.ts b/packages/eslint-plugin/src/rules/consistent-type-exports.ts index 36fa561bcb3b..bc8902454e98 100644 --- a/packages/eslint-plugin/src/rules/consistent-type-exports.ts +++ b/packages/eslint-plugin/src/rules/consistent-type-exports.ts @@ -214,6 +214,7 @@ function isSpecifierTypeBased( const symbol = checker.getSymbolAtLocation(node); const aliasedSymbol = checker.getAliasedSymbol(symbol!); + // eslint-disable-next-line @typescript-eslint/strict-enums if (!aliasedSymbol || aliasedSymbol.escapedName === 'unknown') { return undefined; } diff --git a/packages/eslint-plugin/src/rules/no-implied-eval.ts b/packages/eslint-plugin/src/rules/no-implied-eval.ts index b4c623deb800..f3c9616eb67b 100644 --- a/packages/eslint-plugin/src/rules/no-implied-eval.ts +++ b/packages/eslint-plugin/src/rules/no-implied-eval.ts @@ -76,6 +76,7 @@ export default util.createRule({ return true; } + // eslint-disable-next-line @typescript-eslint/strict-enums if (symbol && symbol.escapedName === FUNCTION_CONSTRUCTOR) { const declarations = symbol.getDeclarations() ?? []; for (const declaration of declarations) { diff --git a/packages/eslint-plugin/src/rules/no-redundant-type-constituents.ts b/packages/eslint-plugin/src/rules/no-redundant-type-constituents.ts index 1ee8c3c49594..3c617cc9a8cf 100644 --- a/packages/eslint-plugin/src/rules/no-redundant-type-constituents.ts +++ b/packages/eslint-plugin/src/rules/no-redundant-type-constituents.ts @@ -295,6 +295,7 @@ export default util.createRule({ for (const literalTypeFlag of literalTypeFlags) { if (typePart.typeFlags === literalTypeFlag) { + // eslint-disable-next-line @typescript-eslint/strict-enums addToMapGroup( seenLiteralTypes, literalToPrimitiveTypeFlags[literalTypeFlag], @@ -306,6 +307,7 @@ export default util.createRule({ for (const primitiveTypeFlag of primitiveTypeFlags) { if (typePart.typeFlags === primitiveTypeFlag) { + // eslint-disable-next-line @typescript-eslint/strict-enums addToMapGroup(seenPrimitiveTypes, primitiveTypeFlag, typeNode); } } @@ -387,6 +389,7 @@ export default util.createRule({ for (const literalTypeFlag of literalTypeFlags) { if (typePart.typeFlags === literalTypeFlag) { + // eslint-disable-next-line @typescript-eslint/strict-enums addToMapGroup( seenLiteralTypes, literalToPrimitiveTypeFlags[literalTypeFlag], diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts b/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts index ae01754294b1..2d7742226901 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts @@ -2,6 +2,10 @@ import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils'; import * as ts from 'typescript'; import * as util from '../util'; +const NULL_OR_UNDEFINED = ts.TypeFlags.Undefined | ts.TypeFlags.Null; +const BOOLEAN_OR_BOOLEAN_LITERAL = + ts.TypeFlags.Boolean | ts.TypeFlags.BooleanLiteral; + type MessageIds = | 'direct' | 'negated' @@ -106,9 +110,9 @@ export default util.createRule({ } function isBooleanType(expressionType: ts.Type): boolean { - return util.isTypeFlagSet( + return util.isTypeFlagSetSimple( expressionType, - ts.TypeFlags.Boolean | ts.TypeFlags.BooleanLiteral, + BOOLEAN_OR_BOOLEAN_LITERAL, ); } @@ -126,8 +130,7 @@ export default util.createRule({ const { types } = expressionType; const nonNullishTypes = types.filter( - type => - !util.isTypeFlagSet(type, ts.TypeFlags.Undefined | ts.TypeFlags.Null), + type => !util.isTypeFlagSetSimple(type, NULL_OR_UNDEFINED), ); const hasNonNullishType = nonNullishTypes.length > 0; diff --git a/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts b/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts index c7e7ed1141eb..bd2f91f7ca72 100644 --- a/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts +++ b/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts @@ -1,9 +1,10 @@ import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; - import * as util from '../util'; +const ANY_OR_UNKNOWN = ts.TypeFlags.Any | ts.TypeFlags.Unknown; + export default util.createRule({ name: 'non-nullable-type-assertion-style', meta: { @@ -34,7 +35,7 @@ export default util.createRule({ parserServices.esTreeNodeToTSNodeMap.get(node), ); - if (util.isTypeFlagSet(type, ts.TypeFlags.Any | ts.TypeFlags.Unknown)) { + if (util.isTypeFlagSet(type, ANY_OR_UNKNOWN)) { return undefined; } diff --git a/packages/eslint-plugin/src/rules/semi.ts b/packages/eslint-plugin/src/rules/semi.ts index 1d77e7283f92..3f00395dcde6 100644 --- a/packages/eslint-plugin/src/rules/semi.ts +++ b/packages/eslint-plugin/src/rules/semi.ts @@ -56,6 +56,7 @@ export default util.createRule({ const checkForSemicolon = rules.ExpressionStatement as TSESLint.RuleFunction; + // eslint-disable-next-line @typescript-eslint/strict-enums const nodesToCheck = SEMI_AST_NODE_TYPES.reduce( (accumulator, node) => { accumulator[node as string] = checkForSemicolon; diff --git a/packages/type-utils/src/typeFlagUtils.ts b/packages/type-utils/src/typeFlagUtils.ts index cc3e71ea0309..e69085e9f5cd 100644 --- a/packages/type-utils/src/typeFlagUtils.ts +++ b/packages/type-utils/src/typeFlagUtils.ts @@ -3,10 +3,6 @@ import * as ts from 'typescript'; const ANY_OR_UNKNOWN = ts.TypeFlags.Any | ts.TypeFlags.Unknown; -function isFlagSet(flags: number, flag: number): boolean { - return (flags & flag) !== 0; -} - /** * Gets all of the type flags in a type, iterating through unions automatically */ @@ -18,10 +14,30 @@ export function getTypeFlags(type: ts.Type): number { return flags; } +function isFlagSet(flags: number, flag: number): boolean { + return (flags & flag) !== 0; +} + /** - * Checks if the given type is (or accepts) the given flags - * @param flagsToCheck The composition of one or more `ts.TypeFlags` - * @param isReceiver true if the type is a receiving type (i.e. the type of a called function's parameter) + * @param flagsToCheck The composition of one or more `ts.SymbolFlags` + */ +export function isSymbolFlagSet( + symbol: ts.Symbol, + flagsToCheck: number, +): boolean { + return isFlagSet(symbol.flags, flagsToCheck); +} + +/** + * Checks if the given type is (or accepts) the given flags. + * + * Note that if the type is a union, it will decompose it into the parts and get + * the flags of every union constituent. If this is not desired, use the + * `isTypeFlagSetSimple` function instead. + * + * @param flagsToCheck The composition of one or more `ts.TypeFlags`. + * @param isReceiver True if the type is a receiving type (i.e. the type of a + * called function's parameter). */ export function isTypeFlagSet( type: ts.Type, @@ -38,11 +54,13 @@ export function isTypeFlagSet( } /** - * @param flagsToCheck The composition of one or more `ts.SymbolFlags` + * Similar to the `isTypeFlagSet` function, but does not decompose unions. + * + * This is just a very simple bit flag check. */ -export function isSymbolFlagSet( - symbol: ts.Symbol, +export function isTypeFlagSetSimple( + type: ts.Type, flagsToCheck: number, ): boolean { - return isFlagSet(symbol.flags, flagsToCheck); + return isFlagSet(type.flags, flagsToCheck); } From d784aa03a8b0d9d26c01fb464bd335764f56694d Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Sat, 30 Apr 2022 06:28:54 -0400 Subject: [PATCH 18/88] fix: better comments --- packages/type-utils/src/typeFlagUtils.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/type-utils/src/typeFlagUtils.ts b/packages/type-utils/src/typeFlagUtils.ts index e69085e9f5cd..9ec88423282f 100644 --- a/packages/type-utils/src/typeFlagUtils.ts +++ b/packages/type-utils/src/typeFlagUtils.ts @@ -4,7 +4,7 @@ import * as ts from 'typescript'; const ANY_OR_UNKNOWN = ts.TypeFlags.Any | ts.TypeFlags.Unknown; /** - * Gets all of the type flags in a type, iterating through unions automatically + * Gets all of the type flags in a type, iterating through unions automatically. */ export function getTypeFlags(type: ts.Type): number { let flags = 0; @@ -19,7 +19,7 @@ function isFlagSet(flags: number, flag: number): boolean { } /** - * @param flagsToCheck The composition of one or more `ts.SymbolFlags` + * @param flagsToCheck The composition of one or more `ts.SymbolFlags`. */ export function isSymbolFlagSet( symbol: ts.Symbol, @@ -29,11 +29,9 @@ export function isSymbolFlagSet( } /** - * Checks if the given type is (or accepts) the given flags. - * - * Note that if the type is a union, it will decompose it into the parts and get - * the flags of every union constituent. If this is not desired, use the - * `isTypeFlagSetSimple` function instead. + * Note that if the type is a union, this function will decompose it into the + * parts and get the flags of every union constituent. If this is not desired, + * use the `isTypeFlagSetSimple` function instead. * * @param flagsToCheck The composition of one or more `ts.TypeFlags`. * @param isReceiver True if the type is a receiving type (i.e. the type of a From 811de9856a992d10be1acfcdef3020a9b0f8f264 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Sat, 30 Apr 2022 06:39:03 -0400 Subject: [PATCH 19/88] fix: broken test --- .../src/rules/sort-type-union-intersection-members.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/sort-type-union-intersection-members.ts b/packages/eslint-plugin/src/rules/sort-type-union-intersection-members.ts index 6d6321d6ec6d..fe7f698949c7 100644 --- a/packages/eslint-plugin/src/rules/sort-type-union-intersection-members.ts +++ b/packages/eslint-plugin/src/rules/sort-type-union-intersection-members.ts @@ -95,7 +95,7 @@ export type Options = [ { checkIntersections?: boolean; checkUnions?: boolean; - groupOrder?: Group[]; + groupOrder?: string[]; }, ]; export type MessageIds = 'notSorted' | 'notSortedNamed' | 'suggestFix'; From 9a71d453d29239ff73e5dfb3887b78900f6b897d Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Sat, 30 Apr 2022 06:52:46 -0400 Subject: [PATCH 20/88] fix: adding failing test for generic functions --- .../tests/rules/strict-enums-functions.test.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index 84340f483f67..52c019663cf7 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -603,6 +603,16 @@ useFruits(Fruit.Apple); `, }); +valid.push({ + name: 'Using a number enum literal for a generic function with a default generic type', + code: + fruitEnumDefinition + + ` +function toEqual(expected: E): void {} +toEqual(Fruit.Apple); + `, +}); + strictEnumsRuleTester.run('strict-enums-comparison', rule, { valid, invalid, From f93a02a7497bd3be728101064dcc6756fadf32ab Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Sat, 30 Apr 2022 07:52:29 -0400 Subject: [PATCH 21/88] fix: refactoring tests + adding tests --- .../eslint-plugin/src/rules/strict-enums.ts | 5 +- .../rules/strict-enums-functions.test.ts | 456 ++++++++++++------ 2 files changed, 312 insertions(+), 149 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index a2902b107128..da8e31bdf5f9 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -426,8 +426,9 @@ export default util.createRule({ } /** - * Allow passing enum values into functions that take in generic types - * that should basically match any enum, like the following: + * Allow passing enum values into functions that take in the "any" type + * and similar types that should basically match any enum, like the + * following: * * ```ts * function useNumber(num: number) {} diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index 52c019663cf7..75c5aad6dca0 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -19,72 +19,8 @@ const fruitFunctionDefinition = function useFruit(fruit: Fruit) {} `; -/** A function that takes a number enum literal. */ -const fruitLiteralFunctionDefinition = - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple) {} -`; - -/** A function that takes a number enum with a default argument. */ -const fruitFunctionWithDefaultArgDefinition = - fruitEnumDefinition + - ` -function useFruit(fruit = Fruit.Apple) {} -`; - -/** A function that takes a number enum literal with a default argument. */ -const fruitLiteralFunctionWithDefaultArgDefinition = - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} -`; - -/** A function that takes a number enum with a union. */ -const fruitFunctionWithUnionDefinition = - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null) {} -`; - -/** A function that takes a number enum with a union and a default argument. */ -const fruitFunctionWithUnionAndDefaultDefinition = - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null = Fruit.Apple) {} -`; - -/** A function that takes a number enum literal with a union. */ -const fruitLiteralFunctionWithUnionDefinition = - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null) {} -`; - -/** A function that takes a number enum literal with a union and a default argument. */ -const fruitLiteralFunctionWithUnionAndDefaultDefinition = - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} -`; - -/** A function that takes a number enum literal with a union including two enum types. */ -const fruitLiteralFunctionWithComplexUnionDefinition = - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} -`; - valid.push({ - name: 'Using a normal function without any enums', - code: ` -function useNumber(num: number) {} -useNumber(0); - `, -}); - -valid.push({ - name: 'Using a number enum literal as a function argument', + name: 'Using a number enum literal on a function that takes a number enum', code: fruitFunctionDefinition + ` @@ -93,7 +29,7 @@ useFruit(Fruit.Apple); }); valid.push({ - name: 'Using a number enum value as a function argument', + name: 'Using a number enum value on a function that takes a number enum', code: fruitFunctionDefinition + ` @@ -103,7 +39,7 @@ useFruit(fruit); }); invalid.push({ - name: 'Using a number literal as a function argument', + name: 'Using a number literal on a function that takes a number enum', code: fruitFunctionDefinition + ` @@ -113,336 +49,370 @@ useFruit(0); }); valid.push({ - name: 'Using a number enum literal as a function argument (with an "enum literal" parameter type)', + name: 'Using a number enum literal on a function that takes an enum literal', code: - fruitLiteralFunctionDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple) {} useFruit(Fruit.Apple); `, }); valid.push({ - name: 'Using a number enum value as a function argument (with an "enum literal" parameter type)', + name: 'Using a number enum value on a function that takes an enum literal', code: - fruitLiteralFunctionDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple) {} const fruit = Fruit.Apple; useFruit(fruit); `, }); invalid.push({ - name: 'Using a number literal as a function argument (with an "enum literal" parameter type)', + name: 'Using a number literal on a function that takes an enum literal', code: - fruitLiteralFunctionDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple) {} useFruit(0); `, errors: [{ messageId: 'mismatchedFunctionArgument' }], }); valid.push({ - name: 'Using a number enum literal as a function argument (with a default function argument)', + name: 'Using a number enum literal on a function that takes a number enum with a default argument', code: - fruitFunctionWithDefaultArgDefinition + + fruitEnumDefinition + ` +function useFruit(fruit = Fruit.Apple) {} useFruit(Fruit.Apple); `, }); valid.push({ - name: 'Using a number enum value as a function argument (with a default function argument)', + name: 'Using a number enum value on a function that takes a number enum with a default argument', code: - fruitFunctionWithDefaultArgDefinition + + fruitEnumDefinition + ` +function useFruit(fruit = Fruit.Apple) {} const fruit = Fruit.Apple; useFruit(fruit); `, }); invalid.push({ - name: 'Using a number literal as a function argument (with a default function argument)', + name: 'Using a number literal on a function that takes a number enum with a default argument', code: - fruitFunctionWithDefaultArgDefinition + + fruitEnumDefinition + ` +function useFruit(fruit = Fruit.Apple) {} useFruit(0); `, errors: [{ messageId: 'mismatchedFunctionArgument' }], }); valid.push({ - name: 'Using a number enum literal as a function argument (with a "number literal" arument type + default)', + name: 'Using a number enum literal on a function that takes a number enum literal with a default argument', code: - fruitLiteralFunctionWithDefaultArgDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} useFruit(Fruit.Apple); `, }); valid.push({ - name: 'Using a number enum value as a function argument (with a "number literal" arument type + default)', + name: 'Using a number enum value on a function that takes a number enum literal with a default argument', code: - fruitLiteralFunctionWithDefaultArgDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} const fruit = Fruit.Apple; useFruit(fruit); `, }); invalid.push({ - name: 'Using a number literal as a function argument (with a "number literal" arument type + default)', + name: 'Using a number literal on a function that takes a number enum literal with a default argument', code: - fruitLiteralFunctionWithDefaultArgDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} useFruit(0); `, errors: [{ messageId: 'mismatchedFunctionArgument' }], }); valid.push({ - name: 'Using a number enum literal as a function argument (with a "number enum | null" parameter type)', + name: 'Using a number enum literal on a function that takes a number enum | null', code: - fruitFunctionWithUnionDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit | null) {} useFruit(Fruit.Apple); `, }); valid.push({ - name: 'Using a number enum value as a function argument (with a "number enum | null" parameter type)', + name: 'Using a number enum value on a function that takes a number enum | null', code: - fruitFunctionWithUnionDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit | null) {} const fruit = Fruit.Apple; useFruit(fruit); `, }); valid.push({ - name: 'Using a null literal as a function argument (with a "number enum | null" parameter type)', + name: 'Using a null literal on a function that takes a number enum | null', code: - fruitFunctionWithUnionDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit | null) {} useFruit(null); `, }); valid.push({ - name: 'Using a null value as a function argument (with a "number enum | null" parameter type)', + name: 'Using a null value on a function that takes a number enum | null', code: - fruitFunctionWithUnionDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit | null) {} const fruit = null; useFruit(fruit); `, }); invalid.push({ - name: 'Using a number literal as a function argument (with a "number enum | null" function argument)', + name: 'Using a number literal on a function that takes a number enum | null', code: - fruitFunctionWithUnionDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit | null) {} useFruit(0); `, errors: [{ messageId: 'mismatchedFunctionArgument' }], }); valid.push({ - name: 'Using a number enum literal as a function argument (with a "number enum | null" parameter type + default)', + name: 'Using a number enum literal on a function that takes a number enum | null with a default argument', code: - fruitFunctionWithUnionAndDefaultDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit | null = Fruit.Apple) {} useFruit(Fruit.Apple); `, }); valid.push({ - name: 'Using a number enum value as a function argument (with a "number enum | null" parameter type + default)', + name: 'Using a number enum value on a function that takes a number enum | null with a default argument', code: - fruitFunctionWithUnionAndDefaultDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit | null = Fruit.Apple) {} const fruit = Fruit.Apple; useFruit(fruit); `, }); valid.push({ - name: 'Using a null literal as a function argument (with a "number enum | null" parameter type + default)', + name: 'Using a null literal on a function that takes a number enum | null with a default argument', code: - fruitFunctionWithUnionAndDefaultDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit | null = Fruit.Apple) {} useFruit(null); `, }); valid.push({ - name: 'Using a null value as a function argument (with a "number enum | null" parameter type + default)', + name: 'Using a null value on a function that takes a number enum | null with a default argument', code: - fruitFunctionWithUnionAndDefaultDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit | null = Fruit.Apple) {} const fruit = null; useFruit(fruit); `, }); invalid.push({ - name: 'Using a number literal as a function argument (with a "number enum | null" function argument + default)', + name: 'Using a number literal on a function that takes a number enum | null with a default argument', code: - fruitFunctionWithUnionAndDefaultDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit | null = Fruit.Apple) {} useFruit(0); `, errors: [{ messageId: 'mismatchedFunctionArgument' }], }); valid.push({ - name: 'Using a number enum literal as a function argument (with a "number enum literal | null" parameter type)', + name: 'Using a number enum literal on a function that takes a number enum literal | null', code: - fruitLiteralFunctionWithUnionDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple | null) {} useFruit(Fruit.Apple); `, }); valid.push({ - name: 'Using a number enum value as a function argument (with a "number enum literal | null" parameter type)', + name: 'Using a number enum value on a function that takes a number enum literal | null', code: - fruitLiteralFunctionWithUnionDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple | null) {} const fruit = Fruit.Apple; useFruit(fruit); `, }); valid.push({ - name: 'Using a null literal as a function argument (with a "number enum literal | null" parameter type)', + name: 'Using a null literal on a function that takes a number enum literal | null', code: - fruitLiteralFunctionWithUnionDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple | null) {} useFruit(null); `, }); valid.push({ - name: 'Using a null value as a function argument (with a "number enum literal | null" parameter type)', + name: 'Using a null value on a function that takes a number enum literal | null', code: - fruitLiteralFunctionWithUnionDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple | null) {} const fruit = null; useFruit(fruit); `, }); invalid.push({ - name: 'Using a number literal as a function argument (with a "number enum literal | null" function argument)', + name: 'Using a number literal on a function that takes a number enum literal | null', code: - fruitLiteralFunctionWithUnionDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple | null) {} useFruit(0); `, errors: [{ messageId: 'mismatchedFunctionArgument' }], }); valid.push({ - name: 'Using a number enum literal as a function argument (with a "number enum literal | null" parameter type + default)', + name: 'Using a number enum literal on a function that takes a number enum literal | null with a default argument', code: - fruitLiteralFunctionWithUnionAndDefaultDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} useFruit(Fruit.Apple); `, }); valid.push({ - name: 'Using a number enum value as a function argument (with a "number enum literal | null" parameter type + default)', + name: 'Using a number enum value on a function that takes a number enum literal | null with a default argument', code: - fruitLiteralFunctionWithUnionAndDefaultDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} const fruit = Fruit.Apple; useFruit(fruit); `, }); valid.push({ - name: 'Using a null literal as a function argument (with a "number enum literal | null" parameter type + default)', + name: 'Using a null literal on a function that takes a number enum literal | null with a default argument', code: - fruitLiteralFunctionWithUnionAndDefaultDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} useFruit(null); `, }); valid.push({ - name: 'Using a null value as a function argument (with a "number enum literal | null" parameter type + default)', + name: 'Using a null value on a function that takes a number enum literal | null with a default argument', code: - fruitLiteralFunctionWithUnionAndDefaultDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} const fruit = null; useFruit(fruit); `, }); invalid.push({ - name: 'Using a number literal as a function argument (with a "number enum literal | null" function argument + default)', + name: 'Using a number literal on a function that takes a number enum literal | null with a default argument', code: - fruitLiteralFunctionWithUnionAndDefaultDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} useFruit(0); `, errors: [{ messageId: 'mismatchedFunctionArgument' }], }); valid.push({ - name: 'Using a number enum literal as a function argument (with a "number enum literal | number enum literal | null" parameter type)', + name: 'Using a number enum literal on a function that takes a number enum literal | number enum literal | null', code: - fruitLiteralFunctionWithComplexUnionDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} useFruit(Fruit.Apple); `, }); valid.push({ - name: 'Using a number enum value as a function argument (with a "number enum literal | number enum literal | null" parameter type)', + name: 'Using a number enum value on a function that takes a number enum literal | number enum literal | null', code: - fruitLiteralFunctionWithComplexUnionDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} const fruit = Fruit.Apple; useFruit(fruit); `, }); valid.push({ - name: 'Using a null literal as a function argument (with a "number enum literal | number enum literal | null" parameter type)', + name: 'Using a null literal on a function that takes a number enum literal | number enum literal | null', code: - fruitLiteralFunctionWithComplexUnionDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} useFruit(null); `, }); valid.push({ - name: 'Using a null value as a function argument (with a "number enum literal | number enum literal | null" parameter type)', + name: 'Using a null value on a function that takes a number enum literal | number enum literal | null', code: - fruitLiteralFunctionWithComplexUnionDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} const fruit = null; useFruit(fruit); `, }); invalid.push({ - name: 'Using a number literal as a function argument (with a "number enum literal | number enum literal | null" parameter type)', + name: 'Using a number literal on a function that takes a number enum literal | number enum literal | null', code: - fruitLiteralFunctionWithComplexUnionDefinition + + fruitEnumDefinition + ` +function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} useFruit(0); `, errors: [{ messageId: 'mismatchedFunctionArgument' }], }); valid.push({ - name: 'Using an enum from a composition type as a function argument', + name: 'Using an enum from a composition type on a function that takes a number enum', code: - fruitFunctionDefinition + + fruitEnumDefinition + ` interface BaseNode { type: Fruit; @@ -474,8 +444,23 @@ fruitNodesSet.has(appleNode.type); `, }); +invalid.push({ + name: 'Using a number literal in a Set method', + code: + fruitFunctionDefinition + + ` +const fruitNodesSet = new Set([ + Fruit.Apple, + Fruit.Banana, +]); + +fruitNodesSet.has(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + valid.push({ - name: 'Using a partial union type as a function argument', + name: 'Using a partial union type on a function that takes a number enum', code: fruitFunctionDefinition + ` @@ -485,7 +470,29 @@ useFruit(fruitUnion); }); valid.push({ - name: 'Using a full union type as a function argument', + name: 'Using a partial union type on a function that takes a partial union', + code: + fruitEnumDefinition + + ` +function useFruitSubset(fruit: Fruit.Apple | Fruit.Banana) {} +declare const fruitUnion: Fruit.Apple | Fruit.Banana; +useFruit(fruitUnion); +`, +}); + +invalid.push({ + name: 'Using a number literal on a function that takes a partial union', + code: + fruitEnumDefinition + + ` +function useFruitSubset(fruit: Fruit.Apple | Fruit.Banana) {} +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a full enum union on a function that takes a number enum', code: fruitFunctionDefinition + ` @@ -495,16 +502,37 @@ useFruit(fruitUnion); }); valid.push({ - name: 'Using a partial union type as a function argument (from a type narrowing switch statement)', + name: 'Using a full enum union on a function that takes a full enum union', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | Fruit.Banana | Fruit.Pear) {} +declare const fruitUnion: Fruit.Apple | Fruit.Banana | Fruit.Pear; +useFruit(fruitUnion); +`, +}); + +invalid.push({ + name: 'Using a number literal on a function that takes a full enum union', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | Fruit.Banana | Fruit.Pear) {} +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a partial enum union on a function that takes a number enum (from a type narrowing switch statement)', code: fruitFunctionDefinition + ` -function foo(fruit: Fruit) { - switch (fruit) { - case Fruit.Apple: - case Fruit.Banana: { - useFruit(fruit); - } +declare fruit: Fruit; +switch (fruit) { + case Fruit.Apple: + case Fruit.Banana: { + useFruit(fruit); } } `, @@ -523,6 +551,20 @@ const fruitClass = new FruitClass(Fruit.Apple); `, }); +invalid.push({ + name: 'Using a number literal as a function argument with an enum extension type', + code: + fruitEnumDefinition + + ` +class FruitClass { + constructor(type: FruitType) { + } +} +const fruitClass = new FruitClass(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + valid.push({ name: 'Using a number enum array as a function argument with an number enum array type', code: @@ -533,6 +575,36 @@ useFruitArray([Fruit.Apple, Fruit.Banana]); `, }); +invalid.push({ + name: 'Using a number array as a function argument with an number enum array type', + code: + fruitEnumDefinition + + ` +function useFruitArray(fruitArray: Fruit[]) {} +useFruitArray([0, 1]); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +invalid.push({ + name: 'Using a mixed array as a function argument with an number enum array type', + code: + fruitEnumDefinition + + ` +function useFruitArray(fruitArray: Fruit[]) {} +useFruitArray([Fruit.Apple, 1]); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number literal for a function with type parameter of number', + code: ` +function useNumber(num: number) {} +useNumber(0); + `, +}); + valid.push({ name: 'Using a number enum literal for a function with type parameter of number', code: @@ -543,6 +615,16 @@ useNumber(Fruit.Apple); `, }); +valid.push({ + name: 'Using a string literal for a function with type parameter of string', + code: + vegetableEnumDefinition + + ` +function useString(str: string) {} +useString('lettuce'); + `, +}); + valid.push({ name: 'Using a string enum literal for a function with type parameter of string', code: @@ -553,6 +635,14 @@ useString(Vegetable.Lettuce); `, }); +valid.push({ + name: 'Using a number literal for a function with type parameter of any', + code: ` +function useAnything(something: any) {} +useAnything(0); + `, +}); + valid.push({ name: 'Using a number enum literal for a function with type parameter of any', code: @@ -563,6 +653,14 @@ useAnything(Fruit.Apple); `, }); +valid.push({ + name: 'Using a number literal for a function with type parameter of unknown', + code: ` +function useUnknown(something: unknown) {} +useUnknown(0); + `, +}); + valid.push({ name: 'Using a number enum literal for a function with type parameter of unknown', code: @@ -573,6 +671,17 @@ useUnknown(Fruit.Apple); `, }); +invalid.push({ + name: 'Using a number literal for a function with type parameter of enum | enum array', + code: + fruitEnumDefinition + + ` +function useFruitOrFruitArray(fruitOrFruitArray: Fruit | Fruit[]) {} +useFruitOrFruitArray(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + valid.push({ name: 'Using a number enum literal for a function with type parameter of enum | enum array', code: @@ -593,6 +702,28 @@ useFruitOrFruitArray([Fruit.Apple]); `, }); +invalid.push({ + name: 'Using a number array for a function with type parameter of enum | enum array', + code: + fruitEnumDefinition + + ` +function useFruitOrFruitArray(fruitOrFruitArray: Fruit | Fruit[]) {} +useFruitOrFruitArray([0]); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +invalid.push({ + name: 'Using a number literal for a variadic function', + code: + fruitEnumDefinition + + ` +function useFruits(...fruits: Fruit[]) {} +useFruits(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + valid.push({ name: 'Using a number enum literal for a variadic function', code: @@ -604,7 +735,7 @@ useFruits(Fruit.Apple); }); valid.push({ - name: 'Using a number enum literal for a generic function with a default generic type', + name: 'Using a number enum literal for a generic function with a default generic type that is unspecified', code: fruitEnumDefinition + ` @@ -613,6 +744,37 @@ toEqual(Fruit.Apple); `, }); +valid.push({ + name: 'Using a number enum literal for a generic function with a default generic type that is specified as any', + code: + fruitEnumDefinition + + ` +function toEqual(expected: E): void {} +toEqual(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum literal for a generic function with a default generic type that is specified as a number enum', + code: + fruitEnumDefinition + + ` +function toEqual(expected: E): void {} +toEqual(Fruit.Apple); + `, +}); + +invalid.push({ + name: 'Using a number literal for a generic function with a default generic type that is specified as a number enum', + code: + fruitEnumDefinition + + ` +function toEqual(expected: E): void {} +toEqual(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + strictEnumsRuleTester.run('strict-enums-comparison', rule, { valid, invalid, From 2ced9f8cedea4f4db352123fda905d6402ed6c11 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Sat, 30 Apr 2022 11:16:32 -0400 Subject: [PATCH 22/88] fix: refactoring enum helper function locations --- .../sort-type-union-intersection-members.ts | 2 +- packages/eslint-plugin/src/util/misc.ts | 5 -- .../rules/strict-enums-functions.test.ts | 69 ++++++++++++++++++- packages/type-utils/src/getEnum.ts | 33 +++++++++ packages/type-utils/src/index.ts | 1 + packages/type-utils/src/typeFlagUtils.ts | 19 +++++ 6 files changed, 121 insertions(+), 8 deletions(-) create mode 100644 packages/type-utils/src/getEnum.ts diff --git a/packages/eslint-plugin/src/rules/sort-type-union-intersection-members.ts b/packages/eslint-plugin/src/rules/sort-type-union-intersection-members.ts index fe7f698949c7..3fde2645ec9b 100644 --- a/packages/eslint-plugin/src/rules/sort-type-union-intersection-members.ts +++ b/packages/eslint-plugin/src/rules/sort-type-union-intersection-members.ts @@ -1,6 +1,6 @@ import { AST_NODE_TYPES, TSESLint, TSESTree } from '@typescript-eslint/utils'; +import { getEnumNames } from '@typescript-eslint/type-utils'; import * as util from '../util'; -import { getEnumNames } from '../util'; enum Group { conditional = 'conditional', diff --git a/packages/eslint-plugin/src/util/misc.ts b/packages/eslint-plugin/src/util/misc.ts index 8479feb728dd..0235b6415384 100644 --- a/packages/eslint-plugin/src/util/misc.ts +++ b/packages/eslint-plugin/src/util/misc.ts @@ -145,10 +145,6 @@ type RequireKeys< TKeys extends keyof TObj, > = ExcludeKeys & { [k in TKeys]-?: Exclude }; -function getEnumNames(myEnum: Record): T[] { - return Object.keys(myEnum).filter(x => isNaN(parseInt(x))) as T[]; -} - /** * Given an array of words, returns an English-friendly concatenation, separated with commas, with * the `and` clause inserted before the last item. @@ -174,7 +170,6 @@ export { ExcludeKeys, findFirstResult, formatWordList, - getEnumNames, getNameFromIndexSignature, getNameFromMember, isDefinitionFile, diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index 75c5aad6dca0..b8a94279010f 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -528,7 +528,7 @@ valid.push({ code: fruitFunctionDefinition + ` -declare fruit: Fruit; +declare const fruit: Fruit; switch (fruit) { case Fruit.Apple: case Fruit.Banana: { @@ -734,16 +734,30 @@ useFruits(Fruit.Apple); `, }); +// TODO: failing valid.push({ - name: 'Using a number enum literal for a generic function with a default generic type that is unspecified', + name: 'ZZ Using a number enum literal for a generic function with a default generic type that is unspecified as any', code: fruitEnumDefinition + ` +function a(fruit: Fruit) {} +a(Fruit.Apple); + function toEqual(expected: E): void {} toEqual(Fruit.Apple); `, }); +valid.push({ + name: 'Using a number enum literal for a generic function with a default generic type that is unspecified as a number enum', + code: + fruitEnumDefinition + + ` +function toEqual(expected: E): void {} +toEqual(Fruit.Apple); + `, +}); + valid.push({ name: 'Using a number enum literal for a generic function with a default generic type that is specified as any', code: @@ -775,6 +789,57 @@ toEqual(0); errors: [{ messageId: 'mismatchedFunctionArgument' }], }); +valid.push({ + name: 'Using a number enum literal for a generic function with a default generic type that is unspecified as any + extra arg', + code: + fruitEnumDefinition + + ` +function toEqual(arg1: number, expected: E): void {} +toEqual(0, Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum literal for a generic function with a default generic type that is unspecified as a number enum + extra arg', + code: + fruitEnumDefinition + + ` +function toEqual(arg1: number, expected: E): void {} +toEqual(0, Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum literal for a generic function with a default generic type that is specified as any + extra arg', + code: + fruitEnumDefinition + + ` +function toEqual(arg1: number, expected: E): void {} +toEqual(0, Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum literal for a generic function with a default generic type that is specified as a number enum + extra arg', + code: + fruitEnumDefinition + + ` +function toEqual(arg1: number, expected: E): void {} +toEqual(0, Fruit.Apple); + `, +}); + +invalid.push({ + name: 'Using a number literal for a generic function with a default generic type that is specified as a number enum + extra arg', + code: + fruitEnumDefinition + + ` +function toEqual(arg1: number, expected: E): void {} +toEqual(0, 0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + strictEnumsRuleTester.run('strict-enums-comparison', rule, { valid, invalid, diff --git a/packages/type-utils/src/getEnum.ts b/packages/type-utils/src/getEnum.ts new file mode 100644 index 000000000000..469fb2d03cbb --- /dev/null +++ b/packages/type-utils/src/getEnum.ts @@ -0,0 +1,33 @@ +/** + * Helper function to get only the keys of an enum. + * + * (By default, TypeScript will put the values inside of the keys of a + * number-based enum, so those have to be filtered out.) + * + * This function will work properly for both number and string enums. + */ +function getEnumNames( + transpiledEnum: Record, +): T[] { + const keys = Object.keys(transpiledEnum); + return keys.filter(x => isNaN(parseInt(x, 10))) as T[]; +} + +/** + * Helper function to get the only the values of an enum. + * + * (By default, TypeScript will put the keys inside of the values of a + * number-based enum, so those have to be filtered out.) + * + * This function will work properly for both number and string enums. + */ +function getEnumValues(transpiledEnum: Record): T[] { + const values = Object.values(transpiledEnum); + const numberValues = values.filter(value => typeof value === 'number'); + + // If there are no number values, then this must be a string enum, and no filtration is required + const valuesToReturn = numberValues.length > 0 ? numberValues : values; + return valuesToReturn as T[]; +} + +export { getEnumNames, getEnumValues }; diff --git a/packages/type-utils/src/index.ts b/packages/type-utils/src/index.ts index 44eb35ec945b..02a7e7763854 100644 --- a/packages/type-utils/src/index.ts +++ b/packages/type-utils/src/index.ts @@ -2,6 +2,7 @@ export * from './containsAllTypesByName'; export * from './getConstrainedTypeAtLocation'; export * from './getContextualType'; export * from './getDeclaration'; +export * from './getEnum'; export * from './getSourceFileOfNode'; export * from './getTokenAtPosition'; export * from './getTypeArguments'; diff --git a/packages/type-utils/src/typeFlagUtils.ts b/packages/type-utils/src/typeFlagUtils.ts index 9ec88423282f..ba01dc5bb714 100644 --- a/packages/type-utils/src/typeFlagUtils.ts +++ b/packages/type-utils/src/typeFlagUtils.ts @@ -1,5 +1,6 @@ import { unionTypeParts } from 'tsutils'; import * as ts from 'typescript'; +import { getEnumValues } from './getEnum'; const ANY_OR_UNKNOWN = ts.TypeFlags.Any | ts.TypeFlags.Unknown; @@ -14,6 +15,24 @@ export function getTypeFlags(type: ts.Type): number { return flags; } +/** + * Returns an array containing the names of every type flag that matches the + * given type flags. + * + * Useful for debugging and inspecting the AST. + */ +export function getTypeFlagNames(type: ts.Type): string[] { + const flagNames: string[] = []; + for (const flag of getEnumValues(ts.TypeFlags)) { + if (isTypeFlagSet(type, flag)) { + const flagName = ts.TypeFlags[flag]; + flagNames.push(flagName); + } + } + + return flagNames; +} + function isFlagSet(flags: number, flag: number): boolean { return (flags & flag) !== 0; } From 0695c1b9cbac37009dbfd14e77735deef97dab5e Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Sat, 30 Apr 2022 11:17:31 -0400 Subject: [PATCH 23/88] fix: cleanup --- .../tests/rules/strict-enums-functions.test.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index b8a94279010f..c58978d656cc 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -734,15 +734,11 @@ useFruits(Fruit.Apple); `, }); -// TODO: failing valid.push({ - name: 'ZZ Using a number enum literal for a generic function with a default generic type that is unspecified as any', + name: 'Using a number enum literal for a generic function with a default generic type that is unspecified as any', code: fruitEnumDefinition + ` -function a(fruit: Fruit) {} -a(Fruit.Apple); - function toEqual(expected: E): void {} toEqual(Fruit.Apple); `, From 7272a95cb07aae294826bae66e7f6a9962a6eca7 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Sun, 1 May 2022 10:01:39 -0400 Subject: [PATCH 24/88] fix: refactoring + fixing tests --- .../eslint-plugin/src/rules/strict-enums.ts | 190 +++--------------- .../rules/strict-enums-functions.test.ts | 66 +++--- 2 files changed, 69 insertions(+), 187 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index da8e31bdf5f9..dabfa79955df 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -169,23 +169,20 @@ export default util.createRule({ return typeChecker.getTypeAtLocation(tsNode); } - function getTypeName(...types: ts.Type[]): string { - const typeNamesArray = types.map(type => - util.getTypeName(typeChecker, type), - ); - const typeNames = typeNamesArray.join(', '); + function getTypeName(type: ts.Type): string { + const typeName = util.getTypeName(typeChecker, type); if ( - typeNames.length <= TYPE_NAME_TRUNCATION_THRESHOLD || + typeName.length <= TYPE_NAME_TRUNCATION_THRESHOLD || insideJestTest() // Never truncate in tests ) { - return typeNames; + return typeName; } - const truncatedTypeNames = typeNames.substring( + const truncatedTypeName = typeName.substring( 0, TYPE_NAME_TRUNCATION_THRESHOLD, ); - return `${truncatedTypeNames} [snip]`; + return `${truncatedTypeName} [snip]`; } function hasEnumTypes(type: ts.Type): boolean { @@ -211,28 +208,6 @@ export default util.createRule({ return types.some(type => util.isTypeFlagSet(type, NULL_OR_UNDEFINED)); } - function isRestParameter(parameter: ts.Symbol): boolean { - const declarations = parameter.getDeclarations(); - if (declarations === undefined) { - return false; - } - - for (const declaration of declarations) { - if ( - ts.isParameter(declaration) && - declaration.dotDotDotToken !== undefined - ) { - return true; - } - } - - return false; - } - - function setHasAnyElement(set: Set, ...elements: T[]): boolean { - return elements.some(element => set.has(element)); - } - function setHasAnyElementFromSet(set1: Set, set2: Set): boolean { for (const value of set2.values()) { if (set1.has(value)) { @@ -243,95 +218,10 @@ export default util.createRule({ return false; } - function typeSetHasEnum(typeSet: Set): boolean { - for (const type of typeSet.values()) { - const subTypes = tsutils.unionTypeParts(type); - for (const subType of subTypes) { - if (isEnum(subType)) { - return true; - } - } - } - - return false; - } - // -------------- // Main functions // -------------- - /** - * Given a call expression like `foo(1)`, derive the corresponding - * parameter/argument types of the "real" foo function (as opposed to - * looking at the arguments of the call expression itself). - * - * Note that this function breaks apart types with a union for the purposes - * of inserting each union member in the set. - * - * @returns A `Map` of argument index number to a `Set` of one or more - * types. - */ - function getRealFunctionParameterTypes( - node: TSESTree.CallExpression, - ): Map> { - const functionIdentifier = node.callee; - const functionType = getTypeFromNode(functionIdentifier); - - /** - * There can be potentially multiple signatures for the same function, so - * we have to iterate over all of them. - */ - const signatures = tsutils.getCallSignaturesOfType(functionType); - - /** - * Indexed by parameter number. For example, the first function parameter - * type names are stored at index 0. - */ - const paramNumToTypesMap = new Map>(); - - for (const signature of signatures) { - const parameters = signature.getParameters(); - for (let i = 0; i < parameters.length; i++) { - const parameter = parameters[i]; - if (parameter.valueDeclaration === undefined) { - continue; - } - - const parameterType = typeChecker.getTypeOfSymbolAtLocation( - parameter, - parameter.valueDeclaration, - ); - - /** - * Annoyingly, the type of variadic functions is `Fruit[]` instead of - * `Fruit`, so we must manually convert it. - */ - let parameterTypesToUse: readonly ts.Type[]; - if (isRestParameter(parameter) && isArray(parameterType)) { - parameterTypesToUse = typeChecker.getTypeArguments(parameterType); - } else { - parameterTypesToUse = [parameterType]; - } - - let paramTypeSet = paramNumToTypesMap.get(i); - if (paramTypeSet === undefined) { - paramTypeSet = new Set(); - paramNumToTypesMap.set(i, paramTypeSet); - } - - for (const parameterTypeToUse of parameterTypesToUse) { - const parameterSubTypes = - tsutils.unionTypeParts(parameterTypeToUse); - for (const parameterSubType of parameterSubTypes) { - paramTypeSet.add(parameterSubType); - } - } - } - } - - return paramNumToTypesMap; - } - function isAssigningNonEnumValueToEnumVariable( leftType: ts.Type, rightType: ts.Type, @@ -408,9 +298,10 @@ export default util.createRule({ function isMismatchedEnumFunctionArgument( argumentType: ts.Type, // From the function call - paramTypeSet: Set, // From the function itself + parameterType: ts.Type, // From the function itself ): boolean { const argumentEnumTypes = getEnumTypes(argumentType); + const parameterEnumTypes = getEnumTypes(parameterType); /** * First, allow function calls that have nothing to do with enums, like @@ -421,7 +312,7 @@ export default util.createRule({ * useNumber(0); * ``` */ - if (argumentEnumTypes.size === 0 && !typeSetHasEnum(paramTypeSet)) { + if (argumentEnumTypes.size === 0 && parameterEnumTypes.size === 0) { return false; } @@ -435,15 +326,17 @@ export default util.createRule({ * useNumber(Fruit.Apple); * ``` */ - for (const paramType of paramTypeSet.values()) { - if ( - util.isTypeFlagSet(paramType, ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT) - ) { - return false; - } + if ( + util.isTypeFlagSet(parameterType, ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT) + ) { + return false; } const argumentSubTypes = tsutils.unionTypeParts(argumentType); + const parameterSubTypes = tsutils.unionTypeParts(parameterType); + + const argumentSubTypesSet = new Set(argumentSubTypes); + const parameterSubTypesSet = new Set(parameterSubTypes); /** * Allow function calls that exactly match the function type, like the @@ -462,7 +355,7 @@ export default util.createRule({ * useApple(null); * ``` */ - if (setHasAnyElement(paramTypeSet, ...argumentSubTypes)) { + if (setHasAnyElementFromSet(argumentSubTypesSet, parameterSubTypesSet)) { return false; } @@ -475,30 +368,10 @@ export default util.createRule({ * useFruit(Fruit.Apple); * ``` */ - if (setHasAnyElementFromSet(paramTypeSet, argumentEnumTypes)) { + if (setHasAnyElementFromSet(argumentEnumTypes, parameterEnumTypes)) { return false; } - /** - * Allow function calls that match function types with a union, like the - * following: - * - * ```ts - * function useFruit(fruit: Fruit | null) {} - * useFruit(Fruit.Apple); - * ``` - */ - for (const paramType of paramTypeSet.values()) { - if (!paramType.isUnion()) { - continue; - } - - const paramEnumTypes = getEnumTypes(paramType); - if (setHasAnyElementFromSet(paramEnumTypes, argumentEnumTypes)) { - return false; - } - } - /** * Allow function calls that have an enum array that "matches" the array * on the other end, like the following: @@ -512,12 +385,8 @@ export default util.createRule({ const arrayTypes = typeChecker.getTypeArguments(argumentType); for (const arrayType of arrayTypes) { const arrayEnumTypes = getEnumTypes(arrayType); - - for (const paramType of paramTypeSet.values()) { - const paramEnumTypes = getEnumTypes(paramType); - if (setHasAnyElementFromSet(paramEnumTypes, arrayEnumTypes)) { - return false; - } + if (setHasAnyElementFromSet(arrayEnumTypes, parameterEnumTypes)) { + return false; } } } @@ -531,6 +400,7 @@ export default util.createRule({ * useFruits(Fruit.Apple); * ``` */ + // TODO return true; } @@ -596,7 +466,11 @@ export default util.createRule({ /** When a function is invoked. */ CallExpression(node): void { - const paramNumToTypesMap = getRealFunctionParameterTypes(node); + const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); + const signature = typeChecker.getResolvedSignature(tsNode); + if (signature === undefined) { + return; + } /** * Iterate through the arguments provided to the call function and cross @@ -605,11 +479,7 @@ export default util.createRule({ for (let i = 0; i < node.arguments.length; i++) { const argument = node.arguments[i]; const argumentType = getTypeFromNode(argument); - const paramTypeSet = paramNumToTypesMap.get(i); - if (paramTypeSet === undefined) { - // This should never happen - continue; - } + const parameterType = signature.getTypeParameterAtPosition(i); /** * Disallow mismatched function calls, like the following: @@ -619,14 +489,14 @@ export default util.createRule({ * useFruit(0); * ``` */ - if (isMismatchedEnumFunctionArgument(argumentType, paramTypeSet)) { + if (isMismatchedEnumFunctionArgument(argumentType, parameterType)) { context.report({ node, messageId: 'mismatchedFunctionArgument', data: { ordinal: getOrdinalSuffix(i + 1), // e.g. 0 --> 1st argumentType: getTypeName(argumentType), - parameterType: getTypeName(...paramTypeSet.values()), + parameterType: getTypeName(parameterType), }, }); } diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index c58978d656cc..f4527eca9265 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -19,6 +19,13 @@ const fruitFunctionDefinition = function useFruit(fruit: Fruit) {} `; +valid.push({ + name: 'Using a number enum literal on a non-existent function', + code: ` +useFruit(0); + `, +}); + valid.push({ name: 'Using a number enum literal on a function that takes a number enum', code: @@ -474,7 +481,7 @@ valid.push({ code: fruitEnumDefinition + ` -function useFruitSubset(fruit: Fruit.Apple | Fruit.Banana) {} +function useFruit(fruit: Fruit.Apple | Fruit.Banana) {} declare const fruitUnion: Fruit.Apple | Fruit.Banana; useFruit(fruitUnion); `, @@ -485,7 +492,7 @@ invalid.push({ code: fruitEnumDefinition + ` -function useFruitSubset(fruit: Fruit.Apple | Fruit.Banana) {} +function useFruit(fruit: Fruit.Apple | Fruit.Banana) {} useFruit(0); `, errors: [{ messageId: 'mismatchedFunctionArgument' }], @@ -544,25 +551,30 @@ valid.push({ fruitEnumDefinition + ` class FruitClass { - constructor(type: FruitType) { - } + constructor(type: FruitType) {} + useFruit(type: FruitType) {} } const fruitClass = new FruitClass(Fruit.Apple); - `, +fruitClass.useFruit(Fruit.Apple); +`, }); invalid.push({ - name: 'Using a number literal as a function argument with an enum extension type', + name: 'ZZ Using a number literal as a function argument with an enum extension type', code: fruitEnumDefinition + ` class FruitClass { - constructor(type: FruitType) { - } + constructor(type: FruitType) {} + useFruit(type: FruitType) {} } const fruitClass = new FruitClass(0); +fruitClass.useFruit(0); `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], + errors: [ + { messageId: 'mismatchedAssignment' }, + { messageId: 'mismatchedFunctionArgument' }, + ], }); valid.push({ @@ -570,8 +582,8 @@ valid.push({ code: fruitEnumDefinition + ` -function useFruitArray(fruitArray: Fruit[]) {} -useFruitArray([Fruit.Apple, Fruit.Banana]); +function useFruit(fruitArray: Fruit[]) {} +useFruit([Fruit.Apple, Fruit.Banana]); `, }); @@ -580,8 +592,8 @@ invalid.push({ code: fruitEnumDefinition + ` -function useFruitArray(fruitArray: Fruit[]) {} -useFruitArray([0, 1]); +function useFruit(fruitArray: Fruit[]) {} +useFruit([0, 1]); `, errors: [{ messageId: 'mismatchedFunctionArgument' }], }); @@ -591,8 +603,8 @@ invalid.push({ code: fruitEnumDefinition + ` -function useFruitArray(fruitArray: Fruit[]) {} -useFruitArray([Fruit.Apple, 1]); +function useFruit(fruitArray: Fruit[]) {} +useFruit([Fruit.Apple, 1]); `, errors: [{ messageId: 'mismatchedFunctionArgument' }], }); @@ -676,8 +688,8 @@ invalid.push({ code: fruitEnumDefinition + ` -function useFruitOrFruitArray(fruitOrFruitArray: Fruit | Fruit[]) {} -useFruitOrFruitArray(0); +function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} +useFruit(0); `, errors: [{ messageId: 'mismatchedFunctionArgument' }], }); @@ -687,8 +699,8 @@ valid.push({ code: fruitEnumDefinition + ` -function useFruitOrFruitArray(fruitOrFruitArray: Fruit | Fruit[]) {} -useFruitOrFruitArray(Fruit.Apple); +function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} +useFruit(Fruit.Apple); `, }); @@ -697,8 +709,8 @@ valid.push({ code: fruitEnumDefinition + ` -function useFruitOrFruitArray(fruitOrFruitArray: Fruit | Fruit[]) {} -useFruitOrFruitArray([Fruit.Apple]); +function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} +useFruit([Fruit.Apple]); `, }); @@ -707,8 +719,8 @@ invalid.push({ code: fruitEnumDefinition + ` -function useFruitOrFruitArray(fruitOrFruitArray: Fruit | Fruit[]) {} -useFruitOrFruitArray([0]); +function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} +useFruit([0]); `, errors: [{ messageId: 'mismatchedFunctionArgument' }], }); @@ -718,8 +730,8 @@ invalid.push({ code: fruitEnumDefinition + ` -function useFruits(...fruits: Fruit[]) {} -useFruits(0); +function useFruit(...fruits: Fruit[]) {} +useFruit(0); `, errors: [{ messageId: 'mismatchedFunctionArgument' }], }); @@ -729,8 +741,8 @@ valid.push({ code: fruitEnumDefinition + ` -function useFruits(...fruits: Fruit[]) {} -useFruits(Fruit.Apple); +function useFruit(...fruits: Fruit[]) {} +useFruit(Fruit.Apple); `, }); From 6ed1f66e9b91f3e67cd13761e90eef124f5265c0 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Sun, 1 May 2022 10:38:15 -0400 Subject: [PATCH 25/88] fix: more tests --- .../rules/strict-enums-functions.test.ts | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index f4527eca9265..41566610e782 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -550,6 +550,27 @@ valid.push({ code: fruitEnumDefinition + ` +function useFruit(fruitType: FruitType) {} +useFruit(Fruit.Apple) +`, +}); + +invalid.push({ + name: 'Using a number literal as a function argument with an enum extension type', + code: + fruitEnumDefinition + + ` +function useFruit(fruitType: FruitType) {} +useFruit(0) +`, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum as a class argument with an enum extension type', + code: + fruitEnumDefinition + + ` class FruitClass { constructor(type: FruitType) {} useFruit(type: FruitType) {} @@ -560,7 +581,7 @@ fruitClass.useFruit(Fruit.Apple); }); invalid.push({ - name: 'ZZ Using a number literal as a function argument with an enum extension type', + name: 'Using a number literal as a class argument with an enum extension type', code: fruitEnumDefinition + ` From 83c70e385f3976e965e821cd5a9fa2a66c32bc16 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Sun, 1 May 2022 11:45:03 -0400 Subject: [PATCH 26/88] fix: refactoring and making tests pass --- .../eslint-plugin/src/rules/strict-enums.ts | 124 ++++++++++++------ .../rules/strict-enums-functions.test.ts | 29 +++- 2 files changed, 106 insertions(+), 47 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index dabfa79955df..2c0902806ba3 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -222,6 +222,80 @@ export default util.createRule({ // Main functions // -------------- + function checkCallExpression( + node: TSESTree.CallExpression | TSESTree.NewExpression, + ): void { + const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); + const signature = typeChecker.getResolvedSignature(tsNode); + if (signature === undefined) { + return; + } + + /** + * The `getDeclaration` method actually returns + * `ts.SignatureDeclaration | undefined`, not `ts.SignatureDeclaration`. + */ + const declaration = signature.getDeclaration(); + if (declaration === undefined) { + return; + } + + /** + * Iterate through the arguments provided to the call function and cross + * reference their types to the types of the "real" function parameters. + */ + for (let i = 0; i < node.arguments.length; i++) { + const argument = node.arguments[i]; + const argumentType = getTypeFromNode(argument); + let parameterType = signature.getTypeParameterAtPosition(i); + + /** + * If this function parameter is a generic type that extends another + * type, we want to compare the calling argument to the constraint + * instead. + * + * For example: + * + * ```ts + * function useFruit(fruitType: FruitType) {} + * useFruit(0) + * ``` + * + * Here, we want to compare `Fruit.Apple` to `Fruit`, not `FruitType`, + * because `FruitType` would just be equal to 0 in this case (and + * would be unsafe). + */ + const parameter = declaration.parameters[i]; + if (parameter !== undefined) { + const parameterTSNode = getTypeFromTSNode(parameter); + const constraint = parameterTSNode.getConstraint(); + if (constraint !== undefined) { + parameterType = constraint; + } + } + + /** + * Disallow mismatched function calls, like the following: + * + * ```ts + * function useFruit(fruit: Fruit) {} + * useFruit(0); + * ``` + */ + if (isMismatchedEnumFunctionArgument(argumentType, parameterType)) { + context.report({ + node, + messageId: 'mismatchedFunctionArgument', + data: { + ordinal: getOrdinalSuffix(i + 1), // e.g. 0 --> 1st + argumentType: getTypeName(argumentType), + parameterType: getTypeName(parameterType), + }, + }); + } + } + } + function isAssigningNonEnumValueToEnumVariable( leftType: ts.Type, rightType: ts.Type, @@ -391,17 +465,6 @@ export default util.createRule({ } } - /** - * Allow variadic function calls that "match" the array on the other end, - * like the following: - * - * ```ts - * function useFruits(...fruits: Fruit[]) {} - * useFruits(Fruit.Apple); - * ``` - */ - // TODO - return true; } @@ -466,41 +529,16 @@ export default util.createRule({ /** When a function is invoked. */ CallExpression(node): void { - const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); - const signature = typeChecker.getResolvedSignature(tsNode); - if (signature === undefined) { - return; - } + checkCallExpression(node); + }, + /** When something is instantiated with the "new" keyword. */ + NewExpression(node): void { /** - * Iterate through the arguments provided to the call function and cross - * reference their types to the types of the "real" function parameters. + * We need to perform the exact same checks on a class constructor + * invocation as we do on a normal function invocation. */ - for (let i = 0; i < node.arguments.length; i++) { - const argument = node.arguments[i]; - const argumentType = getTypeFromNode(argument); - const parameterType = signature.getTypeParameterAtPosition(i); - - /** - * Disallow mismatched function calls, like the following: - * - * ```ts - * function useFruit(fruit: Fruit) {} - * useFruit(0); - * ``` - */ - if (isMismatchedEnumFunctionArgument(argumentType, parameterType)) { - context.report({ - node, - messageId: 'mismatchedFunctionArgument', - data: { - ordinal: getOrdinalSuffix(i + 1), // e.g. 0 --> 1st - argumentType: getTypeName(argumentType), - parameterType: getTypeName(parameterType), - }, - }); - } - } + checkCallExpression(node); }, /** When a unary operator is invoked. */ diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index 41566610e782..4e8ea6c54501 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -545,13 +545,33 @@ switch (fruit) { `, }); +valid.push({ + name: 'Using a number enum as a function argument with an extension type', + code: + fruitEnumDefinition + + ` +function useFruit(fruitType: FruitType) {} +useFruit(Fruit.Apple); +`, +}); + +valid.push({ + name: 'Using a number literal as a function argument with an extension type', + code: + fruitEnumDefinition + + ` +function useFruit(fruitType: FruitType) {} +useFruit(0); +`, +}); + valid.push({ name: 'Using a number enum as a function argument with an enum extension type', code: fruitEnumDefinition + ` function useFruit(fruitType: FruitType) {} -useFruit(Fruit.Apple) +useFruit(Fruit.Apple); `, }); @@ -561,7 +581,7 @@ invalid.push({ fruitEnumDefinition + ` function useFruit(fruitType: FruitType) {} -useFruit(0) +useFruit(0); `, errors: [{ messageId: 'mismatchedFunctionArgument' }], }); @@ -593,7 +613,7 @@ const fruitClass = new FruitClass(0); fruitClass.useFruit(0); `, errors: [ - { messageId: 'mismatchedAssignment' }, + { messageId: 'mismatchedFunctionArgument' }, { messageId: 'mismatchedFunctionArgument' }, ], }); @@ -608,8 +628,9 @@ useFruit([Fruit.Apple, Fruit.Banana]); `, }); +// TODO: name invalid.push({ - name: 'Using a number array as a function argument with an number enum array type', + name: 'ZZ Using a number array as a function argument with an number enum array type', code: fruitEnumDefinition + ` From 0ff3096e2bb96cf81c5a5ab3c652d333bbf49c02 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Sun, 1 May 2022 21:04:00 -0400 Subject: [PATCH 27/88] fix: adding array code, all tests pass now --- .../eslint-plugin/src/rules/strict-enums.ts | 167 ++++++++++----- .../rules/strict-enums-assignment.test.ts | 43 +++- .../rules/strict-enums-comparison.test.ts | 3 +- .../rules/strict-enums-functions.test.ts | 194 ++++++++++++++---- 4 files changed, 308 insertions(+), 99 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 2c0902806ba3..e19fb93bffd7 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -43,7 +43,7 @@ export default util.createRule({ mismatchedAssignment: 'The type of the enum assignment ({{ assignmentType }}) does not match the declared enum type ({{ declaredType }}) of the variable.', mismatchedComparison: - 'The two things in the comparison do not have a shared enum type.', + 'The two things in the comparison ({{ leftType }} and {{ rightType }}) do not have a shared enum type.', mismatchedFunctionArgument: 'The {{ ordinal }} argument in the function call ({{ argumentType}}) does not match the declared enum type of the function signature ({{ parameterType }}).', }, @@ -197,7 +197,12 @@ export default util.createRule({ function isArray( type: ts.Type, ): type is ts.TypeReference | ts.TupleTypeReference { - return typeChecker.isArrayType(type) || typeChecker.isTupleType(type); + const typeName = getTypeName(type); + return ( + typeChecker.isArrayType(type) || + typeChecker.isTupleType(type) || + typeName.startsWith('Iterable<') + ); } function isEnum(type: ts.Type): boolean { @@ -300,6 +305,37 @@ export default util.createRule({ leftType: ts.Type, rightType: ts.Type, ): boolean { + // Handle arrays recursively + if (isArray(leftType)) { + const leftArrayType = typeChecker.getTypeArguments(leftType)[0]; + if (leftArrayType === undefined) { + return false; + } + + const rightSubTypes = tsutils.unionTypeParts(rightType); + for (const rightSubType of rightSubTypes) { + if (!isArray(rightSubType)) { + continue; + } + + const rightArrayType = typeChecker.getTypeArguments(rightSubType)[0]; + if (rightArrayType === undefined) { + return false; + } + + if ( + !isAssigningNonEnumValueToEnumVariable( + leftArrayType, + rightArrayType, + ) + ) { + return false; + } + } + + return true; + } + const leftEnumTypes = getEnumTypes(leftType); if (leftEnumTypes.size === 0) { // This is not an enum assignment @@ -374,8 +410,39 @@ export default util.createRule({ argumentType: ts.Type, // From the function call parameterType: ts.Type, // From the function itself ): boolean { - const argumentEnumTypes = getEnumTypes(argumentType); - const parameterEnumTypes = getEnumTypes(parameterType); + const argumentSubTypes = tsutils.unionTypeParts(argumentType); + const parameterSubTypes = tsutils.unionTypeParts(parameterType); + + // Handle arrays recursively + if (isArray(argumentType)) { + const argumentArrayType = typeChecker.getTypeArguments(argumentType)[0]; + if (argumentArrayType === undefined) { + return false; + } + + for (const parameterSubType of parameterSubTypes) { + if (!isArray(parameterSubType)) { + continue; + } + + const parameterArrayType = + typeChecker.getTypeArguments(parameterSubType)[0]; + if (parameterArrayType === undefined) { + return false; + } + + if ( + !isMismatchedEnumFunctionArgument( + argumentArrayType, + parameterArrayType, + ) + ) { + return false; + } + } + + return true; + } /** * First, allow function calls that have nothing to do with enums, like @@ -386,7 +453,9 @@ export default util.createRule({ * useNumber(0); * ``` */ - if (argumentEnumTypes.size === 0 && parameterEnumTypes.size === 0) { + const argumentEnumTypes = getEnumTypes(argumentType); + const parameterEnumTypes = getEnumTypes(parameterType); + if (parameterEnumTypes.size === 0) { return false; } @@ -400,35 +469,44 @@ export default util.createRule({ * useNumber(Fruit.Apple); * ``` */ - if ( - util.isTypeFlagSet(parameterType, ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT) - ) { - return false; + for (const parameterSubType of parameterSubTypes) { + if ( + util.isTypeFlagSet( + parameterSubType, + ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT, + ) + ) { + return false; + } } - const argumentSubTypes = tsutils.unionTypeParts(argumentType); - const parameterSubTypes = tsutils.unionTypeParts(parameterType); - - const argumentSubTypesSet = new Set(argumentSubTypes); - const parameterSubTypesSet = new Set(parameterSubTypes); - /** - * Allow function calls that exactly match the function type, like the - * following: + * Disallow passing number literals or string literals into functions that + * take in an enum, like the following: * * ```ts - * function useApple(apple: Fruit.Apple) {} - * useApple(Fruit.Apple); + * function useFruit(fruit: Fruit) {} + * declare const fruit: Fruit.Apple | 1; + * useFruit(fruit) * ``` - * - * Additionally, allow function calls that match one of the types in a - * union, like the following: + */ + for (const argumentSubType of argumentSubTypes) { + if (argumentSubType.isLiteral() && !isEnum(argumentSubType)) { + return true; + } + } + + /** + * Allow function calls that match one of the types in a union, like the + * following: * * ```ts - * function useApple(apple: Fruit.Apple | null) {} + * function useApple(fruitOrNull: Fruit | null) {} * useApple(null); * ``` */ + const argumentSubTypesSet = new Set(argumentSubTypes); + const parameterSubTypesSet = new Set(parameterSubTypes); if (setHasAnyElementFromSet(argumentSubTypesSet, parameterSubTypesSet)) { return false; } @@ -438,7 +516,7 @@ export default util.createRule({ * type, like the following: * * ```ts - * function useFruit(apple: Fruit) {} + * function useFruit(fruit: Fruit) {} * useFruit(Fruit.Apple); * ``` */ @@ -446,25 +524,6 @@ export default util.createRule({ return false; } - /** - * Allow function calls that have an enum array that "matches" the array - * on the other end, like the following: - * - * ```ts - * function useFruitOrFruitArray(fruitOrFruitArray: Fruit | Fruit[]) {} - * useFruitOrFruitArray([Fruit.Apple]); - * ``` - */ - if (isArray(argumentType)) { - const arrayTypes = typeChecker.getTypeArguments(argumentType); - for (const arrayType of arrayTypes) { - const arrayEnumTypes = getEnumTypes(arrayType); - if (setHasAnyElementFromSet(arrayEnumTypes, parameterEnumTypes)) { - return false; - } - } - } - return true; } @@ -483,8 +542,8 @@ export default util.createRule({ node, messageId: 'mismatchedAssignment', data: { - assignmentType: getTypeName(leftType), - declaredType: getTypeName(rightType), + assignmentType: getTypeName(rightType), + declaredType: getTypeName(leftType), }, }); } @@ -523,7 +582,14 @@ export default util.createRule({ rightEnumTypes, ) ) { - context.report({ node, messageId: 'mismatchedComparison' }); + context.report({ + node, + messageId: 'mismatchedComparison', + data: { + leftType: getTypeName(leftType), + rightType: getTypeName(rightType), + }, + }); } }, @@ -597,7 +663,14 @@ export default util.createRule({ } if (isAssigningNonEnumValueToEnumVariable(leftType, rightType)) { - context.report({ node, messageId: 'mismatchedAssignment' }); + context.report({ + node, + messageId: 'mismatchedAssignment', + data: { + assignmentType: getTypeName(rightType), + declaredType: getTypeName(leftType), + }, + }); } } }, diff --git a/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts index 5596298d4c25..041079d9bd80 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts @@ -163,7 +163,7 @@ const fruitCopy: Fruit = fruit; }); valid.push({ - name: 'Assignment to variables with a composition type that includes individual enum values', + name: 'Assigning variables with a composition type that includes individual enum values', code: ` enum Foo { A = 1, @@ -187,7 +187,7 @@ const z: Foo.A | Foo.B | Foo.C | Foo.D = foo; * doing and allow it. */ valid.push({ - name: 'Assignment to a variable with a intersection enum type', + name: 'Assigning a variable with a intersection enum type', code: fruitEnumDefinition + fruit2EnumDefinition + @@ -197,11 +197,8 @@ const foo: Fruit & Fruit2 = Fruit.Apple; }); valid.push({ - name: 'Assignment to a variable with a composition of binary flags', - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` + name: 'Assigning to a variable with a composition of binary flags', + code: ` enum Flag { Value1 = 1 << 0, Value2 = 1 << 1, @@ -210,6 +207,38 @@ const flags = Flag.Value1 | Flag.Value2; `, }); +valid.push({ + name: 'Assigning a number enum array to a variable with a number enum array', + code: + fruitEnumDefinition + + ` +declare let fruits: Fruit[]; +fruits = [Fruit.Apple, Fruit.Banana]; + `, +}); + +valid.push({ + name: 'Assigning a number enum array to a variable with a number array', + code: + fruitEnumDefinition + + ` +declare let numbers: number[]; +numbers = [Fruit.Apple, Fruit.Banana]; + `, +}); + +invalid.push({ + name: 'Assigning a number array to a variable with a number enum array', + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` +declare let fruits: Fruit[]; +fruits = [0, 1]; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + strictEnumsRuleTester.run('strict-enums-assignment', rule, { valid, invalid, diff --git a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts index 16bb8bfb1ef4..8d7dfd391268 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts @@ -246,8 +246,9 @@ if (vegetable === Vegetable2.Lettuce2) { errors: [{ messageId: 'mismatchedComparison' }], }); +// TODO valid.push({ - name: 'Comparing a generic enum extension value with a number enum literal', + name: 'ZZ Comparing a generic enum extension value with a number enum literal', code: fruitEnumDefinition + ` diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index 4e8ea6c54501..1711724d9783 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -40,7 +40,7 @@ valid.push({ code: fruitFunctionDefinition + ` -const fruit = Fruit.Apple; +declare const fruit: Fruit.Apple; useFruit(fruit); `, }); @@ -56,7 +56,7 @@ useFruit(0); }); valid.push({ - name: 'Using a number enum literal on a function that takes an enum literal', + name: 'Using a matching number enum literal on a function that takes an enum literal', code: fruitEnumDefinition + ` @@ -65,13 +65,42 @@ useFruit(Fruit.Apple); `, }); +/** + * The TypeScript compiler will correctly handle this case, so the lint rule + * does not need to care. + */ valid.push({ - name: 'Using a number enum value on a function that takes an enum literal', + name: 'Using a non-matching number enum literal on a function that takes an enum literal', code: fruitEnumDefinition + ` function useFruit(fruit: Fruit.Apple) {} -const fruit = Fruit.Apple; +useFruit(Fruit.Banana); + `, +}); + +valid.push({ + name: 'Using a matching number enum value on a function that takes an enum literal', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple) {} +declare const fruit: Fruit.Apple; +useFruit(fruit); + `, +}); + +/** + * The TypeScript compiler will correctly handle this case, so the lint rule + * does not need to care. + */ +valid.push({ + name: 'Using a non-matching number enum value on a function that takes an enum literal', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple) {} +declare const fruit: Fruit.Banana; useFruit(fruit); `, }); @@ -451,17 +480,31 @@ fruitNodesSet.has(appleNode.type); `, }); +valid.push({ + name: 'Using an enum number literal in a Set method', + code: + fruitEnumDefinition + + ` +const fruitSet = new Set([ + Fruit.Apple, + Fruit.Banana, +]); + +fruitSet.has(Fruit.Apple); + `, +}); + invalid.push({ name: 'Using a number literal in a Set method', code: - fruitFunctionDefinition + + fruitEnumDefinition + ` -const fruitNodesSet = new Set([ +const fruitSet = new Set([ Fruit.Apple, Fruit.Banana, ]); -fruitNodesSet.has(0); +fruitSet.has(0); `, errors: [{ messageId: 'mismatchedFunctionArgument' }], }); @@ -546,7 +589,7 @@ switch (fruit) { }); valid.push({ - name: 'Using a number enum as a function argument with an extension type', + name: 'Using a number enum on a function that takes an extension type', code: fruitEnumDefinition + ` @@ -556,7 +599,7 @@ useFruit(Fruit.Apple); }); valid.push({ - name: 'Using a number literal as a function argument with an extension type', + name: 'Using a number literal on a function that takes an extension type', code: fruitEnumDefinition + ` @@ -566,7 +609,7 @@ useFruit(0); }); valid.push({ - name: 'Using a number enum as a function argument with an enum extension type', + name: 'Using a number enum on a function that takes an enum extension type', code: fruitEnumDefinition + ` @@ -576,7 +619,7 @@ useFruit(Fruit.Apple); }); invalid.push({ - name: 'Using a number literal as a function argument with an enum extension type', + name: 'Using a number literal on a function that takes an enum extension type', code: fruitEnumDefinition + ` @@ -587,7 +630,7 @@ useFruit(0); }); valid.push({ - name: 'Using a number enum as a class argument with an enum extension type', + name: 'Using a number enum on a function that takes an enum extension type', code: fruitEnumDefinition + ` @@ -601,7 +644,7 @@ fruitClass.useFruit(Fruit.Apple); }); invalid.push({ - name: 'Using a number literal as a class argument with an enum extension type', + name: 'Using a number literal on a function that takes an enum extension type', code: fruitEnumDefinition + ` @@ -619,7 +662,17 @@ fruitClass.useFruit(0); }); valid.push({ - name: 'Using a number enum array as a function argument with an number enum array type', + name: 'Using a number array on a function that takes a number array', + code: + fruitEnumDefinition + + ` +function useNumbers(numberArray: number[]) {} +useNumbers([0, 1]); + `, +}); + +valid.push({ + name: 'Using a number enum array on a function that takes a number enum array', code: fruitEnumDefinition + ` @@ -628,9 +681,8 @@ useFruit([Fruit.Apple, Fruit.Banana]); `, }); -// TODO: name invalid.push({ - name: 'ZZ Using a number array as a function argument with an number enum array type', + name: 'Using a number array on a function that takes a number enum array', code: fruitEnumDefinition + ` @@ -641,7 +693,7 @@ useFruit([0, 1]); }); invalid.push({ - name: 'Using a mixed array as a function argument with an number enum array type', + name: 'Using a mixed array on a function that takes a number enum array', code: fruitEnumDefinition + ` @@ -652,7 +704,7 @@ useFruit([Fruit.Apple, 1]); }); valid.push({ - name: 'Using a number literal for a function with type parameter of number', + name: 'Using a number literal on a function that takes a number', code: ` function useNumber(num: number) {} useNumber(0); @@ -660,7 +712,7 @@ useNumber(0); }); valid.push({ - name: 'Using a number enum literal for a function with type parameter of number', + name: 'Using a number enum literal on a function that takes a number', code: fruitEnumDefinition + ` @@ -670,7 +722,7 @@ useNumber(Fruit.Apple); }); valid.push({ - name: 'Using a string literal for a function with type parameter of string', + name: 'Using a string literal on a function that takes a string', code: vegetableEnumDefinition + ` @@ -680,7 +732,7 @@ useString('lettuce'); }); valid.push({ - name: 'Using a string enum literal for a function with type parameter of string', + name: 'Using a string enum literal on a function that takes a string', code: vegetableEnumDefinition + ` @@ -690,7 +742,7 @@ useString(Vegetable.Lettuce); }); valid.push({ - name: 'Using a number literal for a function with type parameter of any', + name: 'Using a number literal on a function that takes any', code: ` function useAnything(something: any) {} useAnything(0); @@ -698,7 +750,7 @@ useAnything(0); }); valid.push({ - name: 'Using a number enum literal for a function with type parameter of any', + name: 'Using a number enum literal on a function that takes any', code: fruitEnumDefinition + ` @@ -708,7 +760,7 @@ useAnything(Fruit.Apple); }); valid.push({ - name: 'Using a number literal for a function with type parameter of unknown', + name: 'Using a number literal on a function that takes unknown', code: ` function useUnknown(something: unknown) {} useUnknown(0); @@ -716,7 +768,7 @@ useUnknown(0); }); valid.push({ - name: 'Using a number enum literal for a function with type parameter of unknown', + name: 'Using a number enum literal on a function that takes unknown', code: fruitEnumDefinition + ` @@ -726,7 +778,7 @@ useUnknown(Fruit.Apple); }); invalid.push({ - name: 'Using a number literal for a function with type parameter of enum | enum array', + name: 'Using a number literal on a function that takes enum | enum array', code: fruitEnumDefinition + ` @@ -737,7 +789,7 @@ useFruit(0); }); valid.push({ - name: 'Using a number enum literal for a function with type parameter of enum | enum array', + name: 'Using a number enum literal on a function that takes enum | enum array', code: fruitEnumDefinition + ` @@ -747,28 +799,70 @@ useFruit(Fruit.Apple); }); valid.push({ - name: 'Using a number enum array for a function with type parameter of enum | enum array', + name: 'Using a number enum array on a function that takes enum | enum array', code: fruitEnumDefinition + ` function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} -useFruit([Fruit.Apple]); +useFruit([Fruit.Apple, Fruit.Banana]); + `, +}); + +valid.push({ + name: 'Using a enum | enum array union on a function that takes enum | enum array', + code: + fruitEnumDefinition + + ` +function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} +declare const fruit: Fruit | Fruit[]; +useFruit(fruit); `, }); invalid.push({ - name: 'Using a number array for a function with type parameter of enum | enum array', + name: 'Using a number array on a function that takes enum | enum array', code: fruitEnumDefinition + ` function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} -useFruit([0]); +useFruit([0, 1]); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number on a function that takes number | enum array', + code: + fruitEnumDefinition + + ` +function useFruit(fruitOrFruitArray: number | Fruit[]) {} +useFruit(0); + `, +}); + +valid.push({ + name: 'Using an enum array on a function that takes number | enum array', + code: + fruitEnumDefinition + + ` +function useFruit(fruitOrFruitArray: number | Fruit[]) {} +useFruit([Fruit.Apple, Fruit.Banana]); + `, +}); + +invalid.push({ + name: 'Using a number array on a function that takes number | enum array', + code: + fruitEnumDefinition + + ` +function useFruit(fruitOrFruitArray: number | Fruit[]) {} +useFruit([0, 1]); `, errors: [{ messageId: 'mismatchedFunctionArgument' }], }); invalid.push({ - name: 'Using a number literal for a variadic function', + name: 'Using a number literal on a variadic function', code: fruitEnumDefinition + ` @@ -779,17 +873,29 @@ useFruit(0); }); valid.push({ - name: 'Using a number enum literal for a variadic function', + name: 'Using a number enum literal on a variadic function', code: fruitEnumDefinition + ` function useFruit(...fruits: Fruit[]) {} useFruit(Fruit.Apple); +useFruit(Fruit.Apple, Fruit.Banana); + `, +}); + +invalid.push({ + name: 'Using a number enum literal and a number literal on a variadic function', + code: + fruitEnumDefinition + + ` +function useFruit(...fruits: Fruit[]) {} +useFruit(Fruit.Apple, 0); `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], }); valid.push({ - name: 'Using a number enum literal for a generic function with a default generic type that is unspecified as any', + name: 'Using a number enum literal on a generic function with a default generic type that is unspecified as any', code: fruitEnumDefinition + ` @@ -799,7 +905,7 @@ toEqual(Fruit.Apple); }); valid.push({ - name: 'Using a number enum literal for a generic function with a default generic type that is unspecified as a number enum', + name: 'Using a number enum literal on a generic function with a default generic type that is unspecified as a number enum', code: fruitEnumDefinition + ` @@ -809,7 +915,7 @@ toEqual(Fruit.Apple); }); valid.push({ - name: 'Using a number enum literal for a generic function with a default generic type that is specified as any', + name: 'Using a number enum literal on a generic function with a default generic type that is specified as any', code: fruitEnumDefinition + ` @@ -819,7 +925,7 @@ toEqual(Fruit.Apple); }); valid.push({ - name: 'Using a number enum literal for a generic function with a default generic type that is specified as a number enum', + name: 'Using a number enum literal on a generic function with a default generic type that is specified as a number enum', code: fruitEnumDefinition + ` @@ -829,7 +935,7 @@ toEqual(Fruit.Apple); }); invalid.push({ - name: 'Using a number literal for a generic function with a default generic type that is specified as a number enum', + name: 'Using a number literal on a generic function with a default generic type that is specified as a number enum', code: fruitEnumDefinition + ` @@ -840,7 +946,7 @@ toEqual(0); }); valid.push({ - name: 'Using a number enum literal for a generic function with a default generic type that is unspecified as any + extra arg', + name: 'Using a number enum literal on a generic function with a default generic type that is unspecified as any + extra arg', code: fruitEnumDefinition + ` @@ -850,7 +956,7 @@ toEqual(0, Fruit.Apple); }); valid.push({ - name: 'Using a number enum literal for a generic function with a default generic type that is unspecified as a number enum + extra arg', + name: 'Using a number enum literal on a generic function with a default generic type that is unspecified as a number enum + extra arg', code: fruitEnumDefinition + ` @@ -860,7 +966,7 @@ toEqual(0, Fruit.Apple); }); valid.push({ - name: 'Using a number enum literal for a generic function with a default generic type that is specified as any + extra arg', + name: 'Using a number enum literal on a generic function with a default generic type that is specified as any + extra arg', code: fruitEnumDefinition + ` @@ -870,7 +976,7 @@ toEqual(0, Fruit.Apple); }); valid.push({ - name: 'Using a number enum literal for a generic function with a default generic type that is specified as a number enum + extra arg', + name: 'Using a number enum literal on a generic function with a default generic type that is specified as a number enum + extra arg', code: fruitEnumDefinition + ` @@ -880,7 +986,7 @@ toEqual(0, Fruit.Apple); }); invalid.push({ - name: 'Using a number literal for a generic function with a default generic type that is specified as a number enum + extra arg', + name: 'Using a number literal on a generic function with a default generic type that is specified as a number enum + extra arg', code: fruitEnumDefinition + ` @@ -890,7 +996,7 @@ toEqual(0, 0); errors: [{ messageId: 'mismatchedFunctionArgument' }], }); -strictEnumsRuleTester.run('strict-enums-comparison', rule, { +strictEnumsRuleTester.run('strict-enums-functions', rule, { valid, invalid, }); From ddebded0c4a5bcb3603185ca8e06f29490061046 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Sun, 1 May 2022 21:59:01 -0400 Subject: [PATCH 28/88] fix: adding failing test --- .../src/rules/no-redundant-type-constituents.ts | 3 --- .../tests/rules/strict-enums-assignment.test.ts | 10 ++++++++++ .../tests/rules/strict-enums-functions.test.ts | 11 +++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-redundant-type-constituents.ts b/packages/eslint-plugin/src/rules/no-redundant-type-constituents.ts index 3c617cc9a8cf..1ee8c3c49594 100644 --- a/packages/eslint-plugin/src/rules/no-redundant-type-constituents.ts +++ b/packages/eslint-plugin/src/rules/no-redundant-type-constituents.ts @@ -295,7 +295,6 @@ export default util.createRule({ for (const literalTypeFlag of literalTypeFlags) { if (typePart.typeFlags === literalTypeFlag) { - // eslint-disable-next-line @typescript-eslint/strict-enums addToMapGroup( seenLiteralTypes, literalToPrimitiveTypeFlags[literalTypeFlag], @@ -307,7 +306,6 @@ export default util.createRule({ for (const primitiveTypeFlag of primitiveTypeFlags) { if (typePart.typeFlags === primitiveTypeFlag) { - // eslint-disable-next-line @typescript-eslint/strict-enums addToMapGroup(seenPrimitiveTypes, primitiveTypeFlag, typeNode); } } @@ -389,7 +387,6 @@ export default util.createRule({ for (const literalTypeFlag of literalTypeFlags) { if (typePart.typeFlags === literalTypeFlag) { - // eslint-disable-next-line @typescript-eslint/strict-enums addToMapGroup( seenLiteralTypes, literalToPrimitiveTypeFlags[literalTypeFlag], diff --git a/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts index 041079d9bd80..cb2893631d47 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts @@ -239,6 +239,16 @@ fruits = [0, 1]; errors: [{ messageId: 'mismatchedAssignment' }], }); +valid.push({ + name: 'Assigning an empty array to a variable with a number enum array', + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` +const fruitArray: Fruit[] = []; + `, +}); + strictEnumsRuleTester.run('strict-enums-assignment', rule, { valid, invalid, diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index 1711724d9783..69f9d5162a97 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -996,6 +996,17 @@ toEqual(0, 0); errors: [{ messageId: 'mismatchedFunctionArgument' }], }); +valid.push({ + name: 'Using JSON.stringify', + code: ` +JSON.stringify( + {}, + (_, value: unknown) => value ?? undefined, + 2, +); + `, +}); + strictEnumsRuleTester.run('strict-enums-functions', rule, { valid, invalid, From c8b239b9a4727ea7a5bdc64c1032591325892fa7 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Sun, 1 May 2022 22:03:01 -0400 Subject: [PATCH 29/88] fix: allow empty arrays --- packages/eslint-plugin/src/rules/strict-enums.ts | 15 +++++++++++++++ .../tests/rules/strict-enums-assignment.test.ts | 2 -- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index e19fb93bffd7..946cbca8cac4 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -209,6 +209,10 @@ export default util.createRule({ return util.isTypeFlagSet(type, ts.TypeFlags.EnumLiteral); } + function isNever(type: ts.Type): boolean { + return util.isTypeFlagSet(type, ts.TypeFlags.Never); + } + function isNullOrUndefined(...types: ts.Type[]): boolean { return types.some(type => util.isTypeFlagSet(type, NULL_OR_UNDEFINED)); } @@ -323,6 +327,17 @@ export default util.createRule({ return false; } + /** + * Allow empty arrays, like the following: + * + * ```ts + * const fruitArray: Fruit[] = []; + * ``` + */ + if (isNever(rightArrayType)) { + return false; + } + if ( !isAssigningNonEnumValueToEnumVariable( leftArrayType, diff --git a/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts index cb2893631d47..2d4c414285af 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts @@ -231,7 +231,6 @@ invalid.push({ name: 'Assigning a number array to a variable with a number enum array', code: fruitEnumDefinition + - fruit2EnumDefinition + ` declare let fruits: Fruit[]; fruits = [0, 1]; @@ -243,7 +242,6 @@ valid.push({ name: 'Assigning an empty array to a variable with a number enum array', code: fruitEnumDefinition + - fruit2EnumDefinition + ` const fruitArray: Fruit[] = []; `, From 90981a9191b2792bd30be7b718f7b295bae04e15 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Sun, 1 May 2022 22:21:05 -0400 Subject: [PATCH 30/88] fix: adding logic for arrays with no enums --- packages/eslint-plugin/src/rules/semi.ts | 1 - packages/eslint-plugin/src/rules/strict-enums.ts | 7 ++++++- .../tests/rules/strict-enums-functions.test.ts | 9 +++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/src/rules/semi.ts b/packages/eslint-plugin/src/rules/semi.ts index 3f00395dcde6..1d77e7283f92 100644 --- a/packages/eslint-plugin/src/rules/semi.ts +++ b/packages/eslint-plugin/src/rules/semi.ts @@ -56,7 +56,6 @@ export default util.createRule({ const checkForSemicolon = rules.ExpressionStatement as TSESLint.RuleFunction; - // eslint-disable-next-line @typescript-eslint/strict-enums const nodesToCheck = SEMI_AST_NODE_TYPES.reduce( (accumulator, node) => { accumulator[node as string] = checkForSemicolon; diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 946cbca8cac4..7d50b967f705 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -435,6 +435,7 @@ export default util.createRule({ return false; } + let atLeastOneParamIsEnum = false; for (const parameterSubType of parameterSubTypes) { if (!isArray(parameterSubType)) { continue; @@ -446,6 +447,10 @@ export default util.createRule({ return false; } + if (hasEnumTypes(parameterArrayType)) { + atLeastOneParamIsEnum = true; + } + if ( !isMismatchedEnumFunctionArgument( argumentArrayType, @@ -456,7 +461,7 @@ export default util.createRule({ } } - return true; + return atLeastOneParamIsEnum; } /** diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts index 69f9d5162a97..660fb6f92b24 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts @@ -1007,6 +1007,15 @@ JSON.stringify( `, }); +valid.push({ + name: 'Using flatten', + code: ` +function flatten(arr: T[][]): T[] { + return arr.reduce((acc, a) => acc.concat(a), []); +} + `, +}); + strictEnumsRuleTester.run('strict-enums-functions', rule, { valid, invalid, From 32dec6321e2b3239c8f54579fcc8d70baf4fff56 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Sun, 1 May 2022 22:53:49 -0400 Subject: [PATCH 31/88] fix: adding more tests --- .../rules/strict-enums-comparison.test.ts | 47 ++++++++++++++++++- .../ast/serializer/serializerScope.ts | 1 + 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts index 8d7dfd391268..825a1dcabdd6 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts @@ -28,6 +28,28 @@ if (1 === 2) { `, }); +valid.push({ + name: 'Comparing a number enum literal to any', + code: + fruitEnumDefinition + + ` +declare thing: any; +if (Fruit.Apple === thing) { +} + `, +}); + +valid.push({ + name: 'Comparing a number enum literal to unknown', + code: + fruitEnumDefinition + + ` +declare thing: unknown; +if (Fruit.Apple === thing) { +} + `, +}); + valid.push({ name: 'Comparing a number enum literal to literal undefined', code: @@ -246,9 +268,8 @@ if (vegetable === Vegetable2.Lettuce2) { errors: [{ messageId: 'mismatchedComparison' }], }); -// TODO valid.push({ - name: 'ZZ Comparing a generic enum extension value with a number enum literal', + name: 'Comparing a generic enum extension value with a number enum literal', code: fruitEnumDefinition + ` @@ -260,6 +281,28 @@ class FruitClass { `, }); +valid.push({ + name: 'Comparing a number union to a number union', + code: + fruitEnumDefinition + + ` +declare const left: number | Fruit; +declare const right: number | Fruit; +if (left === right) {} + `, +}); + +valid.push({ + name: 'Comparing a string union to a string union', + code: + fruitEnumDefinition + + ` +declare const left: string | Fruit; +declare const right: string | Fruit; +if (left === right) {} + `, +}); + // -------------- // OPERATOR TESTS // -------------- diff --git a/packages/website/src/components/ast/serializer/serializerScope.ts b/packages/website/src/components/ast/serializer/serializerScope.ts index 176f49f92c5c..9a2bdac3e5f4 100644 --- a/packages/website/src/components/ast/serializer/serializerScope.ts +++ b/packages/website/src/components/ast/serializer/serializerScope.ts @@ -194,6 +194,7 @@ export function createScopeSerializer(): Serializer { start: { ...data.loc.start }, end: { ...data.loc.end }, }, + // eslint-disable-next-line @typescript-eslint/strict-enums value: data.type === 'Identifier' ? `<"${data.name}">` : '', }; } From d0dbcbb3fd24dcb96d3ff19259b23b1a8abd2678 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Sun, 1 May 2022 23:06:22 -0400 Subject: [PATCH 32/88] fix: fixing test --- .../eslint-plugin/src/rules/strict-enums.ts | 41 ++++++++++++++----- .../rules/strict-enums-comparison.test.ts | 21 +++------- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 7d50b967f705..016c60540bb7 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -4,7 +4,8 @@ import * as ts from 'typescript'; import { TSESTree } from '@typescript-eslint/utils'; const TYPE_NAME_TRUNCATION_THRESHOLD = 40; -const NULL_OR_UNDEFINED = ts.TypeFlags.Null | ts.TypeFlags.Undefined; +const NULL_OR_UNDEFINED_OR_ANY = + ts.TypeFlags.Null | ts.TypeFlags.Undefined | ts.TypeFlags.Any; const ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT = ts.TypeFlags.Any | @@ -213,8 +214,10 @@ export default util.createRule({ return util.isTypeFlagSet(type, ts.TypeFlags.Never); } - function isNullOrUndefined(...types: ts.Type[]): boolean { - return types.some(type => util.isTypeFlagSet(type, NULL_OR_UNDEFINED)); + function isNullOrUndefinedOrAny(...types: ts.Type[]): boolean { + return types.some(type => + util.isTypeFlagSet(type, NULL_OR_UNDEFINED_OR_ANY), + ); } function setHasAnyElementFromSet(set1: Set, set2: Set): boolean { @@ -358,11 +361,11 @@ export default util.createRule({ } /** - * As a special case, allow assignment of null and undefined in all - * circumstances, since the TypeScript compiler should properly type-check - * this. + * As a special case, allow assignment of null and undefined and any in + * all circumstances, since the TypeScript compiler should properly + * type-check this. */ - if (isNullOrUndefined(rightType)) { + if (isNullOrUndefinedOrAny(rightType)) { return false; } @@ -397,15 +400,33 @@ export default util.createRule({ } /** - * As a special exception, allow comparisons to literal null or literal - * undefined. + * As a special exception, allow comparisons to null or undefined or any. * * The TypeScript compiler should handle these cases properly, so the * lint rule is unneeded. */ - if (isNullOrUndefined(leftType, rightType)) { + if (isNullOrUndefinedOrAny(leftType, rightType)) { + return false; + } + + /** + * Allow comparing numbers to numbers and strings to strings, like the + * following: + * + * ```ts + * declare const left: number | Fruit; + * declare const right: number | Fruit; + * if (left === right) {} + * ``` + */ + /* + if (hasNumberType(leftType) && hasNumberType(rightType)) { + return false; + } + if (hasStringType(leftType) && hasStringType(rightType)) { return false; } + */ /** * Disallow mismatched comparisons, like the following: diff --git a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts index 825a1dcabdd6..96adc0c605e3 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts @@ -39,17 +39,6 @@ if (Fruit.Apple === thing) { `, }); -valid.push({ - name: 'Comparing a number enum literal to unknown', - code: - fruitEnumDefinition + - ` -declare thing: unknown; -if (Fruit.Apple === thing) { -} - `, -}); - valid.push({ name: 'Comparing a number enum literal to literal undefined', code: @@ -285,9 +274,10 @@ valid.push({ name: 'Comparing a number union to a number union', code: fruitEnumDefinition + + fruit2EnumDefinition + ` declare const left: number | Fruit; -declare const right: number | Fruit; +declare const right: number | Fruit2; if (left === right) {} `, }); @@ -295,10 +285,11 @@ if (left === right) {} valid.push({ name: 'Comparing a string union to a string union', code: - fruitEnumDefinition + + vegetableEnumDefinition + + vegetable2EnumDefinition + ` -declare const left: string | Fruit; -declare const right: string | Fruit; +declare const left: string | Vegetable; +declare const right: string | Vegetable2; if (left === right) {} `, }); From c63c518c1fd9b8c390b02ff65ba343d8f2ed73cf Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Sun, 1 May 2022 23:23:10 -0400 Subject: [PATCH 33/88] fix: fixing linter --- packages/scope-manager/src/ScopeManager.ts | 6 +++++- packages/scope-manager/src/referencer/ClassVisitor.ts | 1 + packages/scope-manager/src/referencer/Reference.ts | 4 ++-- packages/scope-manager/src/referencer/VisitorBase.ts | 3 ++- packages/scope-manager/src/scope/ScopeBase.ts | 2 +- .../scope-manager/tests/util/serializers/TSESTreeNode.ts | 1 + packages/type-utils/src/isTypeReadonly.ts | 1 + packages/type-utils/src/typeFlagUtils.ts | 8 ++++---- packages/typescript-estree/src/convert-comments.ts | 2 +- packages/typescript-estree/src/simple-traverse.ts | 1 + packages/utils/src/ast-utils/helpers.ts | 1 + 11 files changed, 20 insertions(+), 10 deletions(-) diff --git a/packages/scope-manager/src/ScopeManager.ts b/packages/scope-manager/src/ScopeManager.ts index 5a53fe6fbf8c..21794764d78b 100644 --- a/packages/scope-manager/src/ScopeManager.ts +++ b/packages/scope-manager/src/ScopeManager.ts @@ -1,3 +1,4 @@ +import { ScopeType } from './scope'; import { TSESTree } from '@typescript-eslint/types'; import { assert } from './assert'; import { @@ -106,7 +107,10 @@ class ScopeManager { */ public acquire(node: TSESTree.Node, inner = false): Scope | null { function predicate(testScope: Scope): boolean { - if (testScope.type === 'function' && testScope.functionExpressionScope) { + if ( + testScope.type === ScopeType.function && + testScope.functionExpressionScope + ) { return false; } return true; diff --git a/packages/scope-manager/src/referencer/ClassVisitor.ts b/packages/scope-manager/src/referencer/ClassVisitor.ts index 6f5050442138..f1bb8c8dbd1b 100644 --- a/packages/scope-manager/src/referencer/ClassVisitor.ts +++ b/packages/scope-manager/src/referencer/ClassVisitor.ts @@ -35,6 +35,7 @@ class ClassVisitor extends Visitor { visit(node: TSESTree.Node | null | undefined): void { // make sure we only handle the nodes we are designed to handle + // eslint-disable-next-line @typescript-eslint/strict-enums if (node && node.type in this) { super.visit(node); } else { diff --git a/packages/scope-manager/src/referencer/Reference.ts b/packages/scope-manager/src/referencer/Reference.ts index 9cf624f82a18..8d66fe0b7fc8 100644 --- a/packages/scope-manager/src/referencer/Reference.ts +++ b/packages/scope-manager/src/referencer/Reference.ts @@ -65,7 +65,7 @@ class Reference { /** * In some cases, a reference may be a type, value or both a type and value reference. */ - readonly #referenceType: ReferenceTypeFlag; + readonly #referenceType: number | ReferenceTypeFlag; /** * True if this reference can reference types @@ -88,7 +88,7 @@ class Reference { writeExpr?: TSESTree.Node | null, maybeImplicitGlobal?: ReferenceImplicitGlobal | null, init?: boolean, - referenceType = ReferenceTypeFlag.Value, + referenceType: number | ReferenceTypeFlag = ReferenceTypeFlag.Value, ) { this.identifier = identifier; this.from = scope; diff --git a/packages/scope-manager/src/referencer/VisitorBase.ts b/packages/scope-manager/src/referencer/VisitorBase.ts index 8e06863a229d..dd1909cc9ffb 100644 --- a/packages/scope-manager/src/referencer/VisitorBase.ts +++ b/packages/scope-manager/src/referencer/VisitorBase.ts @@ -35,7 +35,7 @@ abstract class VisitorBase { node: T | null | undefined, excludeArr: (keyof T)[] = [], ): void { - if (node == null || node.type == null) { + if (node == null || node.type === null) { return; } @@ -67,6 +67,7 @@ abstract class VisitorBase { * Dispatching node. */ visit(node: TSESTree.Node | null | undefined): void { + // eslint-disable-next-line @typescript-eslint/strict-enums if (node == null || node.type == null) { return; } diff --git a/packages/scope-manager/src/scope/ScopeBase.ts b/packages/scope-manager/src/scope/ScopeBase.ts index 18196d9cce99..794c3e3dae7f 100644 --- a/packages/scope-manager/src/scope/ScopeBase.ts +++ b/packages/scope-manager/src/scope/ScopeBase.ts @@ -362,7 +362,7 @@ abstract class ScopeBase< if (this.shouldStaticallyClose()) { closeRef = this.#staticCloseRef; - } else if (this.type !== 'global') { + } else if (this.type !== ScopeType.global) { closeRef = this.#dynamicCloseRef; } else { closeRef = this.#globalCloseRef; diff --git a/packages/scope-manager/tests/util/serializers/TSESTreeNode.ts b/packages/scope-manager/tests/util/serializers/TSESTreeNode.ts index 806ad70a8b2d..98accb918eee 100644 --- a/packages/scope-manager/tests/util/serializers/TSESTreeNode.ts +++ b/packages/scope-manager/tests/util/serializers/TSESTreeNode.ts @@ -25,6 +25,7 @@ const serializer: NewPlugin = { // make sure it's not one of the classes from the package Object.getPrototypeOf(val) === Object.prototype && 'type' in val && + // eslint-disable-next-line @typescript-eslint/strict-enums (val as TSESTree.Node).type in AST_NODE_TYPES ); }, diff --git a/packages/type-utils/src/isTypeReadonly.ts b/packages/type-utils/src/isTypeReadonly.ts index c5bc12e6d278..2efce88ef3c2 100644 --- a/packages/type-utils/src/isTypeReadonly.ts +++ b/packages/type-utils/src/isTypeReadonly.ts @@ -74,6 +74,7 @@ function isTypeReadonlyArrayOrTuple( ESLintUtils.NullThrowsReasons.MissingToken('symbol', 'array type'), ); const escapedName = symbol.getEscapedName(); + // eslint-disable-next-line @typescript-eslint/strict-enums if (escapedName === 'Array') { return Readonlyness.Mutable; } diff --git a/packages/type-utils/src/typeFlagUtils.ts b/packages/type-utils/src/typeFlagUtils.ts index ba01dc5bb714..2a69d2625211 100644 --- a/packages/type-utils/src/typeFlagUtils.ts +++ b/packages/type-utils/src/typeFlagUtils.ts @@ -7,7 +7,7 @@ const ANY_OR_UNKNOWN = ts.TypeFlags.Any | ts.TypeFlags.Unknown; /** * Gets all of the type flags in a type, iterating through unions automatically. */ -export function getTypeFlags(type: ts.Type): number { +export function getTypeFlags(type: ts.Type): number | ts.TypeFlags { let flags = 0; for (const t of unionTypeParts(type)) { flags |= t.flags; @@ -42,7 +42,7 @@ function isFlagSet(flags: number, flag: number): boolean { */ export function isSymbolFlagSet( symbol: ts.Symbol, - flagsToCheck: number, + flagsToCheck: number | ts.SymbolFlags, ): boolean { return isFlagSet(symbol.flags, flagsToCheck); } @@ -58,7 +58,7 @@ export function isSymbolFlagSet( */ export function isTypeFlagSet( type: ts.Type, - flagsToCheck: number, + flagsToCheck: number | ts.TypeFlags, isReceiver?: boolean, ): boolean { const flags = getTypeFlags(type); @@ -77,7 +77,7 @@ export function isTypeFlagSet( */ export function isTypeFlagSetSimple( type: ts.Type, - flagsToCheck: number, + flagsToCheck: number | ts.TypeFlags, ): boolean { return isFlagSet(type.flags, flagsToCheck); } diff --git a/packages/typescript-estree/src/convert-comments.ts b/packages/typescript-estree/src/convert-comments.ts index effc4ead9077..062bfdb82d0b 100644 --- a/packages/typescript-estree/src/convert-comments.ts +++ b/packages/typescript-estree/src/convert-comments.ts @@ -20,7 +20,7 @@ export function convertComments( ast, (_, comment) => { const type = - comment.kind == ts.SyntaxKind.SingleLineCommentTrivia + comment.kind === ts.SyntaxKind.SingleLineCommentTrivia ? AST_TOKEN_TYPES.Line : AST_TOKEN_TYPES.Block; const range: TSESTree.Range = [comment.pos, comment.end]; diff --git a/packages/typescript-estree/src/simple-traverse.ts b/packages/typescript-estree/src/simple-traverse.ts index f513e54b14f1..620816ae11a2 100644 --- a/packages/typescript-estree/src/simple-traverse.ts +++ b/packages/typescript-estree/src/simple-traverse.ts @@ -47,6 +47,7 @@ class SimpleTraverser { if ('enter' in this.selectors) { this.selectors.enter(node, parent); + // eslint-disable-next-line @typescript-eslint/strict-enums } else if (node.type in this.selectors) { this.selectors[node.type](node, parent); } diff --git a/packages/utils/src/ast-utils/helpers.ts b/packages/utils/src/ast-utils/helpers.ts index baf4daf68101..aa0eac700015 100644 --- a/packages/utils/src/ast-utils/helpers.ts +++ b/packages/utils/src/ast-utils/helpers.ts @@ -54,6 +54,7 @@ export const isTokenOfTypeWithConditions = < token: TSESTree.Token | null | undefined, ): token is TSESTree.Token & { type: TokenType } & Conditions => token?.type === tokenType && + // eslint-disable-next-line @typescript-eslint/strict-enums entries.every(([key, value]) => token[key] === value); }; From 6e4f70584655144aa896214d450bc4aad6e27158 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 3 May 2022 16:46:59 -0400 Subject: [PATCH 34/88] fix: reverting comment fixes --- packages/eslint-plugin/src/rules/member-ordering.ts | 6 +++--- packages/eslint-plugin/src/rules/no-invalid-void-type.ts | 2 +- packages/eslint-plugin/src/rules/strict-enums.ts | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/eslint-plugin/src/rules/member-ordering.ts b/packages/eslint-plugin/src/rules/member-ordering.ts index cfabf2fb5be0..4ddb49545933 100644 --- a/packages/eslint-plugin/src/rules/member-ordering.ts +++ b/packages/eslint-plugin/src/rules/member-ordering.ts @@ -367,7 +367,7 @@ function getMemberName( * @param memberGroups the valid names to be validated. * @param orderConfig the current order to be validated. * - * @returns Index of the matching member type in the order configuration. + * @return Index of the matching member type in the order configuration. */ function getRankOrder( memberGroups: BaseMemberType[], @@ -564,7 +564,7 @@ export default util.createRule({ * @param groupOrder Group order to be validated. * @param supportsModifiers A flag indicating whether the type supports modifiers (scope or accessibility) or not. * - * @returns Array of member groups or null if one of the groups is not correctly sorted. + * @return Array of member groups or null if one of the groups is not correctly sorted. */ function checkGroupSort( members: Member[], @@ -616,7 +616,7 @@ export default util.createRule({ * @param members Members to be validated. * @param caseSensitive indicates if the alpha ordering is case sensitive or not. * - * @returns True if all members are correctly sorted. + * @return True if all members are correctly sorted. */ function checkAlphaSort( members: Member[], 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 eebd82f49396..cd28cfa16da7 100644 --- a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts +++ b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts @@ -128,7 +128,7 @@ export default util.createRule<[Options], MessageIds>({ /** * @brief checks that a union containing void is valid - * @returns true if every member of the union is specified as a valid type in + * @return true if every member of the union is specified as a valid type in * validUnionMembers, or is a valid generic type parametrized by void */ function isValidUnionType(node: TSESTree.TSUnionType): boolean { diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 016c60540bb7..ef633bd3ce01 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -320,6 +320,7 @@ export default util.createRule({ } const rightSubTypes = tsutils.unionTypeParts(rightType); + for (const rightSubType of rightSubTypes) { if (!isArray(rightSubType)) { continue; From a0a2ee6c059af7c0eab90dbe200d4d20b6207acd Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 3 May 2022 16:48:56 -0400 Subject: [PATCH 35/88] fix: removing refactor --- .../rules/no-unnecessary-boolean-literal-compare.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts b/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts index 2d7742226901..1b2a91e06abe 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts @@ -2,10 +2,6 @@ import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils'; import * as ts from 'typescript'; import * as util from '../util'; -const NULL_OR_UNDEFINED = ts.TypeFlags.Undefined | ts.TypeFlags.Null; -const BOOLEAN_OR_BOOLEAN_LITERAL = - ts.TypeFlags.Boolean | ts.TypeFlags.BooleanLiteral; - type MessageIds = | 'direct' | 'negated' @@ -112,7 +108,7 @@ export default util.createRule({ function isBooleanType(expressionType: ts.Type): boolean { return util.isTypeFlagSetSimple( expressionType, - BOOLEAN_OR_BOOLEAN_LITERAL, + ts.TypeFlags.Boolean | ts.TypeFlags.BooleanLiteral, ); } @@ -130,7 +126,11 @@ export default util.createRule({ const { types } = expressionType; const nonNullishTypes = types.filter( - type => !util.isTypeFlagSetSimple(type, NULL_OR_UNDEFINED), + type => + !util.isTypeFlagSetSimple( + type, + ts.TypeFlags.Undefined | ts.TypeFlags.Null, + ), ); const hasNonNullishType = nonNullishTypes.length > 0; From dbae5db96ba6f64bc1cf1ce820c532cca46d7c0a Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 3 May 2022 17:11:01 -0400 Subject: [PATCH 36/88] fix: removing fixes to dot-notation --- packages/eslint-plugin/src/rules/dot-notation.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/src/rules/dot-notation.ts b/packages/eslint-plugin/src/rules/dot-notation.ts index 5288f9a5b6dc..29db2f3fe1e2 100644 --- a/packages/eslint-plugin/src/rules/dot-notation.ts +++ b/packages/eslint-plugin/src/rules/dot-notation.ts @@ -99,9 +99,9 @@ export default createRule({ propertySymbol?.getDeclarations()?.[0]?.modifiers?.[0].kind; if ( (allowPrivateClassPropertyAccess && - modifierKind === ts.SyntaxKind.PrivateKeyword) || + modifierKind == ts.SyntaxKind.PrivateKeyword) || (allowProtectedClassPropertyAccess && - modifierKind === ts.SyntaxKind.ProtectedKeyword) + modifierKind == ts.SyntaxKind.ProtectedKeyword) ) { return; } From 16965d9811d7febd01f51969f36497b81d965014 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 3 May 2022 17:15:34 -0400 Subject: [PATCH 37/88] fix: removing semi refactor --- packages/eslint-plugin/src/rules/semi.ts | 45 +++++++++++------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/packages/eslint-plugin/src/rules/semi.ts b/packages/eslint-plugin/src/rules/semi.ts index 1d77e7283f92..8df56137311f 100644 --- a/packages/eslint-plugin/src/rules/semi.ts +++ b/packages/eslint-plugin/src/rules/semi.ts @@ -2,24 +2,6 @@ import { TSESTree, TSESLint, AST_NODE_TYPES } from '@typescript-eslint/utils'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; import * as util from '../util'; -/** - * The following nodes are handled by the `member-delimiter-style` rule: - * - AST_NODE_TYPES.TSCallSignatureDeclaration - * - AST_NODE_TYPES.TSConstructSignatureDeclaration - * - AST_NODE_TYPES.TSIndexSignature - * - AST_NODE_TYPES.TSMethodSignature - * - AST_NODE_TYPES.TSPropertySignature - */ -const SEMI_AST_NODE_TYPES = [ - AST_NODE_TYPES.PropertyDefinition, - AST_NODE_TYPES.TSAbstractPropertyDefinition, - AST_NODE_TYPES.TSDeclareFunction, - AST_NODE_TYPES.TSExportAssignment, - AST_NODE_TYPES.TSImportEqualsDeclaration, - AST_NODE_TYPES.TSTypeAliasDeclaration, - AST_NODE_TYPES.TSEmptyBodyFunctionExpression, -]; - const baseRule = getESLintCoreRule('semi'); export type Options = util.InferOptionsTypeFromRule; @@ -56,13 +38,26 @@ export default util.createRule({ const checkForSemicolon = rules.ExpressionStatement as TSESLint.RuleFunction; - const nodesToCheck = SEMI_AST_NODE_TYPES.reduce( - (accumulator, node) => { - accumulator[node as string] = checkForSemicolon; - return accumulator; - }, - {}, - ); + /* + The following nodes are handled by the member-delimiter-style rule + AST_NODE_TYPES.TSCallSignatureDeclaration, + AST_NODE_TYPES.TSConstructSignatureDeclaration, + AST_NODE_TYPES.TSIndexSignature, + AST_NODE_TYPES.TSMethodSignature, + AST_NODE_TYPES.TSPropertySignature, + */ + const nodesToCheck = [ + AST_NODE_TYPES.PropertyDefinition, + AST_NODE_TYPES.TSAbstractPropertyDefinition, + AST_NODE_TYPES.TSDeclareFunction, + AST_NODE_TYPES.TSExportAssignment, + AST_NODE_TYPES.TSImportEqualsDeclaration, + AST_NODE_TYPES.TSTypeAliasDeclaration, + AST_NODE_TYPES.TSEmptyBodyFunctionExpression, + ].reduce((acc, node) => { + acc[node as string] = checkForSemicolon; + return acc; + }, {}); return { ...rules, From 8b8f8f84c0b440d76a09552635308c5a7211aae8 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 3 May 2022 17:21:02 -0400 Subject: [PATCH 38/88] fix: removing jest logic --- packages/eslint-plugin/src/rules/strict-enums.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index ef633bd3ce01..3bfe11c60178 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -172,10 +172,7 @@ export default util.createRule({ function getTypeName(type: ts.Type): string { const typeName = util.getTypeName(typeChecker, type); - if ( - typeName.length <= TYPE_NAME_TRUNCATION_THRESHOLD || - insideJestTest() // Never truncate in tests - ) { + if (typeName.length <= TYPE_NAME_TRUNCATION_THRESHOLD) { return typeName; } @@ -191,10 +188,6 @@ export default util.createRule({ return enumTypes.size > 0; } - function insideJestTest(): boolean { - return process.env.JEST_WORKER_ID !== undefined; - } - function isArray( type: ts.Type, ): type is ts.TypeReference | ts.TupleTypeReference { From 5f437ccf16a93a94dcd1bce26602da5b5f118054 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 3 May 2022 17:48:13 -0400 Subject: [PATCH 39/88] fix: removing comparison operators check --- .../eslint-plugin/docs/rules/strict-enums.md | 41 ++++------ .../eslint-plugin/src/rules/strict-enums.ts | 78 +++---------------- .../rules/strict-enums-comparison.test.ts | 50 +----------- 3 files changed, 29 insertions(+), 140 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/strict-enums.md b/packages/eslint-plugin/docs/rules/strict-enums.md index c328783203d4..d949265e58cf 100644 --- a/packages/eslint-plugin/docs/rules/strict-enums.md +++ b/packages/eslint-plugin/docs/rules/strict-enums.md @@ -24,13 +24,10 @@ See the examples below for the types of patterns that are prevented. The goal of this rule is to make enums work like they do in other languages. One of the main benefits of enums is that they allow you to write code that is future-safe, because enums are supposed to be resilient to reorganization. If you arbitrarily change the values of an enum (or change the ordering of an enum with computed values), the idea is that nothing in your code-base should break. -Subsequently, this rule bans potentially-dangerous patterns that you might already be using, like using the greater than operator to select a subset of enum values. - ## Banned Patterns This rule bans: -1. Comparing enums with unsafe operators - `incorrectComparisonOperator` 1. Enum incrementing/decrementing - `incorrectIncrement` 1. Mismatched enum declarations/assignments - `mismatchedAssignment` 1. Mismatched enum comparisons - `mismatchedComparison` @@ -40,18 +37,13 @@ This rule bans: ### ❌ Incorrect -```ts -const fruit: Fruit = 0; -``` - ```ts let fruit = Fruit.Apple; -fruit = 1; +fruit++; ``` ```ts -let fruit = Fruit.Apple; -fruit++; +const fruit: Fruit = 0; ``` ```ts @@ -61,11 +53,6 @@ if (vegetable === 'lettuce') { } ``` -```ts -if (fruit > Fruit.Apple) { -} -``` - ```ts function useFruit(fruit: Fruit) {} useFruit(0); @@ -74,12 +61,12 @@ useFruit(0); ### ✅ Correct ```ts -const fruit = Fruit.Apple; +let fruit = Fruit.Apple; +fruit = Fruit.Banana; ``` ```ts -let fruit = Fruit.Apple; -fruit = Fruit.Banana; +const fruit = Fruit.Apple; ``` ```ts @@ -94,11 +81,6 @@ if (vegetable === Vegetable.Lettuce) { } ``` -```ts -if (fruit !== Fruit.Apple) { -} -``` - ```ts function useFruit(fruit: Fruit) {} useFruit(Fruit.Apple); @@ -106,8 +88,6 @@ useFruit(Fruit.Apple); ## Error Information -- `incorrectComparisonOperator` - You cannot compare enums with the "{{ operator }}" operator. You can only compare with the "===", "!==", "&", or "|" operators. - - Enums are supposed to be resilient to reorganization, so you should only explicitly compare them. For example, if you used a greater than sign to compare a number enum, and then someone reassigned/reordered the values of the enum, then it could potentially break your code. - `incorrectIncrement` - You cannot increment or decrement an enum type. - Enums are supposed to be resilient to reorganization, so you should explicitly assign a new value instead. For example, if someone someone reassigned/reordered the values of the enum, then it could potentially break your code. - `mismatchedAssignment` - The type of the assignment does not match the declared enum type of the variable. @@ -147,6 +127,17 @@ if (vegetable === Vegetable.Lettuce) { } ``` +## Comparison Operators + +Since it is a common pattern, this rule allows using greater than or less than to compare numeric enums, like this: + +```ts +if (fruit > Fruit.Banana) { +} +``` + +This pattern allows you to select a subset of enums. However, it can lead to bugs when enum values are arbitrarily changed, because the subset will also change. The TypeScript compiler cannot warn you about this, so you should use this pattern with care. + ## Options No options are provided. diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 3bfe11c60178..08e6e0926b46 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -3,26 +3,14 @@ import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import { TSESTree } from '@typescript-eslint/utils'; -const TYPE_NAME_TRUNCATION_THRESHOLD = 40; -const NULL_OR_UNDEFINED_OR_ANY = - ts.TypeFlags.Null | ts.TypeFlags.Undefined | ts.TypeFlags.Any; - const ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT = ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Number | ts.TypeFlags.String; -const ALLOWED_ENUM_BINARY_COMPARISON_OPERATORS = new Set(['&', '|']); -const ALLOWED_ENUM_NON_BINARY_COMPARISON_OPERATORS = new Set(['===', '!==']); -const ALLOWED_ENUM_COMPARISON_OPERATORS = new Set([ - ...ALLOWED_ENUM_BINARY_COMPARISON_OPERATORS.values(), - ...ALLOWED_ENUM_NON_BINARY_COMPARISON_OPERATORS.values(), -]); - export type Options = []; export type MessageIds = - | 'incorrectComparisonOperator' | 'incorrectIncrement' | 'mismatchedAssignment' | 'mismatchedComparison' @@ -38,8 +26,6 @@ export default util.createRule({ requiresTypeChecking: true, }, messages: { - incorrectComparisonOperator: - 'You cannot compare enums with the "{{ operator }}" operator. You can only compare with the "===", "!==", "&", or "|" operators.', incorrectIncrement: 'You cannot increment or decrement an enum type.', mismatchedAssignment: 'The type of the enum assignment ({{ assignmentType }}) does not match the declared enum type ({{ declaredType }}) of the variable.', @@ -171,16 +157,7 @@ export default util.createRule({ } function getTypeName(type: ts.Type): string { - const typeName = util.getTypeName(typeChecker, type); - if (typeName.length <= TYPE_NAME_TRUNCATION_THRESHOLD) { - return typeName; - } - - const truncatedTypeName = typeName.substring( - 0, - TYPE_NAME_TRUNCATION_THRESHOLD, - ); - return `${truncatedTypeName} [snip]`; + return util.getTypeName(typeChecker, type); } function hasEnumTypes(type: ts.Type): boolean { @@ -209,7 +186,10 @@ export default util.createRule({ function isNullOrUndefinedOrAny(...types: ts.Type[]): boolean { return types.some(type => - util.isTypeFlagSet(type, NULL_OR_UNDEFINED_OR_ANY), + util.isTypeFlagSet( + type, + ts.TypeFlags.Null | ts.TypeFlags.Undefined | ts.TypeFlags.Any, + ), ); } @@ -375,21 +355,12 @@ export default util.createRule({ operator: string, leftType: ts.Type, rightType: ts.Type, - leftEnumTypes: Set, - rightEnumTypes: Set, ): boolean { - /** - * Allow composing a variable based on enum literals using binary - * operators, like the following: - * - * ```ts - * const flags = Flag.Value1 | Flag.Value2; - * ``` - * - * (Even though this is an assignment, it still matches the - * `BinaryExpression` node type.) - */ - if (ALLOWED_ENUM_BINARY_COMPARISON_OPERATORS.has(operator)) { + const leftEnumTypes = getEnumTypes(leftType); + const rightEnumTypes = getEnumTypes(rightType); + + if (leftEnumTypes.size === 0 && rightEnumTypes.size === 0) { + // This is not an enum comparison return false; } @@ -589,34 +560,7 @@ export default util.createRule({ const leftType = getTypeFromNode(node.left); const rightType = getTypeFromNode(node.right); - const leftEnumTypes = getEnumTypes(leftType); - const rightEnumTypes = getEnumTypes(rightType); - - if (leftEnumTypes.size === 0 && rightEnumTypes.size === 0) { - // This is not an enum comparison - return; - } - - /** Only allow certain specific operators for enum comparisons. */ - if (!ALLOWED_ENUM_COMPARISON_OPERATORS.has(node.operator)) { - context.report({ - node, - messageId: 'incorrectComparisonOperator', - data: { - operator: node.operator, - }, - }); - } - - if ( - isMismatchedEnumComparison( - node.operator, - leftType, - rightType, - leftEnumTypes, - rightEnumTypes, - ) - ) { + if (isMismatchedEnumComparison(node.operator, leftType, rightType)) { context.report({ node, messageId: 'mismatchedComparison', diff --git a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts index 96adc0c605e3..6d8bec56491b 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts @@ -318,51 +318,7 @@ if (Vegetable.Lettuce !== Vegetable.Carrot) { `, }); -invalid.push({ - name: 'Comparing a number enum literal value to an enum literal value of the same type (with loose equality)', - code: - fruitEnumDefinition + - ` -if (Fruit.Apple == Fruit.Banana) { -} - `, - errors: [{ messageId: 'incorrectComparisonOperator' }], -}); - -invalid.push({ - name: 'Comparing a string enum literal value to an enum literal value of the same type (with loose equality)', - code: - vegetableEnumDefinition + - ` -if (Vegetable.Lettuce == Vegetable.Carrot) { -} - `, - errors: [{ messageId: 'incorrectComparisonOperator' }], -}); - -invalid.push({ - name: 'Comparing a number enum literal value to an enum literal value of the same type (with loose inequality)', - code: - fruitEnumDefinition + - ` -if (Fruit.Apple != Fruit.Banana) { -} - `, - errors: [{ messageId: 'incorrectComparisonOperator' }], -}); - -invalid.push({ - name: 'Comparing a string enum literal value to an enum literal value of the same type (with loose inequality)', - code: - vegetableEnumDefinition + - ` -if (Vegetable.Lettuce != Vegetable.Carrot) { -} - `, - errors: [{ messageId: 'incorrectComparisonOperator' }], -}); - -invalid.push({ +valid.push({ name: 'Comparing a number enum literal value to an enum literal value of the same type (with greater than)', code: fruitEnumDefinition + @@ -370,10 +326,9 @@ invalid.push({ if (Fruit.Apple > Fruit.Banana) { } `, - errors: [{ messageId: 'incorrectComparisonOperator' }], }); -invalid.push({ +valid.push({ name: 'Comparing a number enum literal value to an enum literal value of the same type (with less than)', code: fruitEnumDefinition + @@ -381,7 +336,6 @@ invalid.push({ if (Fruit.Apple < Fruit.Banana) { } `, - errors: [{ messageId: 'incorrectComparisonOperator' }], }); strictEnumsRuleTester.run('strict-enums-comparison', rule, { From b1dbeb65bc9310abbd15833a63cd8b5b1203de34 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 3 May 2022 18:26:20 -0400 Subject: [PATCH 40/88] fix: adding failing test --- .../eslint-plugin/src/rules/strict-enums.ts | 57 ++++++++++++------- .../rules/strict-enums-comparison.test.ts | 31 ++++++++++ 2 files changed, 69 insertions(+), 19 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 08e6e0926b46..34a0e2316442 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -165,6 +165,44 @@ export default util.createRule({ return enumTypes.size > 0; } + function hasNumberType(type: ts.Type): boolean { + return hasType(type, ts.TypeFlags.Number); + } + + function hasNumberLiteralType(type: ts.Type): boolean { + return hasType(type, ts.TypeFlags.NumberLiteral); + } + + function hasStringType(type: ts.Type): boolean { + return hasType(type, ts.TypeFlags.String); + } + + function hasStringLiteralType(type: ts.Type): boolean { + return hasType(type, ts.TypeFlags.StringLiteral); + } + + function hasType(type: ts.Type, typeFlag: ts.TypeFlags): boolean { + if (type.isUnion()) { + const unionSubTypes = tsutils.unionTypeParts(type); + for (const subType of unionSubTypes) { + if (hasType(subType, typeFlag)) { + return true; + } + } + } + + if (type.isIntersection()) { + const intersectionSubTypes = tsutils.intersectionTypeParts(type); + for (const subType of intersectionSubTypes) { + if (hasType(subType, typeFlag)) { + return true; + } + } + } + + return util.isTypeFlagSet(type, typeFlag); + } + function isArray( type: ts.Type, ): type is ts.TypeReference | ts.TupleTypeReference { @@ -374,25 +412,6 @@ export default util.createRule({ return false; } - /** - * Allow comparing numbers to numbers and strings to strings, like the - * following: - * - * ```ts - * declare const left: number | Fruit; - * declare const right: number | Fruit; - * if (left === right) {} - * ``` - */ - /* - if (hasNumberType(leftType) && hasNumberType(rightType)) { - return false; - } - if (hasStringType(leftType) && hasStringType(rightType)) { - return false; - } - */ - /** * Disallow mismatched comparisons, like the following: * diff --git a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts index 6d8bec56491b..57a0b45740d7 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts @@ -338,6 +338,37 @@ if (Fruit.Apple < Fruit.Banana) { `, }); +valid.push({ + name: 'Comparing a string enum literal value to an intersection with a string (simple)', + code: + vegetableEnumDefinition + + ` +type WeirdString = string & { __someBrand: void; }; +declare weirdString: WeirdString; +if (Vegetable.Lettuce === weirdString) { +} + `, +}); + +valid.push({ + name: 'ZZ Comparing a string enum literal value to an intersection with a string (complicated)', + code: + vegetableEnumDefinition + + ` +enum InternalSymbolName { + Foo = "foo", + Bar = "bar", +} +type __String = + | (string & { __escapedIdentifier: void; }) + | (void & { __escapedIdentifier: void; }) + | InternalSymbolName; +declare const weirdString: __String; +if (weirdString === 'someArbitraryValue') { +} + `, +}); + strictEnumsRuleTester.run('strict-enums-comparison', rule, { valid, invalid, From 25caa05e220bde6784401a12692a03819c0936bc Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 3 May 2022 18:33:10 -0400 Subject: [PATCH 41/88] fix: making test pass --- .../eslint-plugin/src/rules/strict-enums.ts | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 34a0e2316442..084276ce2f8f 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -165,20 +165,12 @@ export default util.createRule({ return enumTypes.size > 0; } - function hasNumberType(type: ts.Type): boolean { - return hasType(type, ts.TypeFlags.Number); + function hasNumber(type: ts.Type): boolean { + return hasType(type, ts.TypeFlags.NumberLike); } - function hasNumberLiteralType(type: ts.Type): boolean { - return hasType(type, ts.TypeFlags.NumberLiteral); - } - - function hasStringType(type: ts.Type): boolean { - return hasType(type, ts.TypeFlags.String); - } - - function hasStringLiteralType(type: ts.Type): boolean { - return hasType(type, ts.TypeFlags.StringLiteral); + function hasString(type: ts.Type): boolean { + return hasType(type, ts.TypeFlags.StringLike); } function hasType(type: ts.Type, typeFlag: ts.TypeFlags): boolean { @@ -200,7 +192,10 @@ export default util.createRule({ } } - return util.isTypeFlagSet(type, typeFlag); + return ( + util.isTypeFlagSet(type, typeFlag) && + !util.isTypeFlagSet(type, ts.TypeFlags.EnumLike) + ); } function isArray( @@ -412,6 +407,17 @@ export default util.createRule({ return false; } + /** + * Allow comparing numbers to numbers and strings to strings in + * complicated union/intersection types. + */ + if (hasNumber(leftType) && hasNumber(rightType)) { + return false; + } + if (hasString(leftType) && hasString(rightType)) { + return false; + } + /** * Disallow mismatched comparisons, like the following: * From f42de6183841c94aafc08d00f76b85cbcf1aa6c1 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 3 May 2022 18:34:40 -0400 Subject: [PATCH 42/88] fix: adding comment --- packages/eslint-plugin/src/rules/strict-enums.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 084276ce2f8f..516137c3d44e 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -173,6 +173,10 @@ export default util.createRule({ return hasType(type, ts.TypeFlags.StringLike); } + /** + * This will return false for any enum-like type, since it would + * subsequently not be a "pure" type anymore. + */ function hasType(type: ts.Type, typeFlag: ts.TypeFlags): boolean { if (type.isUnion()) { const unionSubTypes = tsutils.unionTypeParts(type); From a866dddadff0da9c6e08dcceafd00abc9c3d8c76 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 3 May 2022 18:49:23 -0400 Subject: [PATCH 43/88] fix: adding back in bitwise operator checks since apparently they are needed --- .../eslint-plugin/src/rules/strict-enums.ts | 10 ++++ .../rules/strict-enums-assignment.test.ts | 36 +++++++++++ .../rules/strict-enums-comparison.test.ts | 59 ++++--------------- .../rules/strict-enums-declaration.test.ts | 41 ------------- 4 files changed, 59 insertions(+), 87 deletions(-) delete mode 100644 packages/eslint-plugin/tests/rules/strict-enums-declaration.test.ts diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 516137c3d44e..07bc30e28c79 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -3,6 +3,9 @@ import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import { TSESTree } from '@typescript-eslint/utils'; +/** These operators are always considered to be safe. */ +const ALLOWED_ENUM_OPERATORS = new Set(['in', '|', '&', '|=', '&=']); + const ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT = ts.TypeFlags.Any | ts.TypeFlags.Unknown | @@ -393,6 +396,13 @@ export default util.createRule({ leftType: ts.Type, rightType: ts.Type, ): boolean { + /** + * Allow any comparisons with the some whitelisted operators. + */ + if (ALLOWED_ENUM_OPERATORS.has(operator)) { + return false; + } + const leftEnumTypes = getEnumTypes(leftType); const rightEnumTypes = getEnumTypes(rightType); diff --git a/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts index 2d4c414285af..18380964c27e 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts @@ -12,6 +12,33 @@ import { const valid: ValidTestCase[] = []; const invalid: InvalidTestCase[] = []; +valid.push({ + name: 'Declaring an enum with an empty initializer', + code: + fruitEnumDefinition + + ` + let fruit: Fruit; + if (true) { + fruit = Fruit.Apple; + } else { + fruit = Fruit.Banana; + } + `, +}); + +/** + * In development, this would trigger run-time errors due to the + * `typeChecker.getTypeAtLocation` method being buggy and not having a proper + * function signature. + */ +valid.push({ + name: 'Declaring an "empty" variable with array destructuring', + code: ` + const myArray = [1]; + const [firstElement] = myArray; + `, +}); + valid.push({ name: 'Assigning a number enum literal to a number enum (with type-inference)', code: @@ -247,6 +274,15 @@ const fruitArray: Fruit[] = []; `, }); +valid.push({ + name: 'Assigning a new variable with a composition of bitflags', + code: + fruitEnumDefinition + + ` +const fruitFlags = Fruit.Apple | Fruit.Banana; + `, +}); + strictEnumsRuleTester.run('strict-enums-assignment', rule, { valid, invalid, diff --git a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts index 57a0b45740d7..2619a2eff922 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts @@ -294,52 +294,8 @@ if (left === right) {} `, }); -// -------------- -// OPERATOR TESTS -// -------------- - valid.push({ - name: 'Comparing a number enum literal value to an enum literal value of the same type (with strict inequality)', - code: - fruitEnumDefinition + - ` -if (Fruit.Apple !== Fruit.Banana) { -} - `, -}); - -valid.push({ - name: 'Comparing a string enum literal value to an enum literal value of the same type (with strict inequality)', - code: - vegetableEnumDefinition + - ` -if (Vegetable.Lettuce !== Vegetable.Carrot) { -} - `, -}); - -valid.push({ - name: 'Comparing a number enum literal value to an enum literal value of the same type (with greater than)', - code: - fruitEnumDefinition + - ` -if (Fruit.Apple > Fruit.Banana) { -} - `, -}); - -valid.push({ - name: 'Comparing a number enum literal value to an enum literal value of the same type (with less than)', - code: - fruitEnumDefinition + - ` -if (Fruit.Apple < Fruit.Banana) { -} - `, -}); - -valid.push({ - name: 'Comparing a string enum literal value to an intersection with a string (simple)', + name: 'Comparing a string enum literal to an intersection with a string (simple)', code: vegetableEnumDefinition + ` @@ -351,7 +307,7 @@ if (Vegetable.Lettuce === weirdString) { }); valid.push({ - name: 'ZZ Comparing a string enum literal value to an intersection with a string (complicated)', + name: 'Comparing a string literal to an intersection with a string (complicated)', code: vegetableEnumDefinition + ` @@ -369,6 +325,17 @@ if (weirdString === 'someArbitraryValue') { `, }); +valid.push({ + name: 'Comparing using the in operator', + code: + vegetableEnumDefinition + + ` +const foo = {}; +const vegetable = Vegetable.Lettuce; +if (vegetable in foo) {} + `, +}); + strictEnumsRuleTester.run('strict-enums-comparison', rule, { valid, invalid, diff --git a/packages/eslint-plugin/tests/rules/strict-enums-declaration.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-declaration.test.ts deleted file mode 100644 index f9135bb87c5b..000000000000 --- a/packages/eslint-plugin/tests/rules/strict-enums-declaration.test.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { - InvalidTestCase, - ValidTestCase, -} from '@typescript-eslint/utils/src/ts-eslint'; -import rule, { MessageIds } from '../../src/rules/strict-enums'; -import { fruitEnumDefinition, strictEnumsRuleTester } from './strict-enums'; - -const valid: ValidTestCase[] = []; -const invalid: InvalidTestCase[] = []; - -valid.push({ - name: 'Declaring an enum with an empty initializer', - code: - fruitEnumDefinition + - ` - let fruit: Fruit; - if (true) { - fruit = Fruit.Apple; - } else { - fruit = Fruit.Banana; - } - `, -}); - -/** - * In development, this would trigger run-time errors due to the - * `typeChecker.getTypeAtLocation` method being buggy and not having a proper - * function signature. - */ -valid.push({ - name: 'Declaring an "empty" variable with array destructuring', - code: ` - const myArray = [1]; - const [firstElement] = myArray; - `, -}); - -strictEnumsRuleTester.run('strict-enums-declaration', rule, { - valid, - invalid, -}); From 61cf107d1a5a61bdd49185f0a976976175b54bee Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 3 May 2022 18:51:32 -0400 Subject: [PATCH 44/88] fix: remove bad comment --- packages/scope-manager/src/referencer/VisitorBase.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/scope-manager/src/referencer/VisitorBase.ts b/packages/scope-manager/src/referencer/VisitorBase.ts index dd1909cc9ffb..83d0ffb570e9 100644 --- a/packages/scope-manager/src/referencer/VisitorBase.ts +++ b/packages/scope-manager/src/referencer/VisitorBase.ts @@ -67,7 +67,6 @@ abstract class VisitorBase { * Dispatching node. */ visit(node: TSESTree.Node | null | undefined): void { - // eslint-disable-next-line @typescript-eslint/strict-enums if (node == null || node.type == null) { return; } From 304d79674e6302b01cf045eafda74a4496d636aa Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 3 May 2022 19:03:43 -0400 Subject: [PATCH 45/88] fix: removing unnecessary comments --- .../src/rules/consistent-type-exports.ts | 1 - packages/eslint-plugin/src/rules/no-implied-eval.ts | 1 - .../eslint-plugin/src/rules/prefer-optional-chain.ts | 1 - packages/eslint-plugin/src/rules/return-await.ts | 1 - .../scope-manager/src/referencer/ClassVisitor.ts | 1 - .../tests/util/serializers/TSESTreeNode.ts | 1 - packages/type-utils/src/isTypeReadonly.ts | 1 - packages/typescript-estree/src/node-utils.ts | 12 ------------ packages/typescript-estree/src/simple-traverse.ts | 1 - packages/utils/src/ast-utils/helpers.ts | 1 - 10 files changed, 21 deletions(-) diff --git a/packages/eslint-plugin/src/rules/consistent-type-exports.ts b/packages/eslint-plugin/src/rules/consistent-type-exports.ts index bc8902454e98..36fa561bcb3b 100644 --- a/packages/eslint-plugin/src/rules/consistent-type-exports.ts +++ b/packages/eslint-plugin/src/rules/consistent-type-exports.ts @@ -214,7 +214,6 @@ function isSpecifierTypeBased( const symbol = checker.getSymbolAtLocation(node); const aliasedSymbol = checker.getAliasedSymbol(symbol!); - // eslint-disable-next-line @typescript-eslint/strict-enums if (!aliasedSymbol || aliasedSymbol.escapedName === 'unknown') { return undefined; } diff --git a/packages/eslint-plugin/src/rules/no-implied-eval.ts b/packages/eslint-plugin/src/rules/no-implied-eval.ts index f3c9616eb67b..b4c623deb800 100644 --- a/packages/eslint-plugin/src/rules/no-implied-eval.ts +++ b/packages/eslint-plugin/src/rules/no-implied-eval.ts @@ -76,7 +76,6 @@ export default util.createRule({ return true; } - // eslint-disable-next-line @typescript-eslint/strict-enums if (symbol && symbol.escapedName === FUNCTION_CONSTRUCTOR) { const declarations = symbol.getDeclarations() ?? []; for (const declaration of declarations) { diff --git a/packages/eslint-plugin/src/rules/prefer-optional-chain.ts b/packages/eslint-plugin/src/rules/prefer-optional-chain.ts index d5f812ce71a3..b3815e09ef97 100644 --- a/packages/eslint-plugin/src/rules/prefer-optional-chain.ts +++ b/packages/eslint-plugin/src/rules/prefer-optional-chain.ts @@ -82,7 +82,6 @@ export default util.createRule({ operator, ); - // eslint-disable-next-line @typescript-eslint/strict-enums return leftPrecedence < util.OperatorPrecedence.LeftHandSide; } context.report({ diff --git a/packages/eslint-plugin/src/rules/return-await.ts b/packages/eslint-plugin/src/rules/return-await.ts index 703912bb89ae..edeb60dd0af1 100644 --- a/packages/eslint-plugin/src/rules/return-await.ts +++ b/packages/eslint-plugin/src/rules/return-await.ts @@ -173,7 +173,6 @@ export default util.createRule({ ts.SyntaxKind.Unknown, ); - // eslint-disable-next-line @typescript-eslint/strict-enums return nodePrecedence > awaitPrecedence; } diff --git a/packages/scope-manager/src/referencer/ClassVisitor.ts b/packages/scope-manager/src/referencer/ClassVisitor.ts index f1bb8c8dbd1b..6f5050442138 100644 --- a/packages/scope-manager/src/referencer/ClassVisitor.ts +++ b/packages/scope-manager/src/referencer/ClassVisitor.ts @@ -35,7 +35,6 @@ class ClassVisitor extends Visitor { visit(node: TSESTree.Node | null | undefined): void { // make sure we only handle the nodes we are designed to handle - // eslint-disable-next-line @typescript-eslint/strict-enums if (node && node.type in this) { super.visit(node); } else { diff --git a/packages/scope-manager/tests/util/serializers/TSESTreeNode.ts b/packages/scope-manager/tests/util/serializers/TSESTreeNode.ts index 98accb918eee..806ad70a8b2d 100644 --- a/packages/scope-manager/tests/util/serializers/TSESTreeNode.ts +++ b/packages/scope-manager/tests/util/serializers/TSESTreeNode.ts @@ -25,7 +25,6 @@ const serializer: NewPlugin = { // make sure it's not one of the classes from the package Object.getPrototypeOf(val) === Object.prototype && 'type' in val && - // eslint-disable-next-line @typescript-eslint/strict-enums (val as TSESTree.Node).type in AST_NODE_TYPES ); }, diff --git a/packages/type-utils/src/isTypeReadonly.ts b/packages/type-utils/src/isTypeReadonly.ts index 2efce88ef3c2..c5bc12e6d278 100644 --- a/packages/type-utils/src/isTypeReadonly.ts +++ b/packages/type-utils/src/isTypeReadonly.ts @@ -74,7 +74,6 @@ function isTypeReadonlyArrayOrTuple( ESLintUtils.NullThrowsReasons.MissingToken('symbol', 'array type'), ); const escapedName = symbol.getEscapedName(); - // eslint-disable-next-line @typescript-eslint/strict-enums if (escapedName === 'Array') { return Readonlyness.Mutable; } diff --git a/packages/typescript-estree/src/node-utils.ts b/packages/typescript-estree/src/node-utils.ts index 4055f3dfcb22..d8182aa5655e 100644 --- a/packages/typescript-estree/src/node-utils.ts +++ b/packages/typescript-estree/src/node-utils.ts @@ -32,9 +32,7 @@ export function isAssignmentOperator( operator: ts.Token, ): boolean { return ( - // eslint-disable-next-line @typescript-eslint/strict-enums operator.kind >= SyntaxKind.FirstAssignment && - // eslint-disable-next-line @typescript-eslint/strict-enums operator.kind <= SyntaxKind.LastAssignment ); } @@ -236,7 +234,6 @@ export function getRange(node: ts.Node, ast: ts.SourceFile): [number, number] { */ export function isToken(node: ts.Node): node is ts.Token { return ( - // eslint-disable-next-line @typescript-eslint/strict-enums node.kind >= SyntaxKind.FirstToken && node.kind <= SyntaxKind.LastToken ); } @@ -248,7 +245,6 @@ export function isToken(node: ts.Node): node is ts.Token { */ export function isJSXToken(node: ts.Node): boolean { return ( - // eslint-disable-next-line @typescript-eslint/strict-enums node.kind >= SyntaxKind.JsxElement && node.kind <= SyntaxKind.JsxAttribute ); } @@ -443,9 +439,7 @@ export function getTokenType( if (token.originalKeywordKind === SyntaxKind.NullKeyword) { return AST_TOKEN_TYPES.Null; } else if ( - // eslint-disable-next-line @typescript-eslint/strict-enums token.originalKeywordKind >= SyntaxKind.FirstFutureReservedWord && - // eslint-disable-next-line @typescript-eslint/strict-enums token.originalKeywordKind <= SyntaxKind.LastKeyword ) { return AST_TOKEN_TYPES.Identifier; @@ -454,9 +448,7 @@ export function getTokenType( } if ( - // eslint-disable-next-line @typescript-eslint/strict-enums token.kind >= SyntaxKind.FirstKeyword && - // eslint-disable-next-line @typescript-eslint/strict-enums token.kind <= SyntaxKind.LastFutureReservedWord ) { if ( @@ -470,18 +462,14 @@ export function getTokenType( } if ( - // eslint-disable-next-line @typescript-eslint/strict-enums token.kind >= SyntaxKind.FirstPunctuation && - // eslint-disable-next-line @typescript-eslint/strict-enums token.kind <= SyntaxKind.LastPunctuation ) { return AST_TOKEN_TYPES.Punctuator; } if ( - // eslint-disable-next-line @typescript-eslint/strict-enums token.kind >= SyntaxKind.NoSubstitutionTemplateLiteral && - // eslint-disable-next-line @typescript-eslint/strict-enums token.kind <= SyntaxKind.TemplateTail ) { return AST_TOKEN_TYPES.Template; diff --git a/packages/typescript-estree/src/simple-traverse.ts b/packages/typescript-estree/src/simple-traverse.ts index 620816ae11a2..f513e54b14f1 100644 --- a/packages/typescript-estree/src/simple-traverse.ts +++ b/packages/typescript-estree/src/simple-traverse.ts @@ -47,7 +47,6 @@ class SimpleTraverser { if ('enter' in this.selectors) { this.selectors.enter(node, parent); - // eslint-disable-next-line @typescript-eslint/strict-enums } else if (node.type in this.selectors) { this.selectors[node.type](node, parent); } diff --git a/packages/utils/src/ast-utils/helpers.ts b/packages/utils/src/ast-utils/helpers.ts index aa0eac700015..baf4daf68101 100644 --- a/packages/utils/src/ast-utils/helpers.ts +++ b/packages/utils/src/ast-utils/helpers.ts @@ -54,7 +54,6 @@ export const isTokenOfTypeWithConditions = < token: TSESTree.Token | null | undefined, ): token is TSESTree.Token & { type: TokenType } & Conditions => token?.type === tokenType && - // eslint-disable-next-line @typescript-eslint/strict-enums entries.every(([key, value]) => token[key] === value); }; From 83c5f30728eab7fa1834e99562fd713014787e95 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 3 May 2022 19:29:33 -0400 Subject: [PATCH 46/88] fix: remove types from error messages --- .../eslint-plugin/src/rules/strict-enums.ts | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 07bc30e28c79..fb79c5afe9c2 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -31,11 +31,11 @@ export default util.createRule({ messages: { incorrectIncrement: 'You cannot increment or decrement an enum type.', mismatchedAssignment: - 'The type of the enum assignment ({{ assignmentType }}) does not match the declared enum type ({{ declaredType }}) of the variable.', + 'The type of the enum assignment does not match the declared enum type of the variable.', mismatchedComparison: - 'The two things in the comparison ({{ leftType }} and {{ rightType }}) do not have a shared enum type.', + 'The two things in the comparison do not have a shared enum type.', mismatchedFunctionArgument: - 'The {{ ordinal }} argument in the function call ({{ argumentType}}) does not match the declared enum type of the function signature ({{ parameterType }}).', + 'The {{ ordinal }} argument in the function call does not match the declared enum type of the function signature.', }, schema: [ { @@ -586,10 +586,6 @@ export default util.createRule({ context.report({ node, messageId: 'mismatchedAssignment', - data: { - assignmentType: getTypeName(rightType), - declaredType: getTypeName(leftType), - }, }); } }, @@ -603,10 +599,6 @@ export default util.createRule({ context.report({ node, messageId: 'mismatchedComparison', - data: { - leftType: getTypeName(leftType), - rightType: getTypeName(rightType), - }, }); } }, @@ -638,7 +630,10 @@ export default util.createRule({ * ``` */ if (hasEnumTypes(argumentType)) { - context.report({ node, messageId: 'incorrectIncrement' }); + context.report({ + node, + messageId: 'incorrectIncrement', + }); } }, From 23ac918e71db80855792206b707468943df36dc2 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 3 May 2022 20:25:22 -0400 Subject: [PATCH 47/88] fix: removing isArray + refactoring --- .../eslint-plugin/src/rules/strict-enums.ts | 165 +++++++++--------- .../rules/strict-enums-assignment.test.ts | 12 ++ 2 files changed, 91 insertions(+), 86 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index fb79c5afe9c2..05bb9e8e2e16 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -205,30 +205,21 @@ export default util.createRule({ ); } - function isArray( - type: ts.Type, - ): type is ts.TypeReference | ts.TupleTypeReference { - const typeName = getTypeName(type); - return ( - typeChecker.isArrayType(type) || - typeChecker.isTupleType(type) || - typeName.startsWith('Iterable<') - ); - } - function isEnum(type: ts.Type): boolean { return util.isTypeFlagSet(type, ts.TypeFlags.EnumLiteral); } - function isNever(type: ts.Type): boolean { - return util.isTypeFlagSet(type, ts.TypeFlags.Never); - } - - function isNullOrUndefinedOrAny(...types: ts.Type[]): boolean { + function isNullOrUndefinedOrAnyOrUnknownOrNever( + ...types: ts.Type[] + ): boolean { return types.some(type => util.isTypeFlagSet( type, - ts.TypeFlags.Null | ts.TypeFlags.Undefined | ts.TypeFlags.Any, + ts.TypeFlags.Null | + ts.TypeFlags.Undefined | + ts.TypeFlags.Any | + ts.TypeFlags.Unknown | + ts.TypeFlags.Never, ), ); } @@ -325,47 +316,42 @@ export default util.createRule({ leftType: ts.Type, rightType: ts.Type, ): boolean { - // Handle arrays recursively - if (isArray(leftType)) { - const leftArrayType = typeChecker.getTypeArguments(leftType)[0]; - if (leftArrayType === undefined) { - return false; - } - - const rightSubTypes = tsutils.unionTypeParts(rightType); - - for (const rightSubType of rightSubTypes) { - if (!isArray(rightSubType)) { + /** + * First, recursively check for containers like the following: + * + * ```ts + * declare let fruits: Fruit[]; + * fruits = [0, 1]; + * ``` + */ + if ( + util.isTypeReferenceType(leftType) && + util.isTypeReferenceType(rightType) + ) { + const leftTypeArguments = typeChecker.getTypeArguments(leftType); + const rightTypeArguments = typeChecker.getTypeArguments(rightType); + + for (let i = 0; i < leftTypeArguments.length; i++) { + const leftTypeArgument = leftTypeArguments[i]; + const rightTypeArgument = rightTypeArguments[i]; + if ( + leftTypeArgument === undefined || + rightTypeArgument === undefined + ) { continue; } - const rightArrayType = typeChecker.getTypeArguments(rightSubType)[0]; - if (rightArrayType === undefined) { - return false; - } - - /** - * Allow empty arrays, like the following: - * - * ```ts - * const fruitArray: Fruit[] = []; - * ``` - */ - if (isNever(rightArrayType)) { - return false; - } - if ( - !isAssigningNonEnumValueToEnumVariable( - leftArrayType, - rightArrayType, + isAssigningNonEnumValueToEnumVariable( + leftTypeArgument, + rightTypeArgument, ) ) { - return false; + return true; } } - return true; + return false; } const leftEnumTypes = getEnumTypes(leftType); @@ -375,11 +361,10 @@ export default util.createRule({ } /** - * As a special case, allow assignment of null and undefined and any in - * all circumstances, since the TypeScript compiler should properly - * type-check this. + * As a special case, allow assignment of certain types that the + * TypeScript compiler should handle properly. */ - if (isNullOrUndefinedOrAny(rightType)) { + if (isNullOrUndefinedOrAnyOrUnknownOrNever(rightType)) { return false; } @@ -417,7 +402,7 @@ export default util.createRule({ * The TypeScript compiler should handle these cases properly, so the * lint rule is unneeded. */ - if (isNullOrUndefinedOrAny(leftType, rightType)) { + if (isNullOrUndefinedOrAnyOrUnknownOrNever(leftType, rightType)) { return false; } @@ -450,48 +435,54 @@ export default util.createRule({ argumentType: ts.Type, // From the function call parameterType: ts.Type, // From the function itself ): boolean { - const argumentSubTypes = tsutils.unionTypeParts(argumentType); - const parameterSubTypes = tsutils.unionTypeParts(parameterType); - - // Handle arrays recursively - if (isArray(argumentType)) { - const argumentArrayType = typeChecker.getTypeArguments(argumentType)[0]; - if (argumentArrayType === undefined) { - return false; - } + /** + * First, recursively check for functions with type containers like the + * following: + * + * ```ts + * function useFruits(fruits: Fruit[]) {} + * useFruits([0, 1]); + * ``` + */ + if (util.isTypeReferenceType(argumentType)) { + const argumentTypeArguments = + typeChecker.getTypeArguments(argumentType); - let atLeastOneParamIsEnum = false; + const parameterSubTypes = tsutils.unionTypeParts(parameterType); for (const parameterSubType of parameterSubTypes) { - if (!isArray(parameterSubType)) { + if (!util.isTypeReferenceType(parameterSubType)) { continue; } - - const parameterArrayType = - typeChecker.getTypeArguments(parameterSubType)[0]; - if (parameterArrayType === undefined) { - return false; - } - - if (hasEnumTypes(parameterArrayType)) { - atLeastOneParamIsEnum = true; - } - - if ( - !isMismatchedEnumFunctionArgument( - argumentArrayType, - parameterArrayType, - ) - ) { - return false; + const parameterTypeArguments = + typeChecker.getTypeArguments(parameterSubType); + + for (let i = 0; i < argumentTypeArguments.length; i++) { + const argumentTypeArgument = argumentTypeArguments[i]; + const parameterTypeArgument = parameterTypeArguments[i]; + if ( + argumentTypeArgument === undefined || + parameterTypeArgument === undefined + ) { + continue; + } + + if ( + isMismatchedEnumFunctionArgument( + argumentTypeArgument, + parameterTypeArgument, + ) + ) { + return true; + } } } - return atLeastOneParamIsEnum; + return false; } /** - * First, allow function calls that have nothing to do with enums, like - * the following: + * Allow function calls that have nothing to do with enums, like the + * following: * * ```ts * function useNumber(num: number) {} @@ -514,6 +505,7 @@ export default util.createRule({ * useNumber(Fruit.Apple); * ``` */ + const parameterSubTypes = tsutils.unionTypeParts(parameterType); for (const parameterSubType of parameterSubTypes) { if ( util.isTypeFlagSet( @@ -535,6 +527,7 @@ export default util.createRule({ * useFruit(fruit) * ``` */ + const argumentSubTypes = tsutils.unionTypeParts(argumentType); for (const argumentSubType of argumentSubTypes) { if (argumentSubType.isLiteral() && !isEnum(argumentSubType)) { return true; diff --git a/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts index 18380964c27e..c06093c88ecd 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts @@ -274,6 +274,18 @@ const fruitArray: Fruit[] = []; `, }); +invalid.push({ + name: 'Assigning a mismatched number enum array', + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` +declare let fruits: Fruit[]; +fruits = [Fruit2.Apple2, Fruit2.Banana2]; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + valid.push({ name: 'Assigning a new variable with a composition of bitflags', code: From 99424e1068951450568f05cba86844bf4a760a1a Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 3 May 2022 20:50:42 -0400 Subject: [PATCH 48/88] Update packages/eslint-plugin/src/rules/strict-enums.ts Co-authored-by: Brad Zacher --- packages/eslint-plugin/src/rules/strict-enums.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 05bb9e8e2e16..84dfec180f67 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -25,7 +25,7 @@ export default util.createRule({ type: 'suggestion', docs: { description: 'Disallows the usage of unsafe enum patterns', - recommended: 'error', + recommended: false, requiresTypeChecking: true, }, messages: { From 0de3b26138e3da8ab88aba6eba587884e2abd358 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 3 May 2022 23:36:19 -0400 Subject: [PATCH 49/88] fix: removing strict-enums from recommended --- packages/eslint-plugin/README.md | 2 +- packages/eslint-plugin/docs/rules/README.md | 2 +- packages/eslint-plugin/docs/rules/strict-enums.md | 2 +- .../src/configs/recommended-requiring-type-checking.ts | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index 3fcf200c7753..7a04dc52ad2a 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -177,7 +177,7 @@ Pro Tip: For larger codebases you may want to consider splitting our linting int | [`@typescript-eslint/restrict-template-expressions`](./docs/rules/restrict-template-expressions.md) | Enforce template literal expressions to be of string type | :white_check_mark: | | :thought_balloon: | | [`@typescript-eslint/sort-type-union-intersection-members`](./docs/rules/sort-type-union-intersection-members.md) | Enforces that members of a type union/intersection are sorted alphabetically | | :wrench: | | | [`@typescript-eslint/strict-boolean-expressions`](./docs/rules/strict-boolean-expressions.md) | Restricts the types allowed in boolean expressions | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/strict-enums`](./docs/rules/strict-enums.md) | Disallows the usage of unsafe enum patterns | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/strict-enums`](./docs/rules/strict-enums.md) | Disallows the usage of unsafe enum patterns | | | :thought_balloon: | | [`@typescript-eslint/switch-exhaustiveness-check`](./docs/rules/switch-exhaustiveness-check.md) | Exhaustiveness checking in switch with union type | | | :thought_balloon: | | [`@typescript-eslint/triple-slash-reference`](./docs/rules/triple-slash-reference.md) | Sets preference level for triple slash directives versus ES6-style import declarations | :white_check_mark: | | | | [`@typescript-eslint/type-annotation-spacing`](./docs/rules/type-annotation-spacing.md) | Require consistent spacing around type annotations | | :wrench: | | diff --git a/packages/eslint-plugin/docs/rules/README.md b/packages/eslint-plugin/docs/rules/README.md index 13bf51ee3a16..899ff0f2dc12 100644 --- a/packages/eslint-plugin/docs/rules/README.md +++ b/packages/eslint-plugin/docs/rules/README.md @@ -98,7 +98,7 @@ slug: / | [`@typescript-eslint/restrict-template-expressions`](./restrict-template-expressions.md) | Enforce template literal expressions to be of string type | :white_check_mark: | | :thought_balloon: | | [`@typescript-eslint/sort-type-union-intersection-members`](./sort-type-union-intersection-members.md) | Enforces that members of a type union/intersection are sorted alphabetically | | :wrench: | | | [`@typescript-eslint/strict-boolean-expressions`](./strict-boolean-expressions.md) | Restricts the types allowed in boolean expressions | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/strict-enums`](./docs/rules/strict-enums.md) | Disallows the usage of unsafe enum patterns | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/strict-enums`](./docs/rules/strict-enums.md) | Disallows the usage of unsafe enum patterns | | | :thought_balloon: | | [`@typescript-eslint/switch-exhaustiveness-check`](./switch-exhaustiveness-check.md) | Exhaustiveness checking in switch with union type | | | :thought_balloon: | | [`@typescript-eslint/triple-slash-reference`](./triple-slash-reference.md) | Sets preference level for triple slash directives versus ES6-style import declarations | :white_check_mark: | | | | [`@typescript-eslint/type-annotation-spacing`](./type-annotation-spacing.md) | Require consistent spacing around type annotations | | :wrench: | | diff --git a/packages/eslint-plugin/docs/rules/strict-enums.md b/packages/eslint-plugin/docs/rules/strict-enums.md index d949265e58cf..796686fb1717 100644 --- a/packages/eslint-plugin/docs/rules/strict-enums.md +++ b/packages/eslint-plugin/docs/rules/strict-enums.md @@ -144,6 +144,6 @@ No options are provided. ## Attributes -- [x] ✅ Recommended +- [ ] ✅ Recommended - [ ] 🔧 Fixable - [x] 💭 Requires type information diff --git a/packages/eslint-plugin/src/configs/recommended-requiring-type-checking.ts b/packages/eslint-plugin/src/configs/recommended-requiring-type-checking.ts index 7e8e2047767e..369d33d6687e 100644 --- a/packages/eslint-plugin/src/configs/recommended-requiring-type-checking.ts +++ b/packages/eslint-plugin/src/configs/recommended-requiring-type-checking.ts @@ -21,7 +21,6 @@ export = { '@typescript-eslint/require-await': 'error', '@typescript-eslint/restrict-plus-operands': 'error', '@typescript-eslint/restrict-template-expressions': 'error', - '@typescript-eslint/strict-enums': 'error', '@typescript-eslint/unbound-method': 'error', }, }; From 2d488ccb5889adede391340a1c9f77e770f77b08 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Wed, 4 May 2022 22:01:03 -0400 Subject: [PATCH 50/88] fix: simplify --- packages/eslint-plugin/src/rules/strict-enums.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 84dfec180f67..9c38191dc450 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -659,14 +659,7 @@ export default util.createRule({ * https://github.com/microsoft/TypeScript/issues/48878 */ const leftType = getTypeFromTSNode(leftTSNode.name); - if (leftType === undefined) { - continue; - } - const rightType = getTypeFromTSNode(leftTSNode.initializer); - if (rightType === undefined) { - continue; - } if (isAssigningNonEnumValueToEnumVariable(leftType, rightType)) { context.report({ From 15dc3dff438aec0273789d2cc89dfdecad397848 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Thu, 5 May 2022 22:16:43 -0400 Subject: [PATCH 51/88] fix: undoing refactoring --- .../src/rules/non-nullable-type-assertion-style.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts b/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts index bd2f91f7ca72..1e7a2128c19a 100644 --- a/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts +++ b/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts @@ -3,8 +3,6 @@ import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; -const ANY_OR_UNKNOWN = ts.TypeFlags.Any | ts.TypeFlags.Unknown; - export default util.createRule({ name: 'non-nullable-type-assertion-style', meta: { @@ -35,7 +33,7 @@ export default util.createRule({ parserServices.esTreeNodeToTSNodeMap.get(node), ); - if (util.isTypeFlagSet(type, ANY_OR_UNKNOWN)) { + if (util.isTypeFlagSet(type, ts.TypeFlags.Any | ts.TypeFlags.Unknown)) { return undefined; } From a3d0122cb97770147a350466f438e7e5f5a92b84 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Thu, 5 May 2022 22:16:43 -0400 Subject: [PATCH 52/88] fix: undoing refactoring --- .../rules/strict-enums-assignment.test.ts | 301 ----- .../rules/strict-enums-comparison.test.ts | 342 ------ .../rules/strict-enums-functions.test.ts | 1022 ----------------- .../rules/strict-enums-incrementing.test.ts | 140 --- .../eslint-plugin/tests/rules/strict-enums.ts | 53 - 5 files changed, 1858 deletions(-) delete mode 100644 packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts delete mode 100644 packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts delete mode 100644 packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts delete mode 100644 packages/eslint-plugin/tests/rules/strict-enums-incrementing.test.ts delete mode 100644 packages/eslint-plugin/tests/rules/strict-enums.ts diff --git a/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts deleted file mode 100644 index c06093c88ecd..000000000000 --- a/packages/eslint-plugin/tests/rules/strict-enums-assignment.test.ts +++ /dev/null @@ -1,301 +0,0 @@ -import { - InvalidTestCase, - ValidTestCase, -} from '@typescript-eslint/utils/src/ts-eslint'; -import rule, { MessageIds } from '../../src/rules/strict-enums'; -import { - fruit2EnumDefinition, - fruitEnumDefinition, - strictEnumsRuleTester, -} from './strict-enums'; - -const valid: ValidTestCase[] = []; -const invalid: InvalidTestCase[] = []; - -valid.push({ - name: 'Declaring an enum with an empty initializer', - code: - fruitEnumDefinition + - ` - let fruit: Fruit; - if (true) { - fruit = Fruit.Apple; - } else { - fruit = Fruit.Banana; - } - `, -}); - -/** - * In development, this would trigger run-time errors due to the - * `typeChecker.getTypeAtLocation` method being buggy and not having a proper - * function signature. - */ -valid.push({ - name: 'Declaring an "empty" variable with array destructuring', - code: ` - const myArray = [1]; - const [firstElement] = myArray; - `, -}); - -valid.push({ - name: 'Assigning a number enum literal to a number enum (with type-inference)', - code: - fruitEnumDefinition + - ` -const fruit = Fruit.Apple; - `, -}); - -valid.push({ - name: 'Assigning a number enum literal to a number enum (without type-inference)', - code: - fruitEnumDefinition + - ` -const fruit: Fruit = Fruit.Apple; - `, -}); - -valid.push({ - name: 'Assigning a number enum value to a variable of the same type with const', - code: - fruitEnumDefinition + - ` -const apple = Fruit.Apple; -const fruit: Fruit = apple; - `, -}); - -invalid.push({ - name: 'Assigning a number literal to a number enum with const', - code: - fruitEnumDefinition + - ` -const fruit: Fruit = 0; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -valid.push({ - name: 'Assigning a number enum value to a variable of the same type with let', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Apple; -fruit = Fruit.Banana; - `, -}); - -invalid.push({ - name: 'Assigning a number literal to a number enum with let', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Apple; -fruit = 1; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -invalid.push({ - name: 'Assigning an enum parent to a number enum', - code: - fruitEnumDefinition + - ` -const fruit: Fruit = Fruit; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -invalid.push({ - name: 'Assigning a mismatched enum value to a number enum', - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` -const fruit: Fruit = Fruit2.Apple2; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -valid.push({ - name: 'Assigning a number enum literal to a variable with a union type of "number enum | null" with const', - code: - fruitEnumDefinition + - ` -const fruit: Fruit | null = Fruit.Apple; - `, -}); - -valid.push({ - name: 'Assigning a null value to a variable with a union type of "number enum | null" with const', - code: - fruitEnumDefinition + - ` -const fruit: Fruit | null = null; - `, -}); - -invalid.push({ - name: 'Assigning a number literal to a variable with a union type of "number enum | null" with const', - code: - fruitEnumDefinition + - ` -const fruit: Fruit | null = 0; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -valid.push({ - name: 'Assigning a number enum literal to a variable with a union type of "number enum | null" with let', - code: - fruitEnumDefinition + - ` -let fruit: Fruit | null = null; -fruit = Fruit.Apple; - `, -}); - -valid.push({ - name: 'Assigning a null value to a variable with a union type of "number enum | null" with let', - code: - fruitEnumDefinition + - ` -let fruit: Fruit | null = Fruit.Apple; -fruit = null; - `, -}); - -invalid.push({ - name: 'Assigning a number literal to a variable with a union type of "number enum | null" with let', - code: - fruitEnumDefinition + - ` -let fruit: Fruit | null = null; -fruit = 0; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -invalid.push({ - name: 'Assigning a enum literal to a variable with a union type of "number enum | number"', - code: - fruitEnumDefinition + - ` -declare const fruit: Fruit | number; -const fruitCopy: Fruit = fruit; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -valid.push({ - name: 'Assigning variables with a composition type that includes individual enum values', - code: ` -enum Foo { - A = 1, - B = 2, - C = 3, - D = 4, -} - -declare const foo: Foo; -declare const fooSubset: Foo.A | Foo.B | Foo.C; -const x: Foo = fooSubset; -const y: Foo.A | Foo.B | Foo.C = fooSubset; -const z: Foo.A | Foo.B | Foo.C | Foo.D = foo; - `, -}); - -/** - * Intersection enum types are not checked by this rule. Even though doing this - * would almost certainly be a bad idea, a programmer would have to go to great - * lengths to do this, so we assume that the programmer knows what they are - * doing and allow it. - */ -valid.push({ - name: 'Assigning a variable with a intersection enum type', - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` -const foo: Fruit & Fruit2 = Fruit.Apple; - `, -}); - -valid.push({ - name: 'Assigning to a variable with a composition of binary flags', - code: ` -enum Flag { - Value1 = 1 << 0, - Value2 = 1 << 1, -} -const flags = Flag.Value1 | Flag.Value2; - `, -}); - -valid.push({ - name: 'Assigning a number enum array to a variable with a number enum array', - code: - fruitEnumDefinition + - ` -declare let fruits: Fruit[]; -fruits = [Fruit.Apple, Fruit.Banana]; - `, -}); - -valid.push({ - name: 'Assigning a number enum array to a variable with a number array', - code: - fruitEnumDefinition + - ` -declare let numbers: number[]; -numbers = [Fruit.Apple, Fruit.Banana]; - `, -}); - -invalid.push({ - name: 'Assigning a number array to a variable with a number enum array', - code: - fruitEnumDefinition + - ` -declare let fruits: Fruit[]; -fruits = [0, 1]; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -valid.push({ - name: 'Assigning an empty array to a variable with a number enum array', - code: - fruitEnumDefinition + - ` -const fruitArray: Fruit[] = []; - `, -}); - -invalid.push({ - name: 'Assigning a mismatched number enum array', - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` -declare let fruits: Fruit[]; -fruits = [Fruit2.Apple2, Fruit2.Banana2]; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -valid.push({ - name: 'Assigning a new variable with a composition of bitflags', - code: - fruitEnumDefinition + - ` -const fruitFlags = Fruit.Apple | Fruit.Banana; - `, -}); - -strictEnumsRuleTester.run('strict-enums-assignment', rule, { - valid, - invalid, -}); diff --git a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts deleted file mode 100644 index 2619a2eff922..000000000000 --- a/packages/eslint-plugin/tests/rules/strict-enums-comparison.test.ts +++ /dev/null @@ -1,342 +0,0 @@ -import { - InvalidTestCase, - ValidTestCase, -} from '@typescript-eslint/utils/src/ts-eslint'; -import rule, { MessageIds } from '../../src/rules/strict-enums'; -import { - fruit2EnumDefinition, - fruitEnumDefinition, - strictEnumsRuleTester, - vegetable2EnumDefinition, - vegetableEnumDefinition, -} from './strict-enums'; - -const valid: ValidTestCase[] = []; -const invalid: InvalidTestCase[] = []; - -// ---------------------- -// COMPARISON TYPES TESTS -// ---------------------- - -valid.push({ - name: 'Comparing a number with a number', - code: - fruitEnumDefinition + - ` -if (1 === 2) { -} - `, -}); - -valid.push({ - name: 'Comparing a number enum literal to any', - code: - fruitEnumDefinition + - ` -declare thing: any; -if (Fruit.Apple === thing) { -} - `, -}); - -valid.push({ - name: 'Comparing a number enum literal to literal undefined', - code: - fruitEnumDefinition + - ` -if (Fruit.Apple === undefined) { -} - `, -}); - -valid.push({ - name: 'Comparing a number enum literal to literal null', - code: - fruitEnumDefinition + - ` -if (Fruit.Apple === null) { -} - `, -}); - -valid.push({ - name: 'Comparing a number enum literal with an enum literal of the same type', - code: - fruitEnumDefinition + - ` -if (Fruit.Apple === Fruit.Banana) { -} - `, -}); - -valid.push({ - name: 'Comparing a number enum value with an enum literal of the same type', - code: - fruitEnumDefinition + - ` -const fruit = Fruit.Apple; -if (fruit === Fruit.Banana) { -} - `, -}); - -valid.push({ - name: 'Comparing a string enum value with an enum literal of the same type', - code: - vegetableEnumDefinition + - ` -const vegetable = Vegetable.Lettuce; -if (vegetable === Vegetable.Carrot) { -} - `, -}); - -valid.push({ - name: 'Comparing a number enum value with a value of the same type', - code: - fruitEnumDefinition + - ` -const fruit1 = Fruit.Apple; -const fruit2 = Fruit.Banana; -if (fruit1 === fruit2) { -} - `, -}); - -valid.push({ - name: 'Comparing a string enum value with a value of the same type', - code: - vegetableEnumDefinition + - ` -const vegetable1 = Vegetable.Lettuce; -const vegetable2 = Vegetable.Carrot; -if (vegetable1 === vegetable2) { -} - `, -}); - -invalid.push({ - name: 'Comparing a number enum literal with a number literal', - code: - fruitEnumDefinition + - ` -if (Fruit.Apple === 1) { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a string enum literal with a string literal', - code: - vegetableEnumDefinition + - ` -if (Vegetable.Lettuce === 'carrot') { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a number literal with a number enum literal', - code: - fruitEnumDefinition + - ` -if (1 === Fruit.Apple) { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a string literal with a string enum literal', - code: - vegetableEnumDefinition + - ` -if ('carrot' === Vegetable.Lettuce) { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a number enum value with a number literal', - code: - fruitEnumDefinition + - ` -const fruit = Fruit.Apple; -if (fruit === 1) { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a string enum value with a string literal', - code: - vegetableEnumDefinition + - ` -const vegetable = Vegetable.Lettuce; -if (vegetable === 'carrot') { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a number literal with an enum value', - code: - fruitEnumDefinition + - ` -const fruit = Fruit.Apple; -if (1 === fruit) { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a string literal with an enum value', - code: - vegetableEnumDefinition + - ` -const vegetable = Vegetable.Lettuce; -if ('carrot' === vegetable) { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a number enum literal with a different enum literal', - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` -if (Fruit.Apple === Fruit2.Apple2) { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a string enum literal with a different enum literal', - code: - vegetableEnumDefinition + - vegetable2EnumDefinition + - ` -if (Vegetable.Lettuce === Vegetable2.Lettuce2) { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a number enum value with a different enum literal', - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` -const fruit = Fruit.Apple; -if (fruit === Fruit2.Apple2) { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a string enum value with a different enum literal', - code: - vegetableEnumDefinition + - vegetable2EnumDefinition + - ` -const vegetable = Vegetable.Lettuce; -if (vegetable === Vegetable2.Lettuce2) { -} - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -valid.push({ - name: 'Comparing a generic enum extension value with a number enum literal', - code: - fruitEnumDefinition + - ` -class FruitClass { - constructor(type: FruitType) { - if (type === Fruit.Apple) {} - } -} - `, -}); - -valid.push({ - name: 'Comparing a number union to a number union', - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` -declare const left: number | Fruit; -declare const right: number | Fruit2; -if (left === right) {} - `, -}); - -valid.push({ - name: 'Comparing a string union to a string union', - code: - vegetableEnumDefinition + - vegetable2EnumDefinition + - ` -declare const left: string | Vegetable; -declare const right: string | Vegetable2; -if (left === right) {} - `, -}); - -valid.push({ - name: 'Comparing a string enum literal to an intersection with a string (simple)', - code: - vegetableEnumDefinition + - ` -type WeirdString = string & { __someBrand: void; }; -declare weirdString: WeirdString; -if (Vegetable.Lettuce === weirdString) { -} - `, -}); - -valid.push({ - name: 'Comparing a string literal to an intersection with a string (complicated)', - code: - vegetableEnumDefinition + - ` -enum InternalSymbolName { - Foo = "foo", - Bar = "bar", -} -type __String = - | (string & { __escapedIdentifier: void; }) - | (void & { __escapedIdentifier: void; }) - | InternalSymbolName; -declare const weirdString: __String; -if (weirdString === 'someArbitraryValue') { -} - `, -}); - -valid.push({ - name: 'Comparing using the in operator', - code: - vegetableEnumDefinition + - ` -const foo = {}; -const vegetable = Vegetable.Lettuce; -if (vegetable in foo) {} - `, -}); - -strictEnumsRuleTester.run('strict-enums-comparison', rule, { - valid, - invalid, -}); diff --git a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts deleted file mode 100644 index 660fb6f92b24..000000000000 --- a/packages/eslint-plugin/tests/rules/strict-enums-functions.test.ts +++ /dev/null @@ -1,1022 +0,0 @@ -import { - InvalidTestCase, - ValidTestCase, -} from '@typescript-eslint/utils/src/ts-eslint'; -import rule, { MessageIds } from '../../src/rules/strict-enums'; -import { - fruitEnumDefinition, - strictEnumsRuleTester, - vegetableEnumDefinition, -} from './strict-enums'; - -const valid: ValidTestCase[] = []; -const invalid: InvalidTestCase[] = []; - -/** A function that takes a number enum. */ -const fruitFunctionDefinition = - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit) {} -`; - -valid.push({ - name: 'Using a number enum literal on a non-existent function', - code: ` -useFruit(0); - `, -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes a number enum', - code: - fruitFunctionDefinition + - ` -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value on a function that takes a number enum', - code: - fruitFunctionDefinition + - ` -declare const fruit: Fruit.Apple; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes a number enum', - code: - fruitFunctionDefinition + - ` -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a matching number enum literal on a function that takes an enum literal', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple) {} -useFruit(Fruit.Apple); - `, -}); - -/** - * The TypeScript compiler will correctly handle this case, so the lint rule - * does not need to care. - */ -valid.push({ - name: 'Using a non-matching number enum literal on a function that takes an enum literal', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple) {} -useFruit(Fruit.Banana); - `, -}); - -valid.push({ - name: 'Using a matching number enum value on a function that takes an enum literal', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple) {} -declare const fruit: Fruit.Apple; -useFruit(fruit); - `, -}); - -/** - * The TypeScript compiler will correctly handle this case, so the lint rule - * does not need to care. - */ -valid.push({ - name: 'Using a non-matching number enum value on a function that takes an enum literal', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple) {} -declare const fruit: Fruit.Banana; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes an enum literal', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes a number enum with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit = Fruit.Apple) {} -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value on a function that takes a number enum with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit = Fruit.Apple) {} -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes a number enum with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit = Fruit.Apple) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes a number enum literal with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value on a function that takes a number enum literal with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes a number enum literal with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes a number enum | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null) {} -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value on a function that takes a number enum | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null) {} -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -valid.push({ - name: 'Using a null literal on a function that takes a number enum | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null) {} -useFruit(null); - `, -}); - -valid.push({ - name: 'Using a null value on a function that takes a number enum | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null) {} -const fruit = null; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes a number enum | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes a number enum | null with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null = Fruit.Apple) {} -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value on a function that takes a number enum | null with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null = Fruit.Apple) {} -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -valid.push({ - name: 'Using a null literal on a function that takes a number enum | null with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null = Fruit.Apple) {} -useFruit(null); - `, -}); - -valid.push({ - name: 'Using a null value on a function that takes a number enum | null with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null = Fruit.Apple) {} -const fruit = null; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes a number enum | null with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null = Fruit.Apple) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes a number enum literal | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null) {} -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value on a function that takes a number enum literal | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null) {} -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -valid.push({ - name: 'Using a null literal on a function that takes a number enum literal | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null) {} -useFruit(null); - `, -}); - -valid.push({ - name: 'Using a null value on a function that takes a number enum literal | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null) {} -const fruit = null; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes a number enum literal | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes a number enum literal | null with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value on a function that takes a number enum literal | null with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -valid.push({ - name: 'Using a null literal on a function that takes a number enum literal | null with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} -useFruit(null); - `, -}); - -valid.push({ - name: 'Using a null value on a function that takes a number enum literal | null with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} -const fruit = null; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes a number enum literal | null with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes a number enum literal | number enum literal | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value on a function that takes a number enum literal | number enum literal | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -valid.push({ - name: 'Using a null literal on a function that takes a number enum literal | number enum literal | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} -useFruit(null); - `, -}); - -valid.push({ - name: 'Using a null value on a function that takes a number enum literal | number enum literal | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} -const fruit = null; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes a number enum literal | number enum literal | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using an enum from a composition type on a function that takes a number enum', - code: - fruitEnumDefinition + - ` -interface BaseNode { - type: Fruit; -} - -interface AppleNode extends BaseNode { - type: Fruit.Apple; - apple: number; -} - -interface BananaNode extends BaseNode { - type: Fruit.Apple; - banana: Number; -} - -type Node = AppleNode | BananaNode; - -const fruitNodesSet = new Set([ - Fruit.Apple, - Fruit.Banana, -]); - -const appleNode: AppleNode = { - type: Fruit.Apple, - apple: 1, -}; - -fruitNodesSet.has(appleNode.type); - `, -}); - -valid.push({ - name: 'Using an enum number literal in a Set method', - code: - fruitEnumDefinition + - ` -const fruitSet = new Set([ - Fruit.Apple, - Fruit.Banana, -]); - -fruitSet.has(Fruit.Apple); - `, -}); - -invalid.push({ - name: 'Using a number literal in a Set method', - code: - fruitEnumDefinition + - ` -const fruitSet = new Set([ - Fruit.Apple, - Fruit.Banana, -]); - -fruitSet.has(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a partial union type on a function that takes a number enum', - code: - fruitFunctionDefinition + - ` -declare const fruitUnion: Fruit.Apple | Fruit.Banana; -useFruit(fruitUnion); -`, -}); - -valid.push({ - name: 'Using a partial union type on a function that takes a partial union', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | Fruit.Banana) {} -declare const fruitUnion: Fruit.Apple | Fruit.Banana; -useFruit(fruitUnion); -`, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes a partial union', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | Fruit.Banana) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a full enum union on a function that takes a number enum', - code: - fruitFunctionDefinition + - ` -declare const fruitUnion: Fruit.Apple | Fruit.Banana | Fruit.Pear; -useFruit(fruitUnion); -`, -}); - -valid.push({ - name: 'Using a full enum union on a function that takes a full enum union', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | Fruit.Banana | Fruit.Pear) {} -declare const fruitUnion: Fruit.Apple | Fruit.Banana | Fruit.Pear; -useFruit(fruitUnion); -`, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes a full enum union', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | Fruit.Banana | Fruit.Pear) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a partial enum union on a function that takes a number enum (from a type narrowing switch statement)', - code: - fruitFunctionDefinition + - ` -declare const fruit: Fruit; -switch (fruit) { - case Fruit.Apple: - case Fruit.Banana: { - useFruit(fruit); - } -} -`, -}); - -valid.push({ - name: 'Using a number enum on a function that takes an extension type', - code: - fruitEnumDefinition + - ` -function useFruit(fruitType: FruitType) {} -useFruit(Fruit.Apple); -`, -}); - -valid.push({ - name: 'Using a number literal on a function that takes an extension type', - code: - fruitEnumDefinition + - ` -function useFruit(fruitType: FruitType) {} -useFruit(0); -`, -}); - -valid.push({ - name: 'Using a number enum on a function that takes an enum extension type', - code: - fruitEnumDefinition + - ` -function useFruit(fruitType: FruitType) {} -useFruit(Fruit.Apple); -`, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes an enum extension type', - code: - fruitEnumDefinition + - ` -function useFruit(fruitType: FruitType) {} -useFruit(0); -`, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum on a function that takes an enum extension type', - code: - fruitEnumDefinition + - ` -class FruitClass { - constructor(type: FruitType) {} - useFruit(type: FruitType) {} -} -const fruitClass = new FruitClass(Fruit.Apple); -fruitClass.useFruit(Fruit.Apple); -`, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes an enum extension type', - code: - fruitEnumDefinition + - ` -class FruitClass { - constructor(type: FruitType) {} - useFruit(type: FruitType) {} -} -const fruitClass = new FruitClass(0); -fruitClass.useFruit(0); - `, - errors: [ - { messageId: 'mismatchedFunctionArgument' }, - { messageId: 'mismatchedFunctionArgument' }, - ], -}); - -valid.push({ - name: 'Using a number array on a function that takes a number array', - code: - fruitEnumDefinition + - ` -function useNumbers(numberArray: number[]) {} -useNumbers([0, 1]); - `, -}); - -valid.push({ - name: 'Using a number enum array on a function that takes a number enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitArray: Fruit[]) {} -useFruit([Fruit.Apple, Fruit.Banana]); - `, -}); - -invalid.push({ - name: 'Using a number array on a function that takes a number enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitArray: Fruit[]) {} -useFruit([0, 1]); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -invalid.push({ - name: 'Using a mixed array on a function that takes a number enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitArray: Fruit[]) {} -useFruit([Fruit.Apple, 1]); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number literal on a function that takes a number', - code: ` -function useNumber(num: number) {} -useNumber(0); - `, -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes a number', - code: - fruitEnumDefinition + - ` -function useNumber(num: number) {} -useNumber(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a string literal on a function that takes a string', - code: - vegetableEnumDefinition + - ` -function useString(str: string) {} -useString('lettuce'); - `, -}); - -valid.push({ - name: 'Using a string enum literal on a function that takes a string', - code: - vegetableEnumDefinition + - ` -function useString(str: string) {} -useString(Vegetable.Lettuce); - `, -}); - -valid.push({ - name: 'Using a number literal on a function that takes any', - code: ` -function useAnything(something: any) {} -useAnything(0); - `, -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes any', - code: - fruitEnumDefinition + - ` -function useAnything(something: any) {} -useAnything(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number literal on a function that takes unknown', - code: ` -function useUnknown(something: unknown) {} -useUnknown(0); - `, -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes unknown', - code: - fruitEnumDefinition + - ` -function useUnknown(something: unknown) {} -useUnknown(Fruit.Apple); - `, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes enum | enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes enum | enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum array on a function that takes enum | enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} -useFruit([Fruit.Apple, Fruit.Banana]); - `, -}); - -valid.push({ - name: 'Using a enum | enum array union on a function that takes enum | enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} -declare const fruit: Fruit | Fruit[]; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number array on a function that takes enum | enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} -useFruit([0, 1]); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number on a function that takes number | enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitOrFruitArray: number | Fruit[]) {} -useFruit(0); - `, -}); - -valid.push({ - name: 'Using an enum array on a function that takes number | enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitOrFruitArray: number | Fruit[]) {} -useFruit([Fruit.Apple, Fruit.Banana]); - `, -}); - -invalid.push({ - name: 'Using a number array on a function that takes number | enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitOrFruitArray: number | Fruit[]) {} -useFruit([0, 1]); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -invalid.push({ - name: 'Using a number literal on a variadic function', - code: - fruitEnumDefinition + - ` -function useFruit(...fruits: Fruit[]) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a variadic function', - code: - fruitEnumDefinition + - ` -function useFruit(...fruits: Fruit[]) {} -useFruit(Fruit.Apple); -useFruit(Fruit.Apple, Fruit.Banana); - `, -}); - -invalid.push({ - name: 'Using a number enum literal and a number literal on a variadic function', - code: - fruitEnumDefinition + - ` -function useFruit(...fruits: Fruit[]) {} -useFruit(Fruit.Apple, 0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a generic function with a default generic type that is unspecified as any', - code: - fruitEnumDefinition + - ` -function toEqual(expected: E): void {} -toEqual(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum literal on a generic function with a default generic type that is unspecified as a number enum', - code: - fruitEnumDefinition + - ` -function toEqual(expected: E): void {} -toEqual(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum literal on a generic function with a default generic type that is specified as any', - code: - fruitEnumDefinition + - ` -function toEqual(expected: E): void {} -toEqual(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum literal on a generic function with a default generic type that is specified as a number enum', - code: - fruitEnumDefinition + - ` -function toEqual(expected: E): void {} -toEqual(Fruit.Apple); - `, -}); - -invalid.push({ - name: 'Using a number literal on a generic function with a default generic type that is specified as a number enum', - code: - fruitEnumDefinition + - ` -function toEqual(expected: E): void {} -toEqual(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a generic function with a default generic type that is unspecified as any + extra arg', - code: - fruitEnumDefinition + - ` -function toEqual(arg1: number, expected: E): void {} -toEqual(0, Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum literal on a generic function with a default generic type that is unspecified as a number enum + extra arg', - code: - fruitEnumDefinition + - ` -function toEqual(arg1: number, expected: E): void {} -toEqual(0, Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum literal on a generic function with a default generic type that is specified as any + extra arg', - code: - fruitEnumDefinition + - ` -function toEqual(arg1: number, expected: E): void {} -toEqual(0, Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum literal on a generic function with a default generic type that is specified as a number enum + extra arg', - code: - fruitEnumDefinition + - ` -function toEqual(arg1: number, expected: E): void {} -toEqual(0, Fruit.Apple); - `, -}); - -invalid.push({ - name: 'Using a number literal on a generic function with a default generic type that is specified as a number enum + extra arg', - code: - fruitEnumDefinition + - ` -function toEqual(arg1: number, expected: E): void {} -toEqual(0, 0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using JSON.stringify', - code: ` -JSON.stringify( - {}, - (_, value: unknown) => value ?? undefined, - 2, -); - `, -}); - -valid.push({ - name: 'Using flatten', - code: ` -function flatten(arr: T[][]): T[] { - return arr.reduce((acc, a) => acc.concat(a), []); -} - `, -}); - -strictEnumsRuleTester.run('strict-enums-functions', rule, { - valid, - invalid, -}); diff --git a/packages/eslint-plugin/tests/rules/strict-enums-incrementing.test.ts b/packages/eslint-plugin/tests/rules/strict-enums-incrementing.test.ts deleted file mode 100644 index eaf586b8b667..000000000000 --- a/packages/eslint-plugin/tests/rules/strict-enums-incrementing.test.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { - InvalidTestCase, - ValidTestCase, -} from '@typescript-eslint/utils/src/ts-eslint'; -import rule, { MessageIds } from '../../src/rules/strict-enums'; -import { fruitEnumDefinition, strictEnumsRuleTester } from './strict-enums'; - -const valid: ValidTestCase[] = []; -const invalid: InvalidTestCase[] = []; - -valid.push({ - name: 'Incrementing a number (postfix)', - code: - fruitEnumDefinition + - ` -let fruit = 0; -fruit++; - `, -}); - -invalid.push({ - name: 'Incrementing a number enum value (postfix)', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Apple; -fruit++; - `, - errors: [{ messageId: 'incorrectIncrement' }], -}); - -valid.push({ - name: 'Decrementing a number (postfix)', - code: - fruitEnumDefinition + - ` -let fruit = 1; -fruit--; - `, -}); - -invalid.push({ - name: 'Decrementing a number enum value (postfix)', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Banana; -fruit--; - `, - errors: [{ messageId: 'incorrectIncrement' }], -}); - -valid.push({ - name: 'Incrementing a number (prefix)', - code: - fruitEnumDefinition + - ` -let fruit = 0; -++fruit; - `, -}); - -invalid.push({ - name: 'Incrementing a number enum value (prefix)', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Apple; -++fruit; - `, - errors: [{ messageId: 'incorrectIncrement' }], -}); - -valid.push({ - name: 'Decrementing a number (prefix)', - code: - fruitEnumDefinition + - ` -let fruit = 1; ---fruit - `, -}); - -invalid.push({ - name: 'Decrementing a number enum value (prefix)', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Banana; ---fruit; - `, - errors: [{ messageId: 'incorrectIncrement' }], -}); - -valid.push({ - name: 'Incrementing a number (assignment operator)', - code: - fruitEnumDefinition + - ` -let fruit = 0; -fruit += 1; - `, -}); - -invalid.push({ - name: 'Incrementing a number enum value (assignment operator)', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Apple; -fruit += 1; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -valid.push({ - name: 'Decrementing a number (assignment operator)', - code: - fruitEnumDefinition + - ` -let fruit = 1; -fruit -= 1; - `, -}); - -invalid.push({ - name: 'Decrementing a number enum value (assignment operator)', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Banana; -fruit -= 1; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -strictEnumsRuleTester.run('strict-enums-incrementing', rule, { - valid, - invalid, -}); diff --git a/packages/eslint-plugin/tests/rules/strict-enums.ts b/packages/eslint-plugin/tests/rules/strict-enums.ts deleted file mode 100644 index 53453a3085f2..000000000000 --- a/packages/eslint-plugin/tests/rules/strict-enums.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { getFixturesRootDir, RuleTester } from '../RuleTester'; - -const rootDir = getFixturesRootDir(); -export const strictEnumsRuleTester = new RuleTester({ - parserOptions: { - ecmaVersion: 2015, - tsconfigRootDir: rootDir, - project: './tsconfig.json', - }, - parser: '@typescript-eslint/parser', -}); - -/** A number enum. */ -export const fruitEnumDefinition = ` -enum Fruit { - Apple, - Banana, - Pear, -} -`; - -/** A different number enum. */ -export const fruit2EnumDefinition = ` -enum Fruit2 { - Apple2, - Banana2, - Pear2, -} -`; - -/** - * A string enum. - * - * String enums are almost exclusively used for comparison tests, since the - * TypeScript compiler does a good job of ensuring safety for string enum - * variable assignment and usage in functions. - */ -export const vegetableEnumDefinition = ` - enum Vegetable { - Lettuce = 'lettuce', - Carrot = 'carrot', - Celery = 'celery', - } - `; - -/** A different string enum. */ -export const vegetable2EnumDefinition = ` -enum Vegetable2 { - Lettuce2 = 'lettuce2', - Carrot2 = 'carrot2', - Celery2 = 'celery2', -} -`; From 5cd8fa70307abfda9ba432b6f3c3a4c9a4cb3f3d Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Thu, 5 May 2022 22:21:59 -0400 Subject: [PATCH 53/88] fix: moving tests into subdirectory --- .../strict-enums-assignment.test.ts | 301 +++++ .../strict-enums-comparison.test.ts | 342 ++++++ .../strict-enums-functions.test.ts | 1022 +++++++++++++++++ .../strict-enums-incrementing.test.ts | 140 +++ .../tests/rules/strict-enums/strict-enums.ts | 53 + 5 files changed, 1858 insertions(+) create mode 100644 packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts create mode 100644 packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts create mode 100644 packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts create mode 100644 packages/eslint-plugin/tests/rules/strict-enums/strict-enums-incrementing.test.ts create mode 100644 packages/eslint-plugin/tests/rules/strict-enums/strict-enums.ts diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts new file mode 100644 index 000000000000..e20ffe1fb721 --- /dev/null +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts @@ -0,0 +1,301 @@ +import { + InvalidTestCase, + ValidTestCase, +} from '@typescript-eslint/utils/src/ts-eslint'; +import rule, { MessageIds } from '../../../src/rules/strict-enums'; +import { + fruit2EnumDefinition, + fruitEnumDefinition, + strictEnumsRuleTester, +} from './strict-enums'; + +const valid: ValidTestCase[] = []; +const invalid: InvalidTestCase[] = []; + +valid.push({ + name: 'Declaring an enum with an empty initializer', + code: + fruitEnumDefinition + + ` + let fruit: Fruit; + if (true) { + fruit = Fruit.Apple; + } else { + fruit = Fruit.Banana; + } + `, +}); + +/** + * In development, this would trigger run-time errors due to the + * `typeChecker.getTypeAtLocation` method being buggy and not having a proper + * function signature. + */ +valid.push({ + name: 'Declaring an "empty" variable with array destructuring', + code: ` + const myArray = [1]; + const [firstElement] = myArray; + `, +}); + +valid.push({ + name: 'Assigning a number enum literal to a number enum (with type-inference)', + code: + fruitEnumDefinition + + ` +const fruit = Fruit.Apple; + `, +}); + +valid.push({ + name: 'Assigning a number enum literal to a number enum (without type-inference)', + code: + fruitEnumDefinition + + ` +const fruit: Fruit = Fruit.Apple; + `, +}); + +valid.push({ + name: 'Assigning a number enum value to a variable of the same type with const', + code: + fruitEnumDefinition + + ` +const apple = Fruit.Apple; +const fruit: Fruit = apple; + `, +}); + +invalid.push({ + name: 'Assigning a number literal to a number enum with const', + code: + fruitEnumDefinition + + ` +const fruit: Fruit = 0; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +valid.push({ + name: 'Assigning a number enum value to a variable of the same type with let', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Apple; +fruit = Fruit.Banana; + `, +}); + +invalid.push({ + name: 'Assigning a number literal to a number enum with let', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Apple; +fruit = 1; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +invalid.push({ + name: 'Assigning an enum parent to a number enum', + code: + fruitEnumDefinition + + ` +const fruit: Fruit = Fruit; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +invalid.push({ + name: 'Assigning a mismatched enum value to a number enum', + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` +const fruit: Fruit = Fruit2.Apple2; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +valid.push({ + name: 'Assigning a number enum literal to a variable with a union type of "number enum | null" with const', + code: + fruitEnumDefinition + + ` +const fruit: Fruit | null = Fruit.Apple; + `, +}); + +valid.push({ + name: 'Assigning a null value to a variable with a union type of "number enum | null" with const', + code: + fruitEnumDefinition + + ` +const fruit: Fruit | null = null; + `, +}); + +invalid.push({ + name: 'Assigning a number literal to a variable with a union type of "number enum | null" with const', + code: + fruitEnumDefinition + + ` +const fruit: Fruit | null = 0; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +valid.push({ + name: 'Assigning a number enum literal to a variable with a union type of "number enum | null" with let', + code: + fruitEnumDefinition + + ` +let fruit: Fruit | null = null; +fruit = Fruit.Apple; + `, +}); + +valid.push({ + name: 'Assigning a null value to a variable with a union type of "number enum | null" with let', + code: + fruitEnumDefinition + + ` +let fruit: Fruit | null = Fruit.Apple; +fruit = null; + `, +}); + +invalid.push({ + name: 'Assigning a number literal to a variable with a union type of "number enum | null" with let', + code: + fruitEnumDefinition + + ` +let fruit: Fruit | null = null; +fruit = 0; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +invalid.push({ + name: 'Assigning a enum literal to a variable with a union type of "number enum | number"', + code: + fruitEnumDefinition + + ` +declare const fruit: Fruit | number; +const fruitCopy: Fruit = fruit; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +valid.push({ + name: 'Assigning variables with a composition type that includes individual enum values', + code: ` +enum Foo { + A = 1, + B = 2, + C = 3, + D = 4, +} + +declare const foo: Foo; +declare const fooSubset: Foo.A | Foo.B | Foo.C; +const x: Foo = fooSubset; +const y: Foo.A | Foo.B | Foo.C = fooSubset; +const z: Foo.A | Foo.B | Foo.C | Foo.D = foo; + `, +}); + +/** + * Intersection enum types are not checked by this rule. Even though doing this + * would almost certainly be a bad idea, a programmer would have to go to great + * lengths to do this, so we assume that the programmer knows what they are + * doing and allow it. + */ +valid.push({ + name: 'Assigning a variable with a intersection enum type', + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` +const foo: Fruit & Fruit2 = Fruit.Apple; + `, +}); + +valid.push({ + name: 'Assigning to a variable with a composition of binary flags', + code: ` +enum Flag { + Value1 = 1 << 0, + Value2 = 1 << 1, +} +const flags = Flag.Value1 | Flag.Value2; + `, +}); + +valid.push({ + name: 'Assigning a number enum array to a variable with a number enum array', + code: + fruitEnumDefinition + + ` +declare let fruits: Fruit[]; +fruits = [Fruit.Apple, Fruit.Banana]; + `, +}); + +valid.push({ + name: 'Assigning a number enum array to a variable with a number array', + code: + fruitEnumDefinition + + ` +declare let numbers: number[]; +numbers = [Fruit.Apple, Fruit.Banana]; + `, +}); + +invalid.push({ + name: 'Assigning a number array to a variable with a number enum array', + code: + fruitEnumDefinition + + ` +declare let fruits: Fruit[]; +fruits = [0, 1]; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +valid.push({ + name: 'Assigning an empty array to a variable with a number enum array', + code: + fruitEnumDefinition + + ` +const fruitArray: Fruit[] = []; + `, +}); + +invalid.push({ + name: 'Assigning a mismatched number enum array', + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` +declare let fruits: Fruit[]; +fruits = [Fruit2.Apple2, Fruit2.Banana2]; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +valid.push({ + name: 'Assigning a new variable with a composition of bitflags', + code: + fruitEnumDefinition + + ` +const fruitFlags = Fruit.Apple | Fruit.Banana; + `, +}); + +strictEnumsRuleTester.run('strict-enums-assignment', rule, { + valid, + invalid, +}); diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts new file mode 100644 index 000000000000..30e9df175ef4 --- /dev/null +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts @@ -0,0 +1,342 @@ +import { + InvalidTestCase, + ValidTestCase, +} from '@typescript-eslint/utils/src/ts-eslint'; +import rule, { MessageIds } from '../../../src/rules/strict-enums'; +import { + fruit2EnumDefinition, + fruitEnumDefinition, + strictEnumsRuleTester, + vegetable2EnumDefinition, + vegetableEnumDefinition, +} from './strict-enums'; + +const valid: ValidTestCase[] = []; +const invalid: InvalidTestCase[] = []; + +// ---------------------- +// COMPARISON TYPES TESTS +// ---------------------- + +valid.push({ + name: 'Comparing a number with a number', + code: + fruitEnumDefinition + + ` +if (1 === 2) { +} + `, +}); + +valid.push({ + name: 'Comparing a number enum literal to any', + code: + fruitEnumDefinition + + ` +declare thing: any; +if (Fruit.Apple === thing) { +} + `, +}); + +valid.push({ + name: 'Comparing a number enum literal to literal undefined', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple === undefined) { +} + `, +}); + +valid.push({ + name: 'Comparing a number enum literal to literal null', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple === null) { +} + `, +}); + +valid.push({ + name: 'Comparing a number enum literal with an enum literal of the same type', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple === Fruit.Banana) { +} + `, +}); + +valid.push({ + name: 'Comparing a number enum value with an enum literal of the same type', + code: + fruitEnumDefinition + + ` +const fruit = Fruit.Apple; +if (fruit === Fruit.Banana) { +} + `, +}); + +valid.push({ + name: 'Comparing a string enum value with an enum literal of the same type', + code: + vegetableEnumDefinition + + ` +const vegetable = Vegetable.Lettuce; +if (vegetable === Vegetable.Carrot) { +} + `, +}); + +valid.push({ + name: 'Comparing a number enum value with a value of the same type', + code: + fruitEnumDefinition + + ` +const fruit1 = Fruit.Apple; +const fruit2 = Fruit.Banana; +if (fruit1 === fruit2) { +} + `, +}); + +valid.push({ + name: 'Comparing a string enum value with a value of the same type', + code: + vegetableEnumDefinition + + ` +const vegetable1 = Vegetable.Lettuce; +const vegetable2 = Vegetable.Carrot; +if (vegetable1 === vegetable2) { +} + `, +}); + +invalid.push({ + name: 'Comparing a number enum literal with a number literal', + code: + fruitEnumDefinition + + ` +if (Fruit.Apple === 1) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a string enum literal with a string literal', + code: + vegetableEnumDefinition + + ` +if (Vegetable.Lettuce === 'carrot') { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a number literal with a number enum literal', + code: + fruitEnumDefinition + + ` +if (1 === Fruit.Apple) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a string literal with a string enum literal', + code: + vegetableEnumDefinition + + ` +if ('carrot' === Vegetable.Lettuce) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a number enum value with a number literal', + code: + fruitEnumDefinition + + ` +const fruit = Fruit.Apple; +if (fruit === 1) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a string enum value with a string literal', + code: + vegetableEnumDefinition + + ` +const vegetable = Vegetable.Lettuce; +if (vegetable === 'carrot') { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a number literal with an enum value', + code: + fruitEnumDefinition + + ` +const fruit = Fruit.Apple; +if (1 === fruit) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a string literal with an enum value', + code: + vegetableEnumDefinition + + ` +const vegetable = Vegetable.Lettuce; +if ('carrot' === vegetable) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a number enum literal with a different enum literal', + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` +if (Fruit.Apple === Fruit2.Apple2) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a string enum literal with a different enum literal', + code: + vegetableEnumDefinition + + vegetable2EnumDefinition + + ` +if (Vegetable.Lettuce === Vegetable2.Lettuce2) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a number enum value with a different enum literal', + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` +const fruit = Fruit.Apple; +if (fruit === Fruit2.Apple2) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +invalid.push({ + name: 'Comparing a string enum value with a different enum literal', + code: + vegetableEnumDefinition + + vegetable2EnumDefinition + + ` +const vegetable = Vegetable.Lettuce; +if (vegetable === Vegetable2.Lettuce2) { +} + `, + errors: [{ messageId: 'mismatchedComparison' }], +}); + +valid.push({ + name: 'Comparing a generic enum extension value with a number enum literal', + code: + fruitEnumDefinition + + ` +class FruitClass { + constructor(type: FruitType) { + if (type === Fruit.Apple) {} + } +} + `, +}); + +valid.push({ + name: 'Comparing a number union to a number union', + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` +declare const left: number | Fruit; +declare const right: number | Fruit2; +if (left === right) {} + `, +}); + +valid.push({ + name: 'Comparing a string union to a string union', + code: + vegetableEnumDefinition + + vegetable2EnumDefinition + + ` +declare const left: string | Vegetable; +declare const right: string | Vegetable2; +if (left === right) {} + `, +}); + +valid.push({ + name: 'Comparing a string enum literal to an intersection with a string (simple)', + code: + vegetableEnumDefinition + + ` +type WeirdString = string & { __someBrand: void; }; +declare weirdString: WeirdString; +if (Vegetable.Lettuce === weirdString) { +} + `, +}); + +valid.push({ + name: 'Comparing a string literal to an intersection with a string (complicated)', + code: + vegetableEnumDefinition + + ` +enum InternalSymbolName { + Foo = "foo", + Bar = "bar", +} +type __String = + | (string & { __escapedIdentifier: void; }) + | (void & { __escapedIdentifier: void; }) + | InternalSymbolName; +declare const weirdString: __String; +if (weirdString === 'someArbitraryValue') { +} + `, +}); + +valid.push({ + name: 'Comparing using the in operator', + code: + vegetableEnumDefinition + + ` +const foo = {}; +const vegetable = Vegetable.Lettuce; +if (vegetable in foo) {} + `, +}); + +strictEnumsRuleTester.run('strict-enums-comparison', rule, { + valid, + invalid, +}); diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts new file mode 100644 index 000000000000..8b15940ad8a1 --- /dev/null +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts @@ -0,0 +1,1022 @@ +import { + InvalidTestCase, + ValidTestCase, +} from '@typescript-eslint/utils/src/ts-eslint'; +import rule, { MessageIds } from '../../../src/rules/strict-enums'; +import { + fruitEnumDefinition, + strictEnumsRuleTester, + vegetableEnumDefinition, +} from './strict-enums'; + +const valid: ValidTestCase[] = []; +const invalid: InvalidTestCase[] = []; + +/** A function that takes a number enum. */ +const fruitFunctionDefinition = + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit) {} +`; + +valid.push({ + name: 'Using a number enum literal on a non-existent function', + code: ` +useFruit(0); + `, +}); + +valid.push({ + name: 'Using a number enum literal on a function that takes a number enum', + code: + fruitFunctionDefinition + + ` +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value on a function that takes a number enum', + code: + fruitFunctionDefinition + + ` +declare const fruit: Fruit.Apple; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal on a function that takes a number enum', + code: + fruitFunctionDefinition + + ` +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a matching number enum literal on a function that takes an enum literal', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple) {} +useFruit(Fruit.Apple); + `, +}); + +/** + * The TypeScript compiler will correctly handle this case, so the lint rule + * does not need to care. + */ +valid.push({ + name: 'Using a non-matching number enum literal on a function that takes an enum literal', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple) {} +useFruit(Fruit.Banana); + `, +}); + +valid.push({ + name: 'Using a matching number enum value on a function that takes an enum literal', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple) {} +declare const fruit: Fruit.Apple; +useFruit(fruit); + `, +}); + +/** + * The TypeScript compiler will correctly handle this case, so the lint rule + * does not need to care. + */ +valid.push({ + name: 'Using a non-matching number enum value on a function that takes an enum literal', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple) {} +declare const fruit: Fruit.Banana; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal on a function that takes an enum literal', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple) {} +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal on a function that takes a number enum with a default argument', + code: + fruitEnumDefinition + + ` +function useFruit(fruit = Fruit.Apple) {} +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value on a function that takes a number enum with a default argument', + code: + fruitEnumDefinition + + ` +function useFruit(fruit = Fruit.Apple) {} +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal on a function that takes a number enum with a default argument', + code: + fruitEnumDefinition + + ` +function useFruit(fruit = Fruit.Apple) {} +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal on a function that takes a number enum literal with a default argument', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value on a function that takes a number enum literal with a default argument', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal on a function that takes a number enum literal with a default argument', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal on a function that takes a number enum | null', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit | null) {} +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value on a function that takes a number enum | null', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit | null) {} +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +valid.push({ + name: 'Using a null literal on a function that takes a number enum | null', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit | null) {} +useFruit(null); + `, +}); + +valid.push({ + name: 'Using a null value on a function that takes a number enum | null', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit | null) {} +const fruit = null; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal on a function that takes a number enum | null', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit | null) {} +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal on a function that takes a number enum | null with a default argument', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit | null = Fruit.Apple) {} +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value on a function that takes a number enum | null with a default argument', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit | null = Fruit.Apple) {} +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +valid.push({ + name: 'Using a null literal on a function that takes a number enum | null with a default argument', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit | null = Fruit.Apple) {} +useFruit(null); + `, +}); + +valid.push({ + name: 'Using a null value on a function that takes a number enum | null with a default argument', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit | null = Fruit.Apple) {} +const fruit = null; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal on a function that takes a number enum | null with a default argument', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit | null = Fruit.Apple) {} +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal on a function that takes a number enum literal | null', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | null) {} +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value on a function that takes a number enum literal | null', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | null) {} +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +valid.push({ + name: 'Using a null literal on a function that takes a number enum literal | null', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | null) {} +useFruit(null); + `, +}); + +valid.push({ + name: 'Using a null value on a function that takes a number enum literal | null', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | null) {} +const fruit = null; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal on a function that takes a number enum literal | null', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | null) {} +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal on a function that takes a number enum literal | null with a default argument', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value on a function that takes a number enum literal | null with a default argument', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +valid.push({ + name: 'Using a null literal on a function that takes a number enum literal | null with a default argument', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} +useFruit(null); + `, +}); + +valid.push({ + name: 'Using a null value on a function that takes a number enum literal | null with a default argument', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} +const fruit = null; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal on a function that takes a number enum literal | null with a default argument', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal on a function that takes a number enum literal | number enum literal | null', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum value on a function that takes a number enum literal | number enum literal | null', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} +const fruit = Fruit.Apple; +useFruit(fruit); + `, +}); + +valid.push({ + name: 'Using a null literal on a function that takes a number enum literal | number enum literal | null', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} +useFruit(null); + `, +}); + +valid.push({ + name: 'Using a null value on a function that takes a number enum literal | number enum literal | null', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} +const fruit = null; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number literal on a function that takes a number enum literal | number enum literal | null', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using an enum from a composition type on a function that takes a number enum', + code: + fruitEnumDefinition + + ` +interface BaseNode { + type: Fruit; +} + +interface AppleNode extends BaseNode { + type: Fruit.Apple; + apple: number; +} + +interface BananaNode extends BaseNode { + type: Fruit.Apple; + banana: Number; +} + +type Node = AppleNode | BananaNode; + +const fruitNodesSet = new Set([ + Fruit.Apple, + Fruit.Banana, +]); + +const appleNode: AppleNode = { + type: Fruit.Apple, + apple: 1, +}; + +fruitNodesSet.has(appleNode.type); + `, +}); + +valid.push({ + name: 'Using an enum number literal in a Set method', + code: + fruitEnumDefinition + + ` +const fruitSet = new Set([ + Fruit.Apple, + Fruit.Banana, +]); + +fruitSet.has(Fruit.Apple); + `, +}); + +invalid.push({ + name: 'Using a number literal in a Set method', + code: + fruitEnumDefinition + + ` +const fruitSet = new Set([ + Fruit.Apple, + Fruit.Banana, +]); + +fruitSet.has(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a partial union type on a function that takes a number enum', + code: + fruitFunctionDefinition + + ` +declare const fruitUnion: Fruit.Apple | Fruit.Banana; +useFruit(fruitUnion); +`, +}); + +valid.push({ + name: 'Using a partial union type on a function that takes a partial union', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | Fruit.Banana) {} +declare const fruitUnion: Fruit.Apple | Fruit.Banana; +useFruit(fruitUnion); +`, +}); + +invalid.push({ + name: 'Using a number literal on a function that takes a partial union', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | Fruit.Banana) {} +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a full enum union on a function that takes a number enum', + code: + fruitFunctionDefinition + + ` +declare const fruitUnion: Fruit.Apple | Fruit.Banana | Fruit.Pear; +useFruit(fruitUnion); +`, +}); + +valid.push({ + name: 'Using a full enum union on a function that takes a full enum union', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | Fruit.Banana | Fruit.Pear) {} +declare const fruitUnion: Fruit.Apple | Fruit.Banana | Fruit.Pear; +useFruit(fruitUnion); +`, +}); + +invalid.push({ + name: 'Using a number literal on a function that takes a full enum union', + code: + fruitEnumDefinition + + ` +function useFruit(fruit: Fruit.Apple | Fruit.Banana | Fruit.Pear) {} +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a partial enum union on a function that takes a number enum (from a type narrowing switch statement)', + code: + fruitFunctionDefinition + + ` +declare const fruit: Fruit; +switch (fruit) { + case Fruit.Apple: + case Fruit.Banana: { + useFruit(fruit); + } +} +`, +}); + +valid.push({ + name: 'Using a number enum on a function that takes an extension type', + code: + fruitEnumDefinition + + ` +function useFruit(fruitType: FruitType) {} +useFruit(Fruit.Apple); +`, +}); + +valid.push({ + name: 'Using a number literal on a function that takes an extension type', + code: + fruitEnumDefinition + + ` +function useFruit(fruitType: FruitType) {} +useFruit(0); +`, +}); + +valid.push({ + name: 'Using a number enum on a function that takes an enum extension type', + code: + fruitEnumDefinition + + ` +function useFruit(fruitType: FruitType) {} +useFruit(Fruit.Apple); +`, +}); + +invalid.push({ + name: 'Using a number literal on a function that takes an enum extension type', + code: + fruitEnumDefinition + + ` +function useFruit(fruitType: FruitType) {} +useFruit(0); +`, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum on a function that takes an enum extension type', + code: + fruitEnumDefinition + + ` +class FruitClass { + constructor(type: FruitType) {} + useFruit(type: FruitType) {} +} +const fruitClass = new FruitClass(Fruit.Apple); +fruitClass.useFruit(Fruit.Apple); +`, +}); + +invalid.push({ + name: 'Using a number literal on a function that takes an enum extension type', + code: + fruitEnumDefinition + + ` +class FruitClass { + constructor(type: FruitType) {} + useFruit(type: FruitType) {} +} +const fruitClass = new FruitClass(0); +fruitClass.useFruit(0); + `, + errors: [ + { messageId: 'mismatchedFunctionArgument' }, + { messageId: 'mismatchedFunctionArgument' }, + ], +}); + +valid.push({ + name: 'Using a number array on a function that takes a number array', + code: + fruitEnumDefinition + + ` +function useNumbers(numberArray: number[]) {} +useNumbers([0, 1]); + `, +}); + +valid.push({ + name: 'Using a number enum array on a function that takes a number enum array', + code: + fruitEnumDefinition + + ` +function useFruit(fruitArray: Fruit[]) {} +useFruit([Fruit.Apple, Fruit.Banana]); + `, +}); + +invalid.push({ + name: 'Using a number array on a function that takes a number enum array', + code: + fruitEnumDefinition + + ` +function useFruit(fruitArray: Fruit[]) {} +useFruit([0, 1]); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +invalid.push({ + name: 'Using a mixed array on a function that takes a number enum array', + code: + fruitEnumDefinition + + ` +function useFruit(fruitArray: Fruit[]) {} +useFruit([Fruit.Apple, 1]); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number literal on a function that takes a number', + code: ` +function useNumber(num: number) {} +useNumber(0); + `, +}); + +valid.push({ + name: 'Using a number enum literal on a function that takes a number', + code: + fruitEnumDefinition + + ` +function useNumber(num: number) {} +useNumber(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a string literal on a function that takes a string', + code: + vegetableEnumDefinition + + ` +function useString(str: string) {} +useString('lettuce'); + `, +}); + +valid.push({ + name: 'Using a string enum literal on a function that takes a string', + code: + vegetableEnumDefinition + + ` +function useString(str: string) {} +useString(Vegetable.Lettuce); + `, +}); + +valid.push({ + name: 'Using a number literal on a function that takes any', + code: ` +function useAnything(something: any) {} +useAnything(0); + `, +}); + +valid.push({ + name: 'Using a number enum literal on a function that takes any', + code: + fruitEnumDefinition + + ` +function useAnything(something: any) {} +useAnything(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number literal on a function that takes unknown', + code: ` +function useUnknown(something: unknown) {} +useUnknown(0); + `, +}); + +valid.push({ + name: 'Using a number enum literal on a function that takes unknown', + code: + fruitEnumDefinition + + ` +function useUnknown(something: unknown) {} +useUnknown(Fruit.Apple); + `, +}); + +invalid.push({ + name: 'Using a number literal on a function that takes enum | enum array', + code: + fruitEnumDefinition + + ` +function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal on a function that takes enum | enum array', + code: + fruitEnumDefinition + + ` +function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} +useFruit(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum array on a function that takes enum | enum array', + code: + fruitEnumDefinition + + ` +function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} +useFruit([Fruit.Apple, Fruit.Banana]); + `, +}); + +valid.push({ + name: 'Using a enum | enum array union on a function that takes enum | enum array', + code: + fruitEnumDefinition + + ` +function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} +declare const fruit: Fruit | Fruit[]; +useFruit(fruit); + `, +}); + +invalid.push({ + name: 'Using a number array on a function that takes enum | enum array', + code: + fruitEnumDefinition + + ` +function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} +useFruit([0, 1]); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number on a function that takes number | enum array', + code: + fruitEnumDefinition + + ` +function useFruit(fruitOrFruitArray: number | Fruit[]) {} +useFruit(0); + `, +}); + +valid.push({ + name: 'Using an enum array on a function that takes number | enum array', + code: + fruitEnumDefinition + + ` +function useFruit(fruitOrFruitArray: number | Fruit[]) {} +useFruit([Fruit.Apple, Fruit.Banana]); + `, +}); + +invalid.push({ + name: 'Using a number array on a function that takes number | enum array', + code: + fruitEnumDefinition + + ` +function useFruit(fruitOrFruitArray: number | Fruit[]) {} +useFruit([0, 1]); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +invalid.push({ + name: 'Using a number literal on a variadic function', + code: + fruitEnumDefinition + + ` +function useFruit(...fruits: Fruit[]) {} +useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal on a variadic function', + code: + fruitEnumDefinition + + ` +function useFruit(...fruits: Fruit[]) {} +useFruit(Fruit.Apple); +useFruit(Fruit.Apple, Fruit.Banana); + `, +}); + +invalid.push({ + name: 'Using a number enum literal and a number literal on a variadic function', + code: + fruitEnumDefinition + + ` +function useFruit(...fruits: Fruit[]) {} +useFruit(Fruit.Apple, 0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal on a generic function with a default generic type that is unspecified as any', + code: + fruitEnumDefinition + + ` +function toEqual(expected: E): void {} +toEqual(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum literal on a generic function with a default generic type that is unspecified as a number enum', + code: + fruitEnumDefinition + + ` +function toEqual(expected: E): void {} +toEqual(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum literal on a generic function with a default generic type that is specified as any', + code: + fruitEnumDefinition + + ` +function toEqual(expected: E): void {} +toEqual(Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum literal on a generic function with a default generic type that is specified as a number enum', + code: + fruitEnumDefinition + + ` +function toEqual(expected: E): void {} +toEqual(Fruit.Apple); + `, +}); + +invalid.push({ + name: 'Using a number literal on a generic function with a default generic type that is specified as a number enum', + code: + fruitEnumDefinition + + ` +function toEqual(expected: E): void {} +toEqual(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using a number enum literal on a generic function with a default generic type that is unspecified as any + extra arg', + code: + fruitEnumDefinition + + ` +function toEqual(arg1: number, expected: E): void {} +toEqual(0, Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum literal on a generic function with a default generic type that is unspecified as a number enum + extra arg', + code: + fruitEnumDefinition + + ` +function toEqual(arg1: number, expected: E): void {} +toEqual(0, Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum literal on a generic function with a default generic type that is specified as any + extra arg', + code: + fruitEnumDefinition + + ` +function toEqual(arg1: number, expected: E): void {} +toEqual(0, Fruit.Apple); + `, +}); + +valid.push({ + name: 'Using a number enum literal on a generic function with a default generic type that is specified as a number enum + extra arg', + code: + fruitEnumDefinition + + ` +function toEqual(arg1: number, expected: E): void {} +toEqual(0, Fruit.Apple); + `, +}); + +invalid.push({ + name: 'Using a number literal on a generic function with a default generic type that is specified as a number enum + extra arg', + code: + fruitEnumDefinition + + ` +function toEqual(arg1: number, expected: E): void {} +toEqual(0, 0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], +}); + +valid.push({ + name: 'Using JSON.stringify', + code: ` +JSON.stringify( + {}, + (_, value: unknown) => value ?? undefined, + 2, +); + `, +}); + +valid.push({ + name: 'Using flatten', + code: ` +function flatten(arr: T[][]): T[] { + return arr.reduce((acc, a) => acc.concat(a), []); +} + `, +}); + +strictEnumsRuleTester.run('strict-enums-functions', rule, { + valid, + invalid, +}); diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-incrementing.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-incrementing.test.ts new file mode 100644 index 000000000000..9ffcc1eb6b46 --- /dev/null +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-incrementing.test.ts @@ -0,0 +1,140 @@ +import { + InvalidTestCase, + ValidTestCase, +} from '@typescript-eslint/utils/src/ts-eslint'; +import rule, { MessageIds } from '../../../src/rules/strict-enums'; +import { fruitEnumDefinition, strictEnumsRuleTester } from './strict-enums'; + +const valid: ValidTestCase[] = []; +const invalid: InvalidTestCase[] = []; + +valid.push({ + name: 'Incrementing a number (postfix)', + code: + fruitEnumDefinition + + ` +let fruit = 0; +fruit++; + `, +}); + +invalid.push({ + name: 'Incrementing a number enum value (postfix)', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Apple; +fruit++; + `, + errors: [{ messageId: 'incorrectIncrement' }], +}); + +valid.push({ + name: 'Decrementing a number (postfix)', + code: + fruitEnumDefinition + + ` +let fruit = 1; +fruit--; + `, +}); + +invalid.push({ + name: 'Decrementing a number enum value (postfix)', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Banana; +fruit--; + `, + errors: [{ messageId: 'incorrectIncrement' }], +}); + +valid.push({ + name: 'Incrementing a number (prefix)', + code: + fruitEnumDefinition + + ` +let fruit = 0; +++fruit; + `, +}); + +invalid.push({ + name: 'Incrementing a number enum value (prefix)', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Apple; +++fruit; + `, + errors: [{ messageId: 'incorrectIncrement' }], +}); + +valid.push({ + name: 'Decrementing a number (prefix)', + code: + fruitEnumDefinition + + ` +let fruit = 1; +--fruit + `, +}); + +invalid.push({ + name: 'Decrementing a number enum value (prefix)', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Banana; +--fruit; + `, + errors: [{ messageId: 'incorrectIncrement' }], +}); + +valid.push({ + name: 'Incrementing a number (assignment operator)', + code: + fruitEnumDefinition + + ` +let fruit = 0; +fruit += 1; + `, +}); + +invalid.push({ + name: 'Incrementing a number enum value (assignment operator)', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Apple; +fruit += 1; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +valid.push({ + name: 'Decrementing a number (assignment operator)', + code: + fruitEnumDefinition + + ` +let fruit = 1; +fruit -= 1; + `, +}); + +invalid.push({ + name: 'Decrementing a number enum value (assignment operator)', + code: + fruitEnumDefinition + + ` +let fruit = Fruit.Banana; +fruit -= 1; + `, + errors: [{ messageId: 'mismatchedAssignment' }], +}); + +strictEnumsRuleTester.run('strict-enums-incrementing', rule, { + valid, + invalid, +}); diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums.ts new file mode 100644 index 000000000000..fa651196ab37 --- /dev/null +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums.ts @@ -0,0 +1,53 @@ +import { getFixturesRootDir, RuleTester } from '../../RuleTester'; + +const rootDir = getFixturesRootDir(); +export const strictEnumsRuleTester = new RuleTester({ + parserOptions: { + ecmaVersion: 2015, + tsconfigRootDir: rootDir, + project: './tsconfig.json', + }, + parser: '@typescript-eslint/parser', +}); + +/** A number enum. */ +export const fruitEnumDefinition = ` +enum Fruit { + Apple, + Banana, + Pear, +} +`; + +/** A different number enum. */ +export const fruit2EnumDefinition = ` +enum Fruit2 { + Apple2, + Banana2, + Pear2, +} +`; + +/** + * A string enum. + * + * String enums are almost exclusively used for comparison tests, since the + * TypeScript compiler does a good job of ensuring safety for string enum + * variable assignment and usage in functions. + */ +export const vegetableEnumDefinition = ` + enum Vegetable { + Lettuce = 'lettuce', + Carrot = 'carrot', + Celery = 'celery', + } + `; + +/** A different string enum. */ +export const vegetable2EnumDefinition = ` +enum Vegetable2 { + Lettuce2 = 'lettuce2', + Carrot2 = 'carrot2', + Celery2 = 'celery2', +} +`; From a23608547afc0334e3fcaefd8278e195378b6d02 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Thu, 5 May 2022 22:23:19 -0400 Subject: [PATCH 54/88] Update packages/eslint-plugin/src/rules/strict-enums.ts Co-authored-by: Brad Zacher --- packages/eslint-plugin/src/rules/strict-enums.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 9c38191dc450..94f3b211346b 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -37,13 +37,7 @@ export default util.createRule({ mismatchedFunctionArgument: 'The {{ ordinal }} argument in the function call does not match the declared enum type of the function signature.', }, - schema: [ - { - type: 'object', - properties: {}, - additionalProperties: false, - }, - ], + schema: [], }, defaultOptions: [], create(context) { From c3574323c237379a0d116bc066f4330abbec3688 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Thu, 5 May 2022 22:23:44 -0400 Subject: [PATCH 55/88] Update packages/eslint-plugin/src/rules/strict-enums.ts Co-authored-by: Brad Zacher --- packages/eslint-plugin/src/rules/strict-enums.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 94f3b211346b..18d408b0cdc8 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -294,7 +294,7 @@ export default util.createRule({ */ if (isMismatchedEnumFunctionArgument(argumentType, parameterType)) { context.report({ - node, + node: node.arguments[i], messageId: 'mismatchedFunctionArgument', data: { ordinal: getOrdinalSuffix(i + 1), // e.g. 0 --> 1st From 23959989cc6fd0b3cf8ddbbe4d3dedcc2251fd26 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Thu, 5 May 2022 22:27:31 -0400 Subject: [PATCH 56/88] fix: adding failing test --- .../rules/strict-enums/strict-enums-comparison.test.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts index 30e9df175ef4..589d9a116dbf 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts @@ -336,6 +336,16 @@ if (vegetable in foo) {} `, }); +valid.push({ + name: 'Comparing using a type of enum | boolean', + code: + fruitEnumDefinition + + ` +declare const fruitOrBool: Fruit | boolean; +if (fruitOrBool === true) {} + `, +}); + strictEnumsRuleTester.run('strict-enums-comparison', rule, { valid, invalid, From 2851c3bff1248a4c1afdbffdfb9e366565146719 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Fri, 6 May 2022 11:59:56 -0400 Subject: [PATCH 57/88] fix: making boolean tests pass --- .../eslint-plugin/src/rules/strict-enums.ts | 66 +++++++++++-------- .../strict-enums-assignment.test.ts | 7 +- .../strict-enums-comparison.test.ts | 4 +- 3 files changed, 43 insertions(+), 34 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 18d408b0cdc8..5fdc925deaa8 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -157,28 +157,28 @@ export default util.createRule({ return util.getTypeName(typeChecker, type); } + function hasBooleanAndNotEnum(type: ts.Type): boolean { + return hasTypeAndNotEnum(type, ts.TypeFlags.BooleanLike); + } + function hasEnumTypes(type: ts.Type): boolean { const enumTypes = getEnumTypes(type); return enumTypes.size > 0; } - function hasNumber(type: ts.Type): boolean { - return hasType(type, ts.TypeFlags.NumberLike); + function hasNumberAndNotEnum(type: ts.Type): boolean { + return hasTypeAndNotEnum(type, ts.TypeFlags.NumberLike); } - function hasString(type: ts.Type): boolean { - return hasType(type, ts.TypeFlags.StringLike); + function hasStringAndNotEnum(type: ts.Type): boolean { + return hasTypeAndNotEnum(type, ts.TypeFlags.StringLike); } - /** - * This will return false for any enum-like type, since it would - * subsequently not be a "pure" type anymore. - */ - function hasType(type: ts.Type, typeFlag: ts.TypeFlags): boolean { + function hasTypeAndNotEnum(type: ts.Type, typeFlag: ts.TypeFlags): boolean { if (type.isUnion()) { const unionSubTypes = tsutils.unionTypeParts(type); for (const subType of unionSubTypes) { - if (hasType(subType, typeFlag)) { + if (hasTypeAndNotEnum(subType, typeFlag)) { return true; } } @@ -187,7 +187,7 @@ export default util.createRule({ if (type.isIntersection()) { const intersectionSubTypes = tsutils.intersectionTypeParts(type); for (const subType of intersectionSubTypes) { - if (hasType(subType, typeFlag)) { + if (hasTypeAndNotEnum(subType, typeFlag)) { return true; } } @@ -375,39 +375,53 @@ export default util.createRule({ leftType: ts.Type, rightType: ts.Type, ): boolean { + /** Allow any comparisons with whitelisted operators. */ + if (ALLOWED_ENUM_OPERATORS.has(operator)) { + return false; + } + /** - * Allow any comparisons with the some whitelisted operators. + * Allow exact comparisons to some standard types, like null and + * undefined. + * + * The TypeScript compiler should properly type-check these cases, so the + * lint rule is unneeded. */ - if (ALLOWED_ENUM_OPERATORS.has(operator)) { + if (isNullOrUndefinedOrAnyOrUnknownOrNever(leftType, rightType)) { return false; } + /** Allow comparison that don't have anything to do with enums. */ const leftEnumTypes = getEnumTypes(leftType); const rightEnumTypes = getEnumTypes(rightType); - if (leftEnumTypes.size === 0 && rightEnumTypes.size === 0) { - // This is not an enum comparison return false; } /** - * As a special exception, allow comparisons to null or undefined or any. + * Allow comparisons that contain a union with a boolean, number, or + * string, like the following: * - * The TypeScript compiler should handle these cases properly, so the - * lint rule is unneeded. + * ```ts + * declare const fruitOrBoolean: Fruit | boolean; + * if (fruitOrBoolean === true) {} + * ``` + * + * The TypeScript API is limited in that there is no "type relationship" + * functionality. So there is no way to ask: + * + * "Is true assignable to one of the non-enum types? If yes, ignore it, + * else report." + * + * Thus, we bail out and ignore this case. */ - if (isNullOrUndefinedOrAnyOrUnknownOrNever(leftType, rightType)) { + if (hasBooleanAndNotEnum(leftType) && hasBooleanAndNotEnum(rightType)) { return false; } - - /** - * Allow comparing numbers to numbers and strings to strings in - * complicated union/intersection types. - */ - if (hasNumber(leftType) && hasNumber(rightType)) { + if (hasNumberAndNotEnum(leftType) && hasNumberAndNotEnum(rightType)) { return false; } - if (hasString(leftType) && hasString(rightType)) { + if (hasStringAndNotEnum(leftType) && hasStringAndNotEnum(rightType)) { return false; } diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts index e20ffe1fb721..9977ab5f9883 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts @@ -207,12 +207,7 @@ const z: Foo.A | Foo.B | Foo.C | Foo.D = foo; `, }); -/** - * Intersection enum types are not checked by this rule. Even though doing this - * would almost certainly be a bad idea, a programmer would have to go to great - * lengths to do this, so we assume that the programmer knows what they are - * doing and allow it. - */ +// Intersection types are always allowed; see the docs valid.push({ name: 'Assigning a variable with a intersection enum type', code: diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts index 589d9a116dbf..945dfe0c6d17 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts @@ -341,8 +341,8 @@ valid.push({ code: fruitEnumDefinition + ` -declare const fruitOrBool: Fruit | boolean; -if (fruitOrBool === true) {} +declare const fruitOrBoolean: Fruit | boolean; +if (fruitOrBoolean === true) {} `, }); From cf7c9b71d11884a5f8863ec442a88a40288f532d Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Fri, 6 May 2022 12:17:23 -0400 Subject: [PATCH 58/88] fix: refactor tests + fix linter --- .../strict-enums-comparison.test.ts | 77 +++++++------------ .../ast/serializer/serializerScope.ts | 1 - 2 files changed, 27 insertions(+), 51 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts index 945dfe0c6d17..5818f07d1a44 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts @@ -23,8 +23,7 @@ valid.push({ code: fruitEnumDefinition + ` -if (1 === 2) { -} +1 === 2; `, }); @@ -34,8 +33,7 @@ valid.push({ fruitEnumDefinition + ` declare thing: any; -if (Fruit.Apple === thing) { -} +Fruit.Apple === thing; `, }); @@ -44,8 +42,7 @@ valid.push({ code: fruitEnumDefinition + ` -if (Fruit.Apple === undefined) { -} +Fruit.Apple === undefined; `, }); @@ -54,8 +51,7 @@ valid.push({ code: fruitEnumDefinition + ` -if (Fruit.Apple === null) { -} +Fruit.Apple === null; `, }); @@ -64,8 +60,7 @@ valid.push({ code: fruitEnumDefinition + ` -if (Fruit.Apple === Fruit.Banana) { -} +Fruit.Apple === Fruit.Banana; `, }); @@ -75,8 +70,7 @@ valid.push({ fruitEnumDefinition + ` const fruit = Fruit.Apple; -if (fruit === Fruit.Banana) { -} +fruit === Fruit.Banana; `, }); @@ -86,8 +80,7 @@ valid.push({ vegetableEnumDefinition + ` const vegetable = Vegetable.Lettuce; -if (vegetable === Vegetable.Carrot) { -} +vegetable === Vegetable.Carrot; `, }); @@ -98,8 +91,7 @@ valid.push({ ` const fruit1 = Fruit.Apple; const fruit2 = Fruit.Banana; -if (fruit1 === fruit2) { -} +fruit1 === fruit2; `, }); @@ -110,8 +102,7 @@ valid.push({ ` const vegetable1 = Vegetable.Lettuce; const vegetable2 = Vegetable.Carrot; -if (vegetable1 === vegetable2) { -} +vegetable1 === vegetable2; `, }); @@ -120,8 +111,7 @@ invalid.push({ code: fruitEnumDefinition + ` -if (Fruit.Apple === 1) { -} +Fruit.Apple === 1; `, errors: [{ messageId: 'mismatchedComparison' }], }); @@ -131,8 +121,7 @@ invalid.push({ code: vegetableEnumDefinition + ` -if (Vegetable.Lettuce === 'carrot') { -} +Vegetable.Lettuce === 'carrot'; `, errors: [{ messageId: 'mismatchedComparison' }], }); @@ -142,8 +131,7 @@ invalid.push({ code: fruitEnumDefinition + ` -if (1 === Fruit.Apple) { -} +1 === Fruit.Apple; `, errors: [{ messageId: 'mismatchedComparison' }], }); @@ -153,8 +141,7 @@ invalid.push({ code: vegetableEnumDefinition + ` -if ('carrot' === Vegetable.Lettuce) { -} +'carrot' === Vegetable.Lettuce; `, errors: [{ messageId: 'mismatchedComparison' }], }); @@ -165,8 +152,7 @@ invalid.push({ fruitEnumDefinition + ` const fruit = Fruit.Apple; -if (fruit === 1) { -} +fruit === 1; `, errors: [{ messageId: 'mismatchedComparison' }], }); @@ -177,8 +163,7 @@ invalid.push({ vegetableEnumDefinition + ` const vegetable = Vegetable.Lettuce; -if (vegetable === 'carrot') { -} +vegetable === 'carrot'; `, errors: [{ messageId: 'mismatchedComparison' }], }); @@ -189,8 +174,7 @@ invalid.push({ fruitEnumDefinition + ` const fruit = Fruit.Apple; -if (1 === fruit) { -} +1 === fruit; `, errors: [{ messageId: 'mismatchedComparison' }], }); @@ -201,8 +185,7 @@ invalid.push({ vegetableEnumDefinition + ` const vegetable = Vegetable.Lettuce; -if ('carrot' === vegetable) { -} +'carrot' === vegetable; `, errors: [{ messageId: 'mismatchedComparison' }], }); @@ -213,8 +196,7 @@ invalid.push({ fruitEnumDefinition + fruit2EnumDefinition + ` -if (Fruit.Apple === Fruit2.Apple2) { -} +Fruit.Apple === Fruit2.Apple2; `, errors: [{ messageId: 'mismatchedComparison' }], }); @@ -225,8 +207,7 @@ invalid.push({ vegetableEnumDefinition + vegetable2EnumDefinition + ` -if (Vegetable.Lettuce === Vegetable2.Lettuce2) { -} +Vegetable.Lettuce === Vegetable2.Lettuce2; `, errors: [{ messageId: 'mismatchedComparison' }], }); @@ -238,8 +219,7 @@ invalid.push({ fruit2EnumDefinition + ` const fruit = Fruit.Apple; -if (fruit === Fruit2.Apple2) { -} +fruit === Fruit2.Apple2; `, errors: [{ messageId: 'mismatchedComparison' }], }); @@ -251,8 +231,7 @@ invalid.push({ vegetable2EnumDefinition + ` const vegetable = Vegetable.Lettuce; -if (vegetable === Vegetable2.Lettuce2) { -} +vegetable === Vegetable2.Lettuce2; `, errors: [{ messageId: 'mismatchedComparison' }], }); @@ -278,7 +257,7 @@ valid.push({ ` declare const left: number | Fruit; declare const right: number | Fruit2; -if (left === right) {} +left === right; `, }); @@ -290,7 +269,7 @@ valid.push({ ` declare const left: string | Vegetable; declare const right: string | Vegetable2; -if (left === right) {} +left === right; `, }); @@ -301,8 +280,7 @@ valid.push({ ` type WeirdString = string & { __someBrand: void; }; declare weirdString: WeirdString; -if (Vegetable.Lettuce === weirdString) { -} +Vegetable.Lettuce === weirdString; `, }); @@ -320,8 +298,7 @@ type __String = | (void & { __escapedIdentifier: void; }) | InternalSymbolName; declare const weirdString: __String; -if (weirdString === 'someArbitraryValue') { -} +weirdString === 'someArbitraryValue'; `, }); @@ -332,7 +309,7 @@ valid.push({ ` const foo = {}; const vegetable = Vegetable.Lettuce; -if (vegetable in foo) {} +vegetable in foo; `, }); @@ -342,7 +319,7 @@ valid.push({ fruitEnumDefinition + ` declare const fruitOrBoolean: Fruit | boolean; -if (fruitOrBoolean === true) {} +fruitOrBoolean === true; `, }); diff --git a/packages/website/src/components/ast/serializer/serializerScope.ts b/packages/website/src/components/ast/serializer/serializerScope.ts index 9a2bdac3e5f4..176f49f92c5c 100644 --- a/packages/website/src/components/ast/serializer/serializerScope.ts +++ b/packages/website/src/components/ast/serializer/serializerScope.ts @@ -194,7 +194,6 @@ export function createScopeSerializer(): Serializer { start: { ...data.loc.start }, end: { ...data.loc.end }, }, - // eslint-disable-next-line @typescript-eslint/strict-enums value: data.type === 'Identifier' ? `<"${data.name}">` : '', }; } From 3b2fa5747e19b6faac3911ade6f813f9befa50ed Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Fri, 6 May 2022 12:29:01 -0400 Subject: [PATCH 59/88] fix: adding brads tests --- .../strict-enums-comparison.test.ts | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts index 5818f07d1a44..62f10a00a36c 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts @@ -323,6 +323,70 @@ fruitOrBoolean === true; `, }); +valid.push({ + name: "Comparing various valid types (Brad's test)", + code: ` +enum Str { A = 'a' } +enum Num { B = 1 } +enum Mixed { A = 'a', B = 1 } + +declare const str: Str; +declare const strOrString: Str | string; + +declare const num: Num; +declare const numOrNumber: Num | number; + +declare const mixed: Mixed; +declare const mixedOrStringOrNumber: Mixed | string | number; + +function someFunction() {} + +// following are all ignored due to the presence of "| string" or "| number" +strOrString === 'a'; +numOrNumber === 1; +mixedOrStringOrNumber === 'a'; +mixedOrStringOrNumber === 1; + +// following are all ignored because the value can never be an enum value +str === 1; +num === 'a'; +str === {}; +num === {}; +mixed === {}; +str === true; +num === true; +mixed === true; +str === someFunction; +num === someFunction; +mixed === someFunction; + `, +}); + +invalid.push({ + name: "Comparing various invalid types (Brad's test)", + code: ` +enum Str { A = 'a' } +enum Num { B = 1 } +enum Mixed { A = 'a', B = 1 } + +declare const str: Str; +declare const num: Num; +declare const mixed: Mixed; + +// following are all errors because the value might be an enum value +str === 'a'; +num === 1; +mixed === 'a'; +mixed === 1; + `, + errors: [ + { messageId: 'mismatchedComparison' }, + { messageId: 'mismatchedComparison' }, + { messageId: 'mismatchedComparison' }, + { messageId: 'mismatchedComparison' }, + ], +}); + strictEnumsRuleTester.run('strict-enums-comparison', rule, { valid, invalid, From 6c43f715cb112a449150820e0397acfa6699fff2 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Fri, 6 May 2022 16:24:41 -0400 Subject: [PATCH 60/88] fix: brads tests now pass --- .../eslint-plugin/src/rules/strict-enums.ts | 226 ++++++++++++++---- .../strict-enums-comparison.test.ts | 2 + 2 files changed, 175 insertions(+), 53 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 5fdc925deaa8..90efad39ea00 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -3,9 +3,33 @@ import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import { TSESTree } from '@typescript-eslint/utils'; +/** + * TypeScript only allows number enums, string enums, or mixed enums with both + * numbers and strings. + * + * Mixed enums are be a union of a number enum and a string enum, so there is + * no separate kind for them. + */ +enum EnumKind { + NON_ENUM, + HAS_NUMBER_VALUES, + HAS_STRING_VALUES, +} + /** These operators are always considered to be safe. */ const ALLOWED_ENUM_OPERATORS = new Set(['in', '|', '&', '|=', '&=']); +/** + * See the comment for `EnumKind`. + * + * This rule can safely ignore other kinds of types (and leave the validation in + * question to the TypeScript compiler). + */ +const IMPOSSIBLE_ENUM_TYPES = + ts.TypeFlags.BooleanLike | + ts.TypeFlags.NonPrimitive | + ts.TypeFlags.ESSymbolLike; + const ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT = ts.TypeFlags.Any | ts.TypeFlags.Unknown | @@ -79,6 +103,69 @@ export default util.createRule({ return parentType; } + /** + * See the comment for the `EnumKind` enum. + */ + function getEnumKind(type: ts.Type): EnumKind { + if (type.isUnion()) { + throw new Error( + 'The "getEnumKind" function is not meant to be used on unions. Use the "getEnumKinds" function instead.', + ); + } + + if (type.isIntersection()) { + throw new Error( + 'The "getEnumKind" function is not meant to be used on intersections.', + ); + } + + if (!isEnum(type)) { + return EnumKind.NON_ENUM; + } + + const isStringLiteral = util.isTypeFlagSet( + type, + ts.TypeFlags.StringLiteral, + ); + const isNumberLiteral = util.isTypeFlagSet( + type, + ts.TypeFlags.NumberLiteral, + ); + + if (isStringLiteral && !isNumberLiteral) { + return EnumKind.HAS_STRING_VALUES; + } + + if (isNumberLiteral && !isStringLiteral) { + return EnumKind.HAS_NUMBER_VALUES; + } + + throw new Error( + 'Failed to derive the type of enum, since it did not have string values or number values.', + ); + } + + /** + * Returns a set containing the single `EnumKind` (if it is not a union), or + * a set containing N `EnumKind` (if it is a union). + */ + function getEnumKinds(type: ts.Type): Set { + if (type.isUnion()) { + const subTypes = tsutils.unionTypeParts(type); + const enumKinds = subTypes.map(subType => getEnumKind(subType)); + return new Set(enumKinds); + } + + if (type.isIntersection()) { + throw new Error( + 'The getEnumKinds function is not meant to be used on intersections.', + ); + } + + const enumKind = getEnumKind(type); + return new Set([enumKind]); + } + /** * A thing can have 0 or more enum types. For example: * - 123 --> [] @@ -157,49 +244,33 @@ export default util.createRule({ return util.getTypeName(typeChecker, type); } - function hasBooleanAndNotEnum(type: ts.Type): boolean { - return hasTypeAndNotEnum(type, ts.TypeFlags.BooleanLike); - } - function hasEnumTypes(type: ts.Type): boolean { const enumTypes = getEnumTypes(type); return enumTypes.size > 0; } - function hasNumberAndNotEnum(type: ts.Type): boolean { - return hasTypeAndNotEnum(type, ts.TypeFlags.NumberLike); - } - - function hasStringAndNotEnum(type: ts.Type): boolean { - return hasTypeAndNotEnum(type, ts.TypeFlags.StringLike); - } - - function hasTypeAndNotEnum(type: ts.Type, typeFlag: ts.TypeFlags): boolean { - if (type.isUnion()) { - const unionSubTypes = tsutils.unionTypeParts(type); - for (const subType of unionSubTypes) { - if (hasTypeAndNotEnum(subType, typeFlag)) { - return true; - } - } + function hasIntersection(type: ts.Type): boolean { + if (type.isIntersection()) { + return true; } - if (type.isIntersection()) { - const intersectionSubTypes = tsutils.intersectionTypeParts(type); - for (const subType of intersectionSubTypes) { - if (hasTypeAndNotEnum(subType, typeFlag)) { + if (type.isUnion()) { + const subTypes = tsutils.unionTypeParts(type); + for (const subType of subTypes) { + if (subType.isIntersection()) { return true; } } } - return ( - util.isTypeFlagSet(type, typeFlag) && - !util.isTypeFlagSet(type, ts.TypeFlags.EnumLike) - ); + return false; } function isEnum(type: ts.Type): boolean { + /** + * The "EnumLiteral" flag will be set on both enum base types and enum + * members/values. + */ return util.isTypeFlagSet(type, ts.TypeFlags.EnumLiteral); } @@ -218,6 +289,22 @@ export default util.createRule({ ); } + function isNumber(type: ts.Type): boolean { + /** + * The "NumberLike" flag will be set on both number literals and number + * variables. + */ + return util.isTypeFlagSet(type, ts.TypeFlags.NumberLike); + } + + function isString(type: ts.Type): boolean { + /** + * The "StrikeLike" flag will be set on both string literals and string + * variables. + */ + return util.isTypeFlagSet(type, ts.TypeFlags.StringLike); + } + function setHasAnyElementFromSet(set1: Set, set2: Set): boolean { for (const value of set2.values()) { if (set1.has(value)) { @@ -375,11 +462,40 @@ export default util.createRule({ leftType: ts.Type, rightType: ts.Type, ): boolean { - /** Allow any comparisons with whitelisted operators. */ + /** Allow comparisons with whitelisted operators. */ if (ALLOWED_ENUM_OPERATORS.has(operator)) { return false; } + /** Allow comparisons that don't have anything to do with enums. */ + const leftEnumTypes = getEnumTypes(leftType); + const rightEnumTypes = getEnumTypes(rightType); + if (leftEnumTypes.size === 0 && rightEnumTypes.size === 0) { + return false; + } + + /** + * Allow comparisons to any intersection. Enum intersections would be rare + * in real-life code, so they are out of scope for this rule. + */ + if (hasIntersection(leftType) || hasIntersection(rightType)) { + return false; + } + + /** + * Allow comparisons to things with a type that can never be an enum (like + * a function). + * + * (The TypeScript compiler should properly type-check these cases, so the + * lint rule is unneeded.) + */ + if ( + util.isTypeFlagSet(leftType, IMPOSSIBLE_ENUM_TYPES) || + util.isTypeFlagSet(rightType, IMPOSSIBLE_ENUM_TYPES) + ) { + return false; + } + /** * Allow exact comparisons to some standard types, like null and * undefined. @@ -391,37 +507,41 @@ export default util.createRule({ return false; } - /** Allow comparison that don't have anything to do with enums. */ - const leftEnumTypes = getEnumTypes(leftType); - const rightEnumTypes = getEnumTypes(rightType); - if (leftEnumTypes.size === 0 && rightEnumTypes.size === 0) { - return false; - } - /** - * Allow comparisons that contain a union with a boolean, number, or - * string, like the following: - * - * ```ts - * declare const fruitOrBoolean: Fruit | boolean; - * if (fruitOrBoolean === true) {} - * ``` + * Allow number enums to be compared with strings and string enums to be + * compared with numbers. * - * The TypeScript API is limited in that there is no "type relationship" - * functionality. So there is no way to ask: - * - * "Is true assignable to one of the non-enum types? If yes, ignore it, - * else report." - * - * Thus, we bail out and ignore this case. + * (The TypeScript compiler should properly type-check these cases, so the + * lint rule is unneeded.) */ - if (hasBooleanAndNotEnum(leftType) && hasBooleanAndNotEnum(rightType)) { + const leftEnumKinds = getEnumKinds(leftType); + const rightEnumKinds = getEnumKinds(rightType); + if ( + leftEnumKinds.has(EnumKind.HAS_STRING_VALUES) && + leftEnumKinds.size === 1 && + isNumber(rightType) + ) { + return false; + } + if ( + leftEnumKinds.has(EnumKind.HAS_NUMBER_VALUES) && + leftEnumKinds.size === 1 && + isString(rightType) + ) { return false; } - if (hasNumberAndNotEnum(leftType) && hasNumberAndNotEnum(rightType)) { + if ( + rightEnumKinds.has(EnumKind.HAS_STRING_VALUES) && + rightEnumKinds.size === 1 && + isNumber(leftType) + ) { return false; } - if (hasStringAndNotEnum(leftType) && hasStringAndNotEnum(rightType)) { + if ( + rightEnumKinds.has(EnumKind.HAS_NUMBER_VALUES) && + rightEnumKinds.size === 1 && + isString(leftType) + ) { return false; } diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts index 62f10a00a36c..0a52ea326f1a 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts @@ -349,6 +349,7 @@ mixedOrStringOrNumber === 1; // following are all ignored because the value can never be an enum value str === 1; +/* num === 'a'; str === {}; num === {}; @@ -359,6 +360,7 @@ mixed === true; str === someFunction; num === someFunction; mixed === someFunction; +*/ `, }); From af7d5da50d4c8e8d730eb14db9bdda54953566f3 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Sat, 7 May 2022 13:00:29 -0400 Subject: [PATCH 61/88] Update packages/eslint-plugin/docs/rules/strict-enums.md Co-authored-by: Joshua Chen --- packages/eslint-plugin/docs/rules/strict-enums.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/docs/rules/strict-enums.md b/packages/eslint-plugin/docs/rules/strict-enums.md index 796686fb1717..501adff8e691 100644 --- a/packages/eslint-plugin/docs/rules/strict-enums.md +++ b/packages/eslint-plugin/docs/rules/strict-enums.md @@ -108,7 +108,7 @@ enum Vegetable { } let vegetable = Vegetable.Lettuce; -vegetable = 'definatelyNotAVegetable'; // Type '"definatelyNotAVegetable"' is not assignable to type 'Vegetable'. +vegetable = 'definitelyNotAVegetable'; // Type '"definitelyNotAVegetable"' is not assignable to type 'Vegetable'. // Even "valid" strings will not work, which is good! vegetable = 'carrot'; // Type '"carrot"' is not assignable to type 'Vegetable'. From 85563be9066757b9b30b835aaeb1a2753bc0d4b5 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Mon, 30 May 2022 03:41:22 -0400 Subject: [PATCH 62/88] Update packages/eslint-plugin/src/rules/strict-enums.ts Co-authored-by: Brad Zacher --- packages/eslint-plugin/src/rules/strict-enums.ts | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 90efad39ea00..3ff4c0a1b06e 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -724,17 +724,10 @@ export default util.createRule({ } }, - /** When a function is invoked. */ - CallExpression(node): void { - checkCallExpression(node); - }, - - /** When something is instantiated with the "new" keyword. */ - NewExpression(node): void { - /** - * We need to perform the exact same checks on a class constructor - * invocation as we do on a normal function invocation. - */ + /** When a function is invoked, or class is instantiated. */ + 'CallExpression, NewExpression'( + node: TSESTree.CallExpression | TSESTree.NewExpression, + ): void { checkCallExpression(node); }, From ee96ce55e6cc9a7998c31009de0cd44f99f36b12 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Mon, 30 May 2022 03:41:44 -0400 Subject: [PATCH 63/88] Update packages/eslint-plugin/src/rules/strict-enums.ts Co-authored-by: Brad Zacher --- packages/eslint-plugin/src/rules/strict-enums.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 3ff4c0a1b06e..313bbcc38f22 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -752,8 +752,7 @@ export default util.createRule({ }, /** When a new variable is created. */ - VariableDeclaration(node): void { - for (const declaration of node.declarations) { + VariableDeclarator(node): void { const leftTSNode = parserServices.esTreeNodeToTSNodeMap.get(declaration); From 943bf9f58ea5b41f15119d9934638bd477cad228 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Mon, 30 May 2022 03:43:03 -0400 Subject: [PATCH 64/88] Update packages/eslint-plugin/src/rules/strict-enums.ts Co-authored-by: Brad Zacher --- packages/eslint-plugin/src/rules/strict-enums.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 313bbcc38f22..64ccb5002d94 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -17,7 +17,7 @@ enum EnumKind { } /** These operators are always considered to be safe. */ -const ALLOWED_ENUM_OPERATORS = new Set(['in', '|', '&', '|=', '&=']); +const ALLOWED_ENUM_OPERATORS = new Set(['in', '|', '&', '^', '|=', '&=', '^=']); /** * See the comment for `EnumKind`. From 7679c4a35254349d3abc250edf3d8fb2ff6e9aca Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 31 May 2022 20:59:14 -0400 Subject: [PATCH 65/88] fix: make brads updates actually compile --- .../eslint-plugin/src/rules/strict-enums.ts | 79 +- yarn.lock | 5316 +++++++++-------- 2 files changed, 2891 insertions(+), 2504 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 64ccb5002d94..3878f285554e 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -323,6 +323,10 @@ export default util.createRule({ node: TSESTree.CallExpression | TSESTree.NewExpression, ): void { const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); + if (!ts.isCallLikeExpression(tsNode)) { + return; + } + const signature = typeChecker.getResolvedSignature(tsNode); if (signature === undefined) { return; @@ -753,44 +757,45 @@ export default util.createRule({ /** When a new variable is created. */ VariableDeclarator(node): void { - const leftTSNode = - parserServices.esTreeNodeToTSNodeMap.get(declaration); - - /** - * Allow enum declarations without an initializer, like the following: - * - * ```ts - * let fruit: Fruit; - * if (something()) { - * fruit = Fruit.Apple; - * } else { - * fruit = Fruit.Banana; - * } - * ``` - */ - if (leftTSNode.initializer === undefined) { - continue; - } + const leftTSNode = parserServices.esTreeNodeToTSNodeMap.get(node); + if (!ts.isVariableDeclaration(leftTSNode)) { + return; + } - /** - * We have to use `leftTSNode.name` instead of `leftTSNode` to avoid - * runtime errors because the `typeChecker.getTypeAtLocation` method - * expects a `ts.BindingName` instead of a`ts.VariableDeclaration`. - * https://github.com/microsoft/TypeScript/issues/48878 - */ - const leftType = getTypeFromTSNode(leftTSNode.name); - const rightType = getTypeFromTSNode(leftTSNode.initializer); - - if (isAssigningNonEnumValueToEnumVariable(leftType, rightType)) { - context.report({ - node, - messageId: 'mismatchedAssignment', - data: { - assignmentType: getTypeName(rightType), - declaredType: getTypeName(leftType), - }, - }); - } + /** + * Allow enum declarations without an initializer, like the following: + * + * ```ts + * let fruit: Fruit; + * if (something()) { + * fruit = Fruit.Apple; + * } else { + * fruit = Fruit.Banana; + * } + * ``` + */ + if (leftTSNode.initializer === undefined) { + return; + } + + /** + * We have to use `leftTSNode.name` instead of `leftTSNode` to avoid + * runtime errors because the `typeChecker.getTypeAtLocation` method + * expects a `ts.BindingName` instead of a`ts.VariableDeclaration`. + * https://github.com/microsoft/TypeScript/issues/48878 + */ + const leftType = getTypeFromTSNode(leftTSNode.name); + const rightType = getTypeFromTSNode(leftTSNode.initializer); + + if (isAssigningNonEnumValueToEnumVariable(leftType, rightType)) { + context.report({ + node, + messageId: 'mismatchedAssignment', + data: { + assignmentType: getTypeName(rightType), + declaredType: getTypeName(leftType), + }, + }); } }, }; diff --git a/yarn.lock b/yarn.lock index f9bec1b98816..bb92814af5b0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,140 +2,134 @@ # yarn lockfile v1 -"@algolia/autocomplete-core@1.5.2": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.5.2.tgz#ec0178e07b44fd74a057728ac157291b26cecf37" - integrity sha512-DY0bhyczFSS1b/CqJlTE/nQRtnTAHl6IemIkBy0nEWnhDzRDdtdx4p5Uuk3vwAFxwEEgi1WqKwgSSMx6DpNL4A== - dependencies: - "@algolia/autocomplete-shared" "1.5.2" - -"@algolia/autocomplete-preset-algolia@1.5.2": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.5.2.tgz#36c5638cc6dba6ea46a86e5a0314637ca40a77ca" - integrity sha512-3MRYnYQFJyovANzSX2CToS6/5cfVjbLLqFsZTKcvF3abhQzxbqwwaMBlJtt620uBUOeMzhdfasKhCc40+RHiZw== +"@algolia/autocomplete-core@1.6.3": + version "1.6.3" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.6.3.tgz#76832fffb6405ac2c87bac5a040b8a31a1cdef80" + integrity sha512-dqQqRt01fX3YuVFrkceHsoCnzX0bLhrrg8itJI1NM68KjrPYQPYsE+kY8EZTCM4y8VDnhqJErR73xe/ZsV+qAA== dependencies: - "@algolia/autocomplete-shared" "1.5.2" + "@algolia/autocomplete-shared" "1.6.3" -"@algolia/autocomplete-shared@1.5.2": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.5.2.tgz#e157f9ad624ab8fd940ff28bd2094cdf199cdd79" - integrity sha512-ylQAYv5H0YKMfHgVWX0j0NmL8XBcAeeeVQUmppnnMtzDbDnca6CzhKj3Q8eF9cHCgcdTDdb5K+3aKyGWA0obug== +"@algolia/autocomplete-shared@1.6.3": + version "1.6.3" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.6.3.tgz#52085ce89a755977841ed0a463aa31ce8f1dea97" + integrity sha512-UV46bnkTztyADFaETfzFC5ryIdGVb2zpAoYgu0tfcuYWjhg1KbLXveFffZIrGVoboqmAk1b+jMrl6iCja1i3lg== -"@algolia/cache-browser-local-storage@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.13.0.tgz#f8aa4fe31104b19d616ea392f9ed5c2ea847d964" - integrity sha512-nj1vHRZauTqP/bluwkRIgEADEimqojJgoTRCel5f6q8WCa9Y8QeI4bpDQP28FoeKnDRYa3J5CauDlN466jqRhg== +"@algolia/cache-browser-local-storage@4.13.1": + version "4.13.1" + resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.13.1.tgz#ffacb9230119f77de1a6f163b83680be999110e4" + integrity sha512-UAUVG2PEfwd/FfudsZtYnidJ9eSCpS+LW9cQiesePQLz41NAcddKxBak6eP2GErqyFagSlnVXe/w2E9h2m2ttg== dependencies: - "@algolia/cache-common" "4.13.0" + "@algolia/cache-common" "4.13.1" -"@algolia/cache-common@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.13.0.tgz#27b83fd3939d08d72261b36a07eeafc4cb4d2113" - integrity sha512-f9mdZjskCui/dA/fA/5a+6hZ7xnHaaZI5tM/Rw9X8rRB39SUlF/+o3P47onZ33n/AwkpSbi5QOyhs16wHd55kA== +"@algolia/cache-common@4.13.1": + version "4.13.1" + resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.13.1.tgz#c933fdec9f73b4f7c69d5751edc92eee4a63d76b" + integrity sha512-7Vaf6IM4L0Jkl3sYXbwK+2beQOgVJ0mKFbz/4qSxKd1iy2Sp77uTAazcX+Dlexekg1fqGUOSO7HS4Sx47ZJmjA== -"@algolia/cache-in-memory@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.13.0.tgz#10801a74550cbabb64b59ff08c56bce9c278ff2d" - integrity sha512-hHdc+ahPiMM92CQMljmObE75laYzNFYLrNOu0Q3/eyvubZZRtY2SUsEEgyUEyzXruNdzrkcDxFYa7YpWBJYHAg== +"@algolia/cache-in-memory@4.13.1": + version "4.13.1" + resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.13.1.tgz#c19baa67b4597e1a93e987350613ab3b88768832" + integrity sha512-pZzybCDGApfA/nutsFK1P0Sbsq6fYJU3DwIvyKg4pURerlJM4qZbB9bfLRef0FkzfQu7W11E4cVLCIOWmyZeuQ== dependencies: - "@algolia/cache-common" "4.13.0" + "@algolia/cache-common" "4.13.1" -"@algolia/client-account@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.13.0.tgz#f8646dd40d1e9e3353e10abbd5d6c293ea92a8e2" - integrity sha512-FzFqFt9b0g/LKszBDoEsW+dVBuUe1K3scp2Yf7q6pgHWM1WqyqUlARwVpLxqyc+LoyJkTxQftOKjyFUqddnPKA== +"@algolia/client-account@4.13.1": + version "4.13.1" + resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.13.1.tgz#fea591943665477a23922ab31863ad0732e26c66" + integrity sha512-TFLiZ1KqMiir3FNHU+h3b0MArmyaHG+eT8Iojio6TdpeFcAQ1Aiy+2gb3SZk3+pgRJa/BxGmDkRUwE5E/lv3QQ== dependencies: - "@algolia/client-common" "4.13.0" - "@algolia/client-search" "4.13.0" - "@algolia/transporter" "4.13.0" + "@algolia/client-common" "4.13.1" + "@algolia/client-search" "4.13.1" + "@algolia/transporter" "4.13.1" -"@algolia/client-analytics@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.13.0.tgz#a00bd02df45d71becb9dd4c5c993d805f2e1786d" - integrity sha512-klmnoq2FIiiMHImkzOm+cGxqRLLu9CMHqFhbgSy9wtXZrqb8BBUIUE2VyBe7azzv1wKcxZV2RUyNOMpFqmnRZA== +"@algolia/client-analytics@4.13.1": + version "4.13.1" + resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.13.1.tgz#5275956b2d0d16997148f2085f1701b6c39ecc32" + integrity sha512-iOS1JBqh7xaL5x00M5zyluZ9+9Uy9GqtYHv/2SMuzNW1qP7/0doz1lbcsP3S7KBbZANJTFHUOfuqyRLPk91iFA== dependencies: - "@algolia/client-common" "4.13.0" - "@algolia/client-search" "4.13.0" - "@algolia/requester-common" "4.13.0" - "@algolia/transporter" "4.13.0" + "@algolia/client-common" "4.13.1" + "@algolia/client-search" "4.13.1" + "@algolia/requester-common" "4.13.1" + "@algolia/transporter" "4.13.1" -"@algolia/client-common@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.13.0.tgz#8bc373d164dbdcce38b4586912bbe162492bcb86" - integrity sha512-GoXfTp0kVcbgfSXOjfrxx+slSipMqGO9WnNWgeMmru5Ra09MDjrcdunsiiuzF0wua6INbIpBQFTC2Mi5lUNqGA== +"@algolia/client-common@4.13.1": + version "4.13.1" + resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.13.1.tgz#3bf9e3586f20ef85bbb56ccca390f7dbe57c8f4f" + integrity sha512-LcDoUE0Zz3YwfXJL6lJ2OMY2soClbjrrAKB6auYVMNJcoKZZ2cbhQoFR24AYoxnGUYBER/8B+9sTBj5bj/Gqbg== dependencies: - "@algolia/requester-common" "4.13.0" - "@algolia/transporter" "4.13.0" + "@algolia/requester-common" "4.13.1" + "@algolia/transporter" "4.13.1" -"@algolia/client-personalization@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.13.0.tgz#10fb7af356422551f11a67222b39c52306f1512c" - integrity sha512-KneLz2WaehJmNfdr5yt2HQETpLaCYagRdWwIwkTqRVFCv4DxRQ2ChPVW9jeTj4YfAAhfzE6F8hn7wkQ/Jfj6ZA== +"@algolia/client-personalization@4.13.1": + version "4.13.1" + resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.13.1.tgz#438a1f58576ef19c4ad4addb8417bdacfe2fce2e" + integrity sha512-1CqrOW1ypVrB4Lssh02hP//YxluoIYXAQCpg03L+/RiXJlCs+uIqlzC0ctpQPmxSlTK6h07kr50JQoYH/TIM9w== dependencies: - "@algolia/client-common" "4.13.0" - "@algolia/requester-common" "4.13.0" - "@algolia/transporter" "4.13.0" + "@algolia/client-common" "4.13.1" + "@algolia/requester-common" "4.13.1" + "@algolia/transporter" "4.13.1" -"@algolia/client-search@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.13.0.tgz#2d8ff8e755c4a37ec89968f3f9b358eed005c7f0" - integrity sha512-blgCKYbZh1NgJWzeGf+caKE32mo3j54NprOf0LZVCubQb3Kx37tk1Hc8SDs9bCAE8hUvf3cazMPIg7wscSxspA== +"@algolia/client-search@4.13.1": + version "4.13.1" + resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.13.1.tgz#5501deed01e23c33d4aaa9f9eb96a849f0fce313" + integrity sha512-YQKYA83MNRz3FgTNM+4eRYbSmHi0WWpo019s5SeYcL3HUan/i5R09VO9dk3evELDFJYciiydSjbsmhBzbpPP2A== dependencies: - "@algolia/client-common" "4.13.0" - "@algolia/requester-common" "4.13.0" - "@algolia/transporter" "4.13.0" + "@algolia/client-common" "4.13.1" + "@algolia/requester-common" "4.13.1" + "@algolia/transporter" "4.13.1" "@algolia/events@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950" integrity sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ== -"@algolia/logger-common@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.13.0.tgz#be2606e71aae618a1ff1ea9a1b5f5a74284b35a8" - integrity sha512-8yqXk7rMtmQJ9wZiHOt/6d4/JDEg5VCk83gJ39I+X/pwUPzIsbKy9QiK4uJ3aJELKyoIiDT1hpYVt+5ia+94IA== +"@algolia/logger-common@4.13.1": + version "4.13.1" + resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.13.1.tgz#4221378e701e3f1eacaa051bcd4ba1f25ddfaf4d" + integrity sha512-L6slbL/OyZaAXNtS/1A8SAbOJeEXD5JcZeDCPYDqSTYScfHu+2ePRTDMgUTY4gQ7HsYZ39N1LujOd8WBTmM2Aw== -"@algolia/logger-console@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.13.0.tgz#f28028a760e3d9191e28a10b12925e48f6c9afde" - integrity sha512-YepRg7w2/87L0vSXRfMND6VJ5d6699sFJBRWzZPOlek2p5fLxxK7O0VncYuc/IbVHEgeApvgXx0WgCEa38GVuQ== +"@algolia/logger-console@4.13.1": + version "4.13.1" + resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.13.1.tgz#423d358e4992dd4bceab0d9a4e99d1fd68107043" + integrity sha512-7jQOTftfeeLlnb3YqF8bNgA2GZht7rdKkJ31OCeSH2/61haO0tWPoNRjZq9XLlgMQZH276pPo0NdiArcYPHjCA== dependencies: - "@algolia/logger-common" "4.13.0" + "@algolia/logger-common" "4.13.1" -"@algolia/requester-browser-xhr@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.13.0.tgz#e2483f4e8d7f09e27cd0daf6c77711d15c5a919f" - integrity sha512-Dj+bnoWR5MotrnjblzGKZ2kCdQi2cK/VzPURPnE616NU/il7Ypy6U6DLGZ/ZYz+tnwPa0yypNf21uqt84fOgrg== +"@algolia/requester-browser-xhr@4.13.1": + version "4.13.1" + resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.13.1.tgz#f8ea79233cf6f0392feaf31e35a6b40d68c5bc9e" + integrity sha512-oa0CKr1iH6Nc7CmU6RE7TnXMjHnlyp7S80pP/LvZVABeJHX3p/BcSCKovNYWWltgTxUg0U1o+2uuy8BpMKljwA== dependencies: - "@algolia/requester-common" "4.13.0" + "@algolia/requester-common" "4.13.1" -"@algolia/requester-common@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.13.0.tgz#47fb3464cfb26b55ba43676d13f295d812830596" - integrity sha512-BRTDj53ecK+gn7ugukDWOOcBRul59C4NblCHqj4Zm5msd5UnHFjd/sGX+RLOEoFMhetILAnmg6wMrRrQVac9vw== +"@algolia/requester-common@4.13.1": + version "4.13.1" + resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.13.1.tgz#daea143d15ab6ed3909c4c45877f1b6c36a16179" + integrity sha512-eGVf0ID84apfFEuXsaoSgIxbU3oFsIbz4XiotU3VS8qGCJAaLVUC5BUJEkiFENZIhon7hIB4d0RI13HY4RSA+w== -"@algolia/requester-node-http@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.13.0.tgz#7d981bbd31492f51dd11820a665f9d8906793c37" - integrity sha512-9b+3O4QFU4azLhGMrZAr/uZPydvzOR4aEZfSL8ZrpLZ7fbbqTO0S/5EVko+QIgglRAtVwxvf8UJ1wzTD2jvKxQ== +"@algolia/requester-node-http@4.13.1": + version "4.13.1" + resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.13.1.tgz#32c63d4c009f22d97e396406de7af9b66fb8e89d" + integrity sha512-7C0skwtLdCz5heKTVe/vjvrqgL/eJxmiEjHqXdtypcE5GCQCYI15cb+wC4ytYioZDMiuDGeVYmCYImPoEgUGPw== dependencies: - "@algolia/requester-common" "4.13.0" + "@algolia/requester-common" "4.13.1" -"@algolia/transporter@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.13.0.tgz#f6379e5329efa2127da68c914d1141f5f21dbd07" - integrity sha512-8tSQYE+ykQENAdeZdofvtkOr5uJ9VcQSWgRhQ9h01AehtBIPAczk/b2CLrMsw5yQZziLs5cZ3pJ3478yI+urhA== +"@algolia/transporter@4.13.1": + version "4.13.1" + resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.13.1.tgz#509e03e9145102843d5be4a031c521f692d4e8d6" + integrity sha512-pICnNQN7TtrcYJqqPEXByV8rJ8ZRU2hCiIKLTLRyNpghtQG3VAFk6fVtdzlNfdUGZcehSKGarPIZEHlQXnKjgw== dependencies: - "@algolia/cache-common" "4.13.0" - "@algolia/logger-common" "4.13.0" - "@algolia/requester-common" "4.13.0" + "@algolia/cache-common" "4.13.1" + "@algolia/logger-common" "4.13.1" + "@algolia/requester-common" "4.13.1" "@ampproject/remapping@^2.1.0": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" - integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== + version "2.2.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" + integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== dependencies: - "@jridgewell/trace-mapping" "^0.3.0" + "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/trace-mapping" "^0.3.9" "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.14.5", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.8.3": version "7.16.7" @@ -144,31 +138,26 @@ dependencies: "@babel/highlight" "^7.16.7" -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.8", "@babel/compat-data@^7.17.0": - version "7.17.7" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.7.tgz#078d8b833fbbcc95286613be8c716cef2b519fa2" - integrity sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ== - -"@babel/compat-data@^7.17.10": +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.17.10": version "7.17.10" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.10.tgz#711dc726a492dfc8be8220028b1b92482362baab" integrity sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw== -"@babel/core@*", "@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.15.5", "@babel/core@^7.17.8", "@babel/core@^7.7.2", "@babel/core@^7.7.5", "@babel/core@^7.8.0": - version "7.17.10" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.10.tgz#74ef0fbf56b7dfc3f198fc2d927f4f03e12f4b05" - integrity sha512-liKoppandF3ZcBnIYFjfSDHZLKdLHGJRkoWtG8zQyGJBQfIYobpnVGI5+pLBNtS6psFLDzyq8+h5HiVljW9PNA== +"@babel/core@*", "@babel/core@^7.1.0", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.15.5", "@babel/core@^7.18.2", "@babel/core@^7.7.2", "@babel/core@^7.7.5", "@babel/core@^7.8.0": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.2.tgz#87b2fcd7cce9becaa7f5acebdc4f09f3dd19d876" + integrity sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ== dependencies: "@ampproject/remapping" "^2.1.0" "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.10" - "@babel/helper-compilation-targets" "^7.17.10" - "@babel/helper-module-transforms" "^7.17.7" - "@babel/helpers" "^7.17.9" - "@babel/parser" "^7.17.10" + "@babel/generator" "^7.18.2" + "@babel/helper-compilation-targets" "^7.18.2" + "@babel/helper-module-transforms" "^7.18.0" + "@babel/helpers" "^7.18.2" + "@babel/parser" "^7.18.0" "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.10" - "@babel/types" "^7.17.10" + "@babel/traverse" "^7.18.2" + "@babel/types" "^7.18.2" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -198,21 +187,21 @@ source-map "^0.5.0" "@babel/eslint-parser@*", "@babel/eslint-parser@^7.15.4": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.17.0.tgz#eabb24ad9f0afa80e5849f8240d0e5facc2d90d6" - integrity sha512-PUEJ7ZBXbRkbq3qqM/jZ2nIuakUBqCYc7Qf52Lj7dlZ6zERnqisdHioL0l4wwQZnmskMeasqUNzLBFKs3nylXA== + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.18.2.tgz#e14dee36c010edfb0153cf900c2b0815e82e3245" + integrity sha512-oFQYkE8SuH14+uR51JVAmdqwKYXGRjEXx7s+WiagVjqQ+HPE+nnwyF2qlVG8evUsUHmPcA+6YXMEDbIhEyQc5A== dependencies: eslint-scope "^5.1.1" eslint-visitor-keys "^2.1.0" semver "^6.3.0" -"@babel/generator@^7.12.5", "@babel/generator@^7.17.10", "@babel/generator@^7.17.7", "@babel/generator@^7.7.2": - version "7.17.10" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.10.tgz#c281fa35b0c349bbe9d02916f4ae08fc85ed7189" - integrity sha512-46MJZZo9y3o4kmhBVc7zW7i8dtR1oIK/sdO5NcfcZRhTGYi+KKJRtHNgsU6c4VUcJmUNV/LQdebD/9Dlv4K+Tg== +"@babel/generator@^7.12.5", "@babel/generator@^7.18.2", "@babel/generator@^7.7.2": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.2.tgz#33873d6f89b21efe2da63fe554460f3df1c5880d" + integrity sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw== dependencies: - "@babel/types" "^7.17.10" - "@jridgewell/gen-mapping" "^0.1.0" + "@babel/types" "^7.18.2" + "@jridgewell/gen-mapping" "^0.3.0" jsesc "^2.5.1" "@babel/helper-annotate-as-pure@^7.16.7": @@ -230,38 +219,38 @@ "@babel/helper-explode-assignable-expression" "^7.16.7" "@babel/types" "^7.16.7" -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7", "@babel/helper-compilation-targets@^7.17.10": - version "7.17.10" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.10.tgz#09c63106d47af93cf31803db6bc49fef354e2ebe" - integrity sha512-gh3RxjWbauw/dFiU/7whjd0qN9K6nPJMqe6+Er7rOavFh0CQUSwhAE3IcTho2rywPJFxej6TUUHDkWcYI6gGqQ== +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7", "@babel/helper-compilation-targets@^7.17.10", "@babel/helper-compilation-targets@^7.18.2": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz#67a85a10cbd5fc7f1457fec2e7f45441dc6c754b" + integrity sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ== dependencies: "@babel/compat-data" "^7.17.10" "@babel/helper-validator-option" "^7.16.7" browserslist "^4.20.2" semver "^6.3.0" -"@babel/helper-create-class-features-plugin@^7.16.10", "@babel/helper-create-class-features-plugin@^7.16.7", "@babel/helper-create-class-features-plugin@^7.17.6": - version "7.17.6" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz#3778c1ed09a7f3e65e6d6e0f6fbfcc53809d92c9" - integrity sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg== +"@babel/helper-create-class-features-plugin@^7.17.12", "@babel/helper-create-class-features-plugin@^7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.0.tgz#fac430912606331cb075ea8d82f9a4c145a4da19" + integrity sha512-Kh8zTGR9de3J63e5nS0rQUdRs/kbtwoeQQ0sriS0lItjC96u8XXZN6lKpuyWd2coKSU13py/y+LTmThLuVX0Pg== dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-function-name" "^7.17.9" + "@babel/helper-member-expression-to-functions" "^7.17.7" "@babel/helper-optimise-call-expression" "^7.16.7" "@babel/helper-replace-supers" "^7.16.7" "@babel/helper-split-export-declaration" "^7.16.7" -"@babel/helper-create-regexp-features-plugin@^7.16.7": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz#1dcc7d40ba0c6b6b25618997c5dbfd310f186fe1" - integrity sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA== +"@babel/helper-create-regexp-features-plugin@^7.16.7", "@babel/helper-create-regexp-features-plugin@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.12.tgz#bb37ca467f9694bbe55b884ae7a5cc1e0084e4fd" + integrity sha512-b2aZrV4zvutr9AIa6/gA3wsZKRwTKYoDxYiFKcESS3Ug2GTXzwBEvMuuFLhCQpEnRXs1zng4ISAXSUxxKBIcxw== dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" regexpu-core "^5.0.1" -"@babel/helper-define-polyfill-provider@^0.3.0", "@babel/helper-define-polyfill-provider@^0.3.1": +"@babel/helper-define-polyfill-provider@^0.3.1": version "0.3.1" resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz#52411b445bdb2e676869e5a74960d2d3826d2665" integrity sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA== @@ -275,12 +264,10 @@ resolve "^1.14.2" semver "^6.1.2" -"@babel/helper-environment-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" - integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== - dependencies: - "@babel/types" "^7.16.7" +"@babel/helper-environment-visitor@^7.16.7", "@babel/helper-environment-visitor@^7.18.2": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz#8a6d2dedb53f6bf248e31b4baf38739ee4a637bd" + integrity sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ== "@babel/helper-explode-assignable-expression@^7.16.7": version "7.16.7" @@ -304,7 +291,7 @@ dependencies: "@babel/types" "^7.16.7" -"@babel/helper-member-expression-to-functions@^7.16.7": +"@babel/helper-member-expression-to-functions@^7.17.7": version "7.17.7" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.17.7.tgz#a34013b57d8542a8c4ff8ba3f747c02452a4d8c4" integrity sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw== @@ -318,10 +305,10 @@ dependencies: "@babel/types" "^7.16.7" -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.16.7", "@babel/helper-module-transforms@^7.17.7": - version "7.17.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz#3943c7f777139e7954a5355c815263741a9c1cbd" - integrity sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw== +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz#baf05dec7a5875fb9235bd34ca18bad4e21221cd" + integrity sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA== dependencies: "@babel/helper-environment-visitor" "^7.16.7" "@babel/helper-module-imports" "^7.16.7" @@ -329,8 +316,8 @@ "@babel/helper-split-export-declaration" "^7.16.7" "@babel/helper-validator-identifier" "^7.16.7" "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.3" - "@babel/types" "^7.17.0" + "@babel/traverse" "^7.18.0" + "@babel/types" "^7.18.0" "@babel/helper-optimise-call-expression@^7.16.7": version "7.16.7" @@ -344,10 +331,10 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" - integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.17.12", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz#86c2347da5acbf5583ba0a10aed4c9bf9da9cf96" + integrity sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA== "@babel/helper-remap-async-to-generator@^7.16.8": version "7.16.8" @@ -358,23 +345,23 @@ "@babel/helper-wrap-function" "^7.16.8" "@babel/types" "^7.16.8" -"@babel/helper-replace-supers@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz#e9f5f5f32ac90429c1a4bdec0f231ef0c2838ab1" - integrity sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw== +"@babel/helper-replace-supers@^7.16.7", "@babel/helper-replace-supers@^7.18.2": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.18.2.tgz#41fdfcc9abaf900e18ba6e5931816d9062a7b2e0" + integrity sha512-XzAIyxx+vFnrOxiQrToSUOzUOn0e1J2Li40ntddek1Y69AXUTXoDJ40/D5RdjFu7s7qHiaeoTiempZcbuVXh2Q== dependencies: - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-environment-visitor" "^7.18.2" + "@babel/helper-member-expression-to-functions" "^7.17.7" "@babel/helper-optimise-call-expression" "^7.16.7" - "@babel/traverse" "^7.16.7" - "@babel/types" "^7.16.7" + "@babel/traverse" "^7.18.2" + "@babel/types" "^7.18.2" -"@babel/helper-simple-access@^7.17.7": - version "7.17.7" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz#aaa473de92b7987c6dfa7ce9a7d9674724823367" - integrity sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA== +"@babel/helper-simple-access@^7.17.7", "@babel/helper-simple-access@^7.18.2": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz#4dc473c2169ac3a1c9f4a51cfcd091d1c36fcff9" + integrity sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ== dependencies: - "@babel/types" "^7.17.0" + "@babel/types" "^7.18.2" "@babel/helper-skip-transparent-expression-wrappers@^7.16.0": version "7.16.0" @@ -410,69 +397,69 @@ "@babel/traverse" "^7.16.8" "@babel/types" "^7.16.8" -"@babel/helpers@^7.12.5", "@babel/helpers@^7.17.9": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.9.tgz#b2af120821bfbe44f9907b1826e168e819375a1a" - integrity sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q== +"@babel/helpers@^7.12.5", "@babel/helpers@^7.18.2": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.2.tgz#970d74f0deadc3f5a938bfa250738eb4ac889384" + integrity sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg== dependencies: "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.9" - "@babel/types" "^7.17.0" + "@babel/traverse" "^7.18.2" + "@babel/types" "^7.18.2" "@babel/highlight@^7.16.7": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.17.9.tgz#61b2ee7f32ea0454612def4fccdae0de232b73e3" - integrity sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg== + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.17.12.tgz#257de56ee5afbd20451ac0a75686b6b404257351" + integrity sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg== dependencies: "@babel/helper-validator-identifier" "^7.16.7" chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@*", "@babel/parser@^7.1.0", "@babel/parser@^7.12.7", "@babel/parser@^7.14.7", "@babel/parser@^7.15.7", "@babel/parser@^7.16.7", "@babel/parser@^7.17.10", "@babel/parser@^7.17.8": - version "7.17.10" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.10.tgz#873b16db82a8909e0fbd7f115772f4b739f6ce78" - integrity sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ== +"@babel/parser@*", "@babel/parser@^7.1.0", "@babel/parser@^7.12.7", "@babel/parser@^7.14.7", "@babel/parser@^7.15.7", "@babel/parser@^7.16.7", "@babel/parser@^7.17.8", "@babel/parser@^7.18.0", "@babel/parser@^7.18.3": + version "7.18.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.4.tgz#6774231779dd700e0af29f6ad8d479582d7ce5ef" + integrity sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow== -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz#4eda6d6c2a0aa79c70fa7b6da67763dfe2141050" - integrity sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.17.12.tgz#1dca338caaefca368639c9ffb095afbd4d420b1e" + integrity sha512-xCJQXl4EeQ3J9C4yOmpTrtVGmzpm2iSzyxbkZHw7UCnZBftHpF/hpII80uWVyVrc40ytIClHjgWGTG1g/yB+aw== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz#cc001234dfc139ac45f6bcf801866198c8c72ff9" - integrity sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.17.12.tgz#0d498ec8f0374b1e2eb54b9cb2c4c78714c77753" + integrity sha512-/vt0hpIw0x4b6BLKUkwlvEoiGZYYLNZ96CzyHYPbtG2jZGz6LBe7/V+drYrc/d+ovrF9NBi0pmtvmNb/FsWtRQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" - "@babel/plugin-proposal-optional-chaining" "^7.16.7" + "@babel/plugin-proposal-optional-chaining" "^7.17.12" -"@babel/plugin-proposal-async-generator-functions@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz#3bdd1ebbe620804ea9416706cd67d60787504bc8" - integrity sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ== +"@babel/plugin-proposal-async-generator-functions@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.17.12.tgz#094a417e31ce7e692d84bab06c8e2a607cbeef03" + integrity sha512-RWVvqD1ooLKP6IqWTA5GyFVX2isGEgC5iFxKzfYOIy/QEFdxYyCybBDtIGjipHpb9bDWHzcqGqFakf+mVmBTdQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/helper-remap-async-to-generator" "^7.16.8" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-proposal-class-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz#925cad7b3b1a2fcea7e59ecc8eb5954f961f91b0" - integrity sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww== +"@babel/plugin-proposal-class-properties@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.17.12.tgz#84f65c0cc247d46f40a6da99aadd6438315d80a4" + integrity sha512-U0mI9q8pW5Q9EaTHFPwSVusPMV/DV9Mm8p7csqROFLtIE9rBF5piLqyrBGigftALrBcsBGu4m38JneAe7ZDLXw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.17.12" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-proposal-class-static-block@^7.16.7": - version "7.17.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.17.6.tgz#164e8fd25f0d80fa48c5a4d1438a6629325ad83c" - integrity sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA== +"@babel/plugin-proposal-class-static-block@^7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.0.tgz#7d02253156e3c3793bdb9f2faac3a1c05f0ba710" + integrity sha512-t+8LsRMMDE74c6sV7KShIw13sqbqd58tlqNrsWoWBTIMw7SVQ0cZ905wLNS/FBCy/3PyooRHLFFlfrUNyyz5lA== dependencies: - "@babel/helper-create-class-features-plugin" "^7.17.6" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.18.0" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-proposal-dynamic-import@^7.16.7": @@ -483,36 +470,36 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-proposal-export-namespace-from@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz#09de09df18445a5786a305681423ae63507a6163" - integrity sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA== +"@babel/plugin-proposal-export-namespace-from@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.17.12.tgz#b22864ccd662db9606edb2287ea5fd1709f05378" + integrity sha512-j7Ye5EWdwoXOpRmo5QmRyHPsDIe6+u70ZYZrd7uz+ebPYFKfRcLcNu3Ro0vOlJ5zuv8rU7xa+GttNiRzX56snQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-proposal-json-strings@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz#9732cb1d17d9a2626a08c5be25186c195b6fa6e8" - integrity sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ== +"@babel/plugin-proposal-json-strings@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.17.12.tgz#f4642951792437233216d8c1af370bb0fbff4664" + integrity sha512-rKJ+rKBoXwLnIn7n6o6fulViHMrOThz99ybH+hKHcOZbnN14VuMnH9fo2eHE69C8pO4uX1Q7t2HYYIDmv8VYkg== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-proposal-logical-assignment-operators@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz#be23c0ba74deec1922e639832904be0bea73cdea" - integrity sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg== +"@babel/plugin-proposal-logical-assignment-operators@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.17.12.tgz#c64a1bcb2b0a6d0ed2ff674fd120f90ee4b88a23" + integrity sha512-EqFo2s1Z5yy+JeJu7SFfbIUtToJTVlC61/C7WLKDntSw4Sz6JNAIfL7zQ74VvirxpjB5kz/kIx0gCcb+5OEo2Q== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz#141fc20b6857e59459d430c850a0011e36561d99" - integrity sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ== +"@babel/plugin-proposal-nullish-coalescing-operator@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.17.12.tgz#1e93079bbc2cbc756f6db6a1925157c4a92b94be" + integrity sha512-ws/g3FSGVzv+VH86+QvgtuJL/kR67xaEIF2x0iPqdDfYW6ra6JF3lKVBkWynRLcNtIC1oCTfDRVxmm2mKzy+ag== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" "@babel/plugin-proposal-numeric-separator@^7.16.7": @@ -532,16 +519,16 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.0" "@babel/plugin-transform-parameters" "^7.12.1" -"@babel/plugin-proposal-object-rest-spread@^7.16.7": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz#d9eb649a54628a51701aef7e0ea3d17e2b9dd390" - integrity sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw== +"@babel/plugin-proposal-object-rest-spread@^7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.0.tgz#79f2390c892ba2a68ec112eb0d895cfbd11155e8" + integrity sha512-nbTv371eTrFabDfHLElkn9oyf9VG+VKK6WMzhY2o4eHKaG19BToD9947zzGMO6I/Irstx9d8CwX6njPNIAR/yw== dependencies: - "@babel/compat-data" "^7.17.0" - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/compat-data" "^7.17.10" + "@babel/helper-compilation-targets" "^7.17.10" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.16.7" + "@babel/plugin-transform-parameters" "^7.17.12" "@babel/plugin-proposal-optional-catch-binding@^7.16.7": version "7.16.7" @@ -551,40 +538,40 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-proposal-optional-chaining@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz#7cd629564724816c0e8a969535551f943c64c39a" - integrity sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA== +"@babel/plugin-proposal-optional-chaining@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.17.12.tgz#f96949e9bacace3a9066323a5cf90cfb9de67174" + integrity sha512-7wigcOs/Z4YWlK7xxjkvaIw84vGhDv/P1dFGQap0nHkc8gFKY/r+hXc8Qzf5k1gY7CvGIcHqAnOagVKJJ1wVOQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-proposal-private-methods@^7.16.11": - version "7.16.11" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz#e8df108288555ff259f4527dbe84813aac3a1c50" - integrity sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw== +"@babel/plugin-proposal-private-methods@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.17.12.tgz#c2ca3a80beb7539289938da005ad525a038a819c" + integrity sha512-SllXoxo19HmxhDWm3luPz+cPhtoTSKLJE9PXshsfrOzBqs60QP0r8OaJItrPhAj0d7mZMnNF0Y1UUggCDgMz1A== dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.10" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.17.12" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-proposal-private-property-in-object@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz#b0b8cef543c2c3d57e59e2c611994861d46a3fce" - integrity sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ== +"@babel/plugin-proposal-private-property-in-object@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.17.12.tgz#b02efb7f106d544667d91ae97405a9fd8c93952d" + integrity sha512-/6BtVi57CJfrtDNKfK5b66ydK2J5pXUKBKSPD2G1whamMuEnZWgoOIfO8Vf9F/DoD4izBLD/Au4NMQfruzzykg== dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-create-class-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.17.12" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" -"@babel/plugin-proposal-unicode-property-regex@^7.16.7", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz#635d18eb10c6214210ffc5ff4932552de08188a2" - integrity sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg== +"@babel/plugin-proposal-unicode-property-regex@^7.17.12", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.17.12.tgz#3dbd7a67bd7f94c8238b394da112d86aaf32ad4d" + integrity sha512-Wb9qLjXf3ZazqXA7IvI7ozqRIXIGPtSo+L5coFmEkhTQK18ao4UDDD0zdTGAarmbLj2urpRwrc6893cu5Bfh0A== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-create-regexp-features-plugin" "^7.17.12" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -628,6 +615,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" +"@babel/plugin-syntax-import-assertions@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.17.12.tgz#58096a92b11b2e4e54b24c6a0cc0e5e607abcedd" + integrity sha512-n/loy2zkq9ZEM8tEOwON9wTQSTNDTDEz6NujPtJGLU7qObzT1N4c4YZZf8E6ATB2AjNQg/Ib2AIpO03EZaCehw== + dependencies: + "@babel/helper-plugin-utils" "^7.17.12" + "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" @@ -649,12 +643,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-jsx@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz#50b6571d13f764266a113d77c82b4a6508bbe665" - integrity sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q== +"@babel/plugin-syntax-jsx@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.17.12.tgz#834035b45061983a491f60096f61a2e7c5674a47" + integrity sha512-spyY3E3AURfxh/RHtjx5j6hs8am5NbUBGfcZ2vB3uShSpZdQyXSf5rR5Mk76vbtlAZOelyVQ71Fg0x9SG4fsog== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.4" @@ -712,27 +706,27 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-typescript@^7.16.7", "@babel/plugin-syntax-typescript@^7.7.2": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz#39c9b55ee153151990fb038651d58d3fd03f98f8" - integrity sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A== +"@babel/plugin-syntax-typescript@^7.17.12", "@babel/plugin-syntax-typescript@^7.7.2": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.17.12.tgz#b54fc3be6de734a56b87508f99d6428b5b605a7b" + integrity sha512-TYY0SXFiO31YXtNg3HtFwNJHjLsAyIIhAhNWkQ5whPPS7HWUFlg9z0Ta4qAQNjQbP1wsSt/oKkmZ/4/WWdMUpw== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-transform-arrow-functions@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz#44125e653d94b98db76369de9c396dc14bef4154" - integrity sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ== +"@babel/plugin-transform-arrow-functions@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.17.12.tgz#dddd783b473b1b1537ef46423e3944ff24898c45" + integrity sha512-PHln3CNi/49V+mza4xMwrg+WGYevSF1oaiXaC2EQfdp4HWlSjRsrDXWJiQBKpP7749u6vQ9mcry2uuFOv5CXvA== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-transform-async-to-generator@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz#b83dff4b970cf41f1b819f8b49cc0cfbaa53a808" - integrity sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg== +"@babel/plugin-transform-async-to-generator@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.17.12.tgz#dbe5511e6b01eee1496c944e35cdfe3f58050832" + integrity sha512-J8dbrWIOO3orDzir57NRsjg4uxucvhby0L/KZuGsWDj0g7twWK3g7JhJhOrXtuXiw8MeiSdJ3E0OW9H8LYEzLQ== dependencies: "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/helper-remap-async-to-generator" "^7.16.8" "@babel/plugin-transform-block-scoped-functions@^7.16.7": @@ -742,40 +736,40 @@ dependencies: "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-block-scoping@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz#f50664ab99ddeaee5bc681b8f3a6ea9d72ab4f87" - integrity sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ== +"@babel/plugin-transform-block-scoping@^7.17.12": + version "7.18.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.4.tgz#7988627b3e9186a13e4d7735dc9c34a056613fb9" + integrity sha512-+Hq10ye+jlvLEogSOtq4mKvtk7qwcUQ1f0Mrueai866C82f844Yom2cttfJdMdqRLTxWpsbfbkIkOIfovyUQXw== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-transform-classes@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz#8f4b9562850cd973de3b498f1218796eb181ce00" - integrity sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ== +"@babel/plugin-transform-classes@^7.17.12": + version "7.18.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.4.tgz#51310b812a090b846c784e47087fa6457baef814" + integrity sha512-e42NSG2mlKWgxKUAD9EJJSkZxR67+wZqzNxLSpc51T8tRU5SLFHsPmgYR5yr7sdgX4u+iHA1C5VafJ6AyImV3A== dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" + "@babel/helper-environment-visitor" "^7.18.2" + "@babel/helper-function-name" "^7.17.9" "@babel/helper-optimise-call-expression" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-replace-supers" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" + "@babel/helper-replace-supers" "^7.18.2" "@babel/helper-split-export-declaration" "^7.16.7" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz#66dee12e46f61d2aae7a73710f591eb3df616470" - integrity sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw== +"@babel/plugin-transform-computed-properties@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.17.12.tgz#bca616a83679698f3258e892ed422546e531387f" + integrity sha512-a7XINeplB5cQUWMg1E/GI1tFz3LfK021IjV1rj1ypE+R7jHm+pIHmHl25VNkZxtx9uuYp7ThGk8fur1HHG7PgQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-transform-destructuring@^7.16.7": - version "7.17.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.7.tgz#49dc2675a7afa9a5e4c6bdee636061136c3408d1" - integrity sha512-XVh0r5yq9sLR4vZ6eVZe8FKfIcSgaTBxVBRSYokRj2qksf6QerYnTxz9/GTuKTH/n/HwLP7t6gtlybHetJ/6hQ== +"@babel/plugin-transform-destructuring@^7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.0.tgz#dc4f92587e291b4daa78aa20cc2d7a63aa11e858" + integrity sha512-Mo69klS79z6KEfrLg/1WkmVnB8javh75HX4pi2btjvlIoasuxilEyjtsQW6XPrubNd7AQy0MMaNIaQE4e7+PQw== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-transform-dotall-regex@^7.16.7", "@babel/plugin-transform-dotall-regex@^7.4.4": version "7.16.7" @@ -785,12 +779,12 @@ "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-duplicate-keys@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz#2207e9ca8f82a0d36a5a67b6536e7ef8b08823c9" - integrity sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw== +"@babel/plugin-transform-duplicate-keys@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.17.12.tgz#a09aa709a3310013f8e48e0e23bc7ace0f21477c" + integrity sha512-EA5eYFUG6xeerdabina/xIoB95jJ17mAkR8ivx6ZSu9frKShBjpOGZPn511MTDTkiCO+zXnzNczvUM69YSf3Zw== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-transform-exponentiation-operator@^7.16.7": version "7.16.7" @@ -800,12 +794,12 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-for-of@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz#649d639d4617dff502a9a158c479b3b556728d8c" - integrity sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg== +"@babel/plugin-transform-for-of@^7.18.1": + version "7.18.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.1.tgz#ed14b657e162b72afbbb2b4cdad277bf2bb32036" + integrity sha512-+TTB5XwvJ5hZbO8xvl2H4XaMDOAK57zF4miuC9qQJgysPNEAZZ9Z69rdF5LJkozGdZrjBIUAIyKUWRMmebI7vg== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-transform-function-name@^7.16.7": version "7.16.7" @@ -816,12 +810,12 @@ "@babel/helper-function-name" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz#254c9618c5ff749e87cb0c0cef1a0a050c0bdab1" - integrity sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ== +"@babel/plugin-transform-literals@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.17.12.tgz#97131fbc6bbb261487105b4b3edbf9ebf9c830ae" + integrity sha512-8iRkvaTjJciWycPIZ9k9duu663FT7VrBdNqNgxnVXEFwOIp55JWcZd23VBRySYbnS3PwQ3rGiabJBBBGj5APmQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-transform-member-expression-literals@^7.16.7": version "7.16.7" @@ -830,57 +824,58 @@ dependencies: "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-modules-amd@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz#b28d323016a7daaae8609781d1f8c9da42b13186" - integrity sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g== +"@babel/plugin-transform-modules-amd@^7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.0.tgz#7ef1002e67e36da3155edc8bf1ac9398064c02ed" + integrity sha512-h8FjOlYmdZwl7Xm2Ug4iX2j7Qy63NANI+NQVWQzv6r25fqgg7k2dZl03p95kvqNclglHs4FZ+isv4p1uXMA+QA== dependencies: - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-module-transforms" "^7.18.0" + "@babel/helper-plugin-utils" "^7.17.12" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.16.8": - version "7.17.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.17.7.tgz#d86b217c8e45bb5f2dbc11eefc8eab62cf980d19" - integrity sha512-ITPmR2V7MqioMJyrxUo2onHNC3e+MvfFiFIR0RP21d3PtlVb6sfzoxNKiphSZUOM9hEIdzCcZe83ieX3yoqjUA== +"@babel/plugin-transform-modules-commonjs@^7.18.2": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.2.tgz#1aa8efa2e2a6e818b6a7f2235fceaf09bdb31e9e" + integrity sha512-f5A865gFPAJAEE0K7F/+nm5CmAE3y8AWlMBG9unu5j9+tk50UQVK0QS8RNxSp7MJf0wh97uYyLWt3Zvu71zyOQ== dependencies: - "@babel/helper-module-transforms" "^7.17.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-simple-access" "^7.17.7" + "@babel/helper-module-transforms" "^7.18.0" + "@babel/helper-plugin-utils" "^7.17.12" + "@babel/helper-simple-access" "^7.18.2" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.16.7": - version "7.17.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.17.8.tgz#81fd834024fae14ea78fbe34168b042f38703859" - integrity sha512-39reIkMTUVagzgA5x88zDYXPCMT6lcaRKs1+S9K6NKBPErbgO/w/kP8GlNQTC87b412ZTlmNgr3k2JrWgHH+Bw== +"@babel/plugin-transform-modules-systemjs@^7.18.0": + version "7.18.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.4.tgz#3d6fd9868c735cce8f38d6ae3a407fb7e61e6d46" + integrity sha512-lH2UaQaHVOAeYrUUuZ8i38o76J/FnO8vu21OE+tD1MyP9lxdZoSfz+pDbWkq46GogUrdrMz3tiz/FYGB+bVThg== dependencies: "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-module-transforms" "^7.17.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-module-transforms" "^7.18.0" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/helper-validator-identifier" "^7.16.7" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-umd@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz#23dad479fa585283dbd22215bff12719171e7618" - integrity sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ== +"@babel/plugin-transform-modules-umd@^7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.0.tgz#56aac64a2c2a1922341129a4597d1fd5c3ff020f" + integrity sha512-d/zZ8I3BWli1tmROLxXLc9A6YXvGK8egMxHp+E/rRwMh1Kip0AP77VwZae3snEJ33iiWwvNv2+UIIhfalqhzZA== dependencies: - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-module-transforms" "^7.18.0" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-transform-named-capturing-groups-regex@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz#7f860e0e40d844a02c9dcf9d84965e7dfd666252" - integrity sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw== +"@babel/plugin-transform-named-capturing-groups-regex@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.17.12.tgz#9c4a5a5966e0434d515f2675c227fd8cc8606931" + integrity sha512-vWoWFM5CKaTeHrdUJ/3SIOTRV+MBVGybOC9mhJkaprGNt5demMymDW24yC74avb915/mIRe3TgNb/d8idvnCRA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-create-regexp-features-plugin" "^7.17.12" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-transform-new-target@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz#9967d89a5c243818e0800fdad89db22c5f514244" - integrity sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg== +"@babel/plugin-transform-new-target@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.17.12.tgz#10842cd605a620944e81ea6060e9e65c265742e3" + integrity sha512-CaOtzk2fDYisbjAD4Sd1MTKGVIpRtx9bWLyj24Y/k6p4s4gQ3CqDGJauFJxt8M/LEx003d0i3klVqnN73qvK3w== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-transform-object-super@^7.16.7": version "7.16.7" @@ -890,12 +885,12 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-replace-supers" "^7.16.7" -"@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz#a1721f55b99b736511cb7e0152f61f17688f331f" - integrity sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw== +"@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.17.12.tgz#eb467cd9586ff5ff115a9880d6fdbd4a846b7766" + integrity sha512-6qW4rWo1cyCdq1FkYri7AHpauchbGLXpdwnYsfxFb+KtddHENfsY5JZb35xUwkK5opOLcJ3BNd2l7PhRYGlwIA== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-transform-property-literals@^7.16.7": version "7.16.7" @@ -905,11 +900,11 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-react-constant-elements@^7.14.5": - version "7.17.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.17.6.tgz#6cc273c2f612a6a50cb657e63ee1303e5e68d10a" - integrity sha512-OBv9VkyyKtsHZiHLoSfCn+h6yU7YKX8nrs32xUmOa1SRSk+t03FosB6fBZ0Yz4BpD1WV7l73Nsad+2Tz7APpqw== + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.17.12.tgz#cc580857696b6dd9e5e3d079e673d060a0657f37" + integrity sha512-maEkX2xs2STuv2Px8QuqxqjhV2LsFobT1elCgyU5704fcyTu9DyD/bJXxD/mrRiVyhpHweOQ00OJ5FKhHq9oEw== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-transform-react-display-name@^7.16.7": version "7.16.7" @@ -925,46 +920,47 @@ dependencies: "@babel/plugin-transform-react-jsx" "^7.16.7" -"@babel/plugin-transform-react-jsx@^7.16.7": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz#eac1565da176ccb1a715dae0b4609858808008c1" - integrity sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ== +"@babel/plugin-transform-react-jsx@^7.16.7", "@babel/plugin-transform-react-jsx@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.12.tgz#2aa20022709cd6a3f40b45d60603d5f269586dba" + integrity sha512-Lcaw8bxd1DKht3thfD4A12dqo1X16he1Lm8rIv8sTwjAYNInRS1qHa9aJoqvzpscItXvftKDCfaEQzwoVyXpEQ== dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-jsx" "^7.16.7" - "@babel/types" "^7.17.0" + "@babel/helper-plugin-utils" "^7.17.12" + "@babel/plugin-syntax-jsx" "^7.17.12" + "@babel/types" "^7.17.12" "@babel/plugin-transform-react-pure-annotations@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz#232bfd2f12eb551d6d7d01d13fe3f86b45eb9c67" - integrity sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA== + version "7.18.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.0.tgz#ef82c8e310913f3522462c9ac967d395092f1954" + integrity sha512-6+0IK6ouvqDn9bmEG7mEyF/pwlJXVj5lwydybpyyH3D0A7Hftk+NCTdYjnLNZksn261xaOV5ksmp20pQEmc2RQ== dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-transform-regenerator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz#9e7576dc476cb89ccc5096fff7af659243b4adeb" - integrity sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q== +"@babel/plugin-transform-regenerator@^7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.0.tgz#44274d655eb3f1af3f3a574ba819d3f48caf99d5" + integrity sha512-C8YdRw9uzx25HSIzwA7EM7YP0FhCe5wNvJbZzjVNHHPGVcDJ3Aie+qGYYdS1oVQgn+B3eAIJbWFLrJ4Jipv7nw== dependencies: - regenerator-transform "^0.14.2" + "@babel/helper-plugin-utils" "^7.17.12" + regenerator-transform "^0.15.0" -"@babel/plugin-transform-reserved-words@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz#1d798e078f7c5958eec952059c460b220a63f586" - integrity sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg== +"@babel/plugin-transform-reserved-words@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.17.12.tgz#7dbd349f3cdffba751e817cf40ca1386732f652f" + integrity sha512-1KYqwbJV3Co03NIi14uEHW8P50Md6KqFgt0FfpHdK6oyAHQVTosgPuPSiWud1HX0oYJ1hGRRlk0fP87jFpqXZA== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-transform-runtime@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz#0a2e08b5e2b2d95c4b1d3b3371a2180617455b70" - integrity sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A== +"@babel/plugin-transform-runtime@^7.18.2": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.2.tgz#04637de1e45ae8847ff14b9beead09c33d34374d" + integrity sha512-mr1ufuRMfS52ttq+1G1PD8OJNqgcTFjq3hwn8SZ5n1x1pBhi0E36rYMdTK0TsKtApJ4lDEdfXJwtGobQMHSMPg== dependencies: "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" babel-plugin-polyfill-corejs2 "^0.3.0" babel-plugin-polyfill-corejs3 "^0.5.0" babel-plugin-polyfill-regenerator "^0.3.0" @@ -977,12 +973,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-spread@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz#a303e2122f9f12e0105daeedd0f30fb197d8ff44" - integrity sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg== +"@babel/plugin-transform-spread@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.17.12.tgz#c112cad3064299f03ea32afed1d659223935d1f5" + integrity sha512-9pgmuQAtFi3lpNUstvG9nGfk9DkrdmWNp9KeKPFmuZCpEnxRzYlS8JgwPjYj+1AWDOSvoGN0H30p1cBOmT/Svg== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-transform-sticky-regex@^7.16.7": @@ -992,28 +988,28 @@ dependencies: "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-template-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz#f3d1c45d28967c8e80f53666fc9c3e50618217ab" - integrity sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA== +"@babel/plugin-transform-template-literals@^7.18.2": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.2.tgz#31ed6915721864847c48b656281d0098ea1add28" + integrity sha512-/cmuBVw9sZBGZVOMkpAEaVLwm4JmK2GZ1dFKOGGpMzEHWFmyZZ59lUU0PdRr8YNYeQdNzTDwuxP2X2gzydTc9g== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-transform-typeof-symbol@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz#9cdbe622582c21368bd482b660ba87d5545d4f7e" - integrity sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ== +"@babel/plugin-transform-typeof-symbol@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.17.12.tgz#0f12f57ac35e98b35b4ed34829948d42bd0e6889" + integrity sha512-Q8y+Jp7ZdtSPXCThB6zjQ74N3lj0f6TDh1Hnf5B+sYlzQ8i5Pjp8gW0My79iekSpT4WnI06blqP6DT0OmaXXmw== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-transform-typescript@^7.16.7": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz#591ce9b6b83504903fa9dd3652c357c2ba7a1ee0" - integrity sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ== +"@babel/plugin-transform-typescript@^7.17.12": + version "7.18.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.18.4.tgz#587eaf6a39edb8c06215e550dc939faeadd750bf" + integrity sha512-l4vHuSLUajptpHNEOUDEGsnpl9pfRLsN1XUoDQDD/YBuXTM+v37SHGS+c6n4jdcZy96QtuUuSvZYMLSSsjH8Mw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-typescript" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.18.0" + "@babel/helper-plugin-utils" "^7.17.12" + "@babel/plugin-syntax-typescript" "^7.17.12" "@babel/plugin-transform-unicode-escapes@^7.16.7": version "7.16.7" @@ -1030,37 +1026,38 @@ "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" -"@babel/preset-env@^7.15.6", "@babel/preset-env@^7.16.11": - version "7.16.11" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.11.tgz#5dd88fd885fae36f88fd7c8342475c9f0abe2982" - integrity sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g== +"@babel/preset-env@^7.15.6", "@babel/preset-env@^7.18.2": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.18.2.tgz#f47d3000a098617926e674c945d95a28cb90977a" + integrity sha512-PfpdxotV6afmXMU47S08F9ZKIm2bJIQ0YbAAtDfIENX7G1NUAXigLREh69CWDjtgUy7dYn7bsMzkgdtAlmS68Q== dependencies: - "@babel/compat-data" "^7.16.8" - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/compat-data" "^7.17.10" + "@babel/helper-compilation-targets" "^7.18.2" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/helper-validator-option" "^7.16.7" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.16.7" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.16.7" - "@babel/plugin-proposal-async-generator-functions" "^7.16.8" - "@babel/plugin-proposal-class-properties" "^7.16.7" - "@babel/plugin-proposal-class-static-block" "^7.16.7" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.17.12" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.17.12" + "@babel/plugin-proposal-async-generator-functions" "^7.17.12" + "@babel/plugin-proposal-class-properties" "^7.17.12" + "@babel/plugin-proposal-class-static-block" "^7.18.0" "@babel/plugin-proposal-dynamic-import" "^7.16.7" - "@babel/plugin-proposal-export-namespace-from" "^7.16.7" - "@babel/plugin-proposal-json-strings" "^7.16.7" - "@babel/plugin-proposal-logical-assignment-operators" "^7.16.7" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.7" + "@babel/plugin-proposal-export-namespace-from" "^7.17.12" + "@babel/plugin-proposal-json-strings" "^7.17.12" + "@babel/plugin-proposal-logical-assignment-operators" "^7.17.12" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.17.12" "@babel/plugin-proposal-numeric-separator" "^7.16.7" - "@babel/plugin-proposal-object-rest-spread" "^7.16.7" + "@babel/plugin-proposal-object-rest-spread" "^7.18.0" "@babel/plugin-proposal-optional-catch-binding" "^7.16.7" - "@babel/plugin-proposal-optional-chaining" "^7.16.7" - "@babel/plugin-proposal-private-methods" "^7.16.11" - "@babel/plugin-proposal-private-property-in-object" "^7.16.7" - "@babel/plugin-proposal-unicode-property-regex" "^7.16.7" + "@babel/plugin-proposal-optional-chaining" "^7.17.12" + "@babel/plugin-proposal-private-methods" "^7.17.12" + "@babel/plugin-proposal-private-property-in-object" "^7.17.12" + "@babel/plugin-proposal-unicode-property-regex" "^7.17.12" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-class-properties" "^7.12.13" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-import-assertions" "^7.17.12" "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" @@ -1070,44 +1067,44 @@ "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-transform-arrow-functions" "^7.16.7" - "@babel/plugin-transform-async-to-generator" "^7.16.8" + "@babel/plugin-transform-arrow-functions" "^7.17.12" + "@babel/plugin-transform-async-to-generator" "^7.17.12" "@babel/plugin-transform-block-scoped-functions" "^7.16.7" - "@babel/plugin-transform-block-scoping" "^7.16.7" - "@babel/plugin-transform-classes" "^7.16.7" - "@babel/plugin-transform-computed-properties" "^7.16.7" - "@babel/plugin-transform-destructuring" "^7.16.7" + "@babel/plugin-transform-block-scoping" "^7.17.12" + "@babel/plugin-transform-classes" "^7.17.12" + "@babel/plugin-transform-computed-properties" "^7.17.12" + "@babel/plugin-transform-destructuring" "^7.18.0" "@babel/plugin-transform-dotall-regex" "^7.16.7" - "@babel/plugin-transform-duplicate-keys" "^7.16.7" + "@babel/plugin-transform-duplicate-keys" "^7.17.12" "@babel/plugin-transform-exponentiation-operator" "^7.16.7" - "@babel/plugin-transform-for-of" "^7.16.7" + "@babel/plugin-transform-for-of" "^7.18.1" "@babel/plugin-transform-function-name" "^7.16.7" - "@babel/plugin-transform-literals" "^7.16.7" + "@babel/plugin-transform-literals" "^7.17.12" "@babel/plugin-transform-member-expression-literals" "^7.16.7" - "@babel/plugin-transform-modules-amd" "^7.16.7" - "@babel/plugin-transform-modules-commonjs" "^7.16.8" - "@babel/plugin-transform-modules-systemjs" "^7.16.7" - "@babel/plugin-transform-modules-umd" "^7.16.7" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.16.8" - "@babel/plugin-transform-new-target" "^7.16.7" + "@babel/plugin-transform-modules-amd" "^7.18.0" + "@babel/plugin-transform-modules-commonjs" "^7.18.2" + "@babel/plugin-transform-modules-systemjs" "^7.18.0" + "@babel/plugin-transform-modules-umd" "^7.18.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.17.12" + "@babel/plugin-transform-new-target" "^7.17.12" "@babel/plugin-transform-object-super" "^7.16.7" - "@babel/plugin-transform-parameters" "^7.16.7" + "@babel/plugin-transform-parameters" "^7.17.12" "@babel/plugin-transform-property-literals" "^7.16.7" - "@babel/plugin-transform-regenerator" "^7.16.7" - "@babel/plugin-transform-reserved-words" "^7.16.7" + "@babel/plugin-transform-regenerator" "^7.18.0" + "@babel/plugin-transform-reserved-words" "^7.17.12" "@babel/plugin-transform-shorthand-properties" "^7.16.7" - "@babel/plugin-transform-spread" "^7.16.7" + "@babel/plugin-transform-spread" "^7.17.12" "@babel/plugin-transform-sticky-regex" "^7.16.7" - "@babel/plugin-transform-template-literals" "^7.16.7" - "@babel/plugin-transform-typeof-symbol" "^7.16.7" + "@babel/plugin-transform-template-literals" "^7.18.2" + "@babel/plugin-transform-typeof-symbol" "^7.17.12" "@babel/plugin-transform-unicode-escapes" "^7.16.7" "@babel/plugin-transform-unicode-regex" "^7.16.7" "@babel/preset-modules" "^0.1.5" - "@babel/types" "^7.16.8" + "@babel/types" "^7.18.2" babel-plugin-polyfill-corejs2 "^0.3.0" babel-plugin-polyfill-corejs3 "^0.5.0" babel-plugin-polyfill-regenerator "^0.3.0" - core-js-compat "^3.20.2" + core-js-compat "^3.22.1" semver "^6.3.0" "@babel/preset-modules@^0.1.5": @@ -1121,42 +1118,49 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/preset-react@^7.14.5", "@babel/preset-react@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.16.7.tgz#4c18150491edc69c183ff818f9f2aecbe5d93852" - integrity sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA== +"@babel/preset-react@^7.14.5", "@babel/preset-react@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.17.12.tgz#62adbd2d1870c0de3893095757ed5b00b492ab3d" + integrity sha512-h5U+rwreXtZaRBEQhW1hOJLMq8XNJBQ/9oymXiCXTuT/0uOwpbT0gUt+sXeOqoXBgNuUKI7TaObVwoEyWkpFgA== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/helper-validator-option" "^7.16.7" "@babel/plugin-transform-react-display-name" "^7.16.7" - "@babel/plugin-transform-react-jsx" "^7.16.7" + "@babel/plugin-transform-react-jsx" "^7.17.12" "@babel/plugin-transform-react-jsx-development" "^7.16.7" "@babel/plugin-transform-react-pure-annotations" "^7.16.7" -"@babel/preset-typescript@^7.15.0", "@babel/preset-typescript@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz#ab114d68bb2020afc069cd51b37ff98a046a70b9" - integrity sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ== +"@babel/preset-typescript@^7.15.0", "@babel/preset-typescript@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.17.12.tgz#40269e0a0084d56fc5731b6c40febe1c9a4a3e8c" + integrity sha512-S1ViF8W2QwAKUGJXxP9NAfNaqGDdEBJKpYkxHf5Yy2C4NPPzXGeR3Lhk7G8xJaaLcFTRfNjVbtbVtm8Gb0mqvg== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/helper-validator-option" "^7.16.7" - "@babel/plugin-transform-typescript" "^7.16.7" + "@babel/plugin-transform-typescript" "^7.17.12" -"@babel/runtime-corejs3@^7.10.2", "@babel/runtime-corejs3@^7.17.8": - version "7.17.8" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.17.8.tgz#d7dd49fb812f29c61c59126da3792d8740d4e284" - integrity sha512-ZbYSUvoSF6dXZmMl/CYTMOvzIFnbGfv4W3SEHYgMvNsFTeLaF2gkGAF4K2ddmtSK4Emej+0aYcnSC6N5dPCXUQ== +"@babel/runtime-corejs3@^7.10.2", "@babel/runtime-corejs3@^7.18.3": + version "7.18.3" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.18.3.tgz#52f0241a31e0ec61a6187530af6227c2846bd60c" + integrity sha512-l4ddFwrc9rnR+EJsHsh+TJ4A35YqQz/UqcjtlX2ov53hlJYG5CxtQmNZxyajwDVmCxwy++rtvGU5HazCK4W41Q== dependencies: core-js-pure "^3.20.2" regenerator-runtime "^0.13.4" -"@babel/runtime@7.17.9", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.6", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.8", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4": +"@babel/runtime@7.17.9": version "7.17.9" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.9.tgz#d19fbf802d01a8cb6cf053a64e472d42c434ba72" integrity sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg== dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.6", "@babel/runtime@^7.16.3", "@babel/runtime@^7.18.3", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4": + version "7.18.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.3.tgz#c7b654b57f6f63cf7f8b418ac9ca04408c4579f4" + integrity sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.12.7", "@babel/template@^7.16.7", "@babel/template@^7.3.3": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" @@ -1166,26 +1170,26 @@ "@babel/parser" "^7.16.7" "@babel/types" "^7.16.7" -"@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.17.10", "@babel/traverse@^7.17.3", "@babel/traverse@^7.17.9", "@babel/traverse@^7.7.2": - version "7.17.10" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.10.tgz#1ee1a5ac39f4eac844e6cf855b35520e5eb6f8b5" - integrity sha512-VmbrTHQteIdUUQNTb+zE12SHS/xQVIShmBPhlNP12hD5poF2pbITW1Z4172d03HegaQWhLffdkRJYtAzp0AGcw== +"@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.16.8", "@babel/traverse@^7.18.0", "@babel/traverse@^7.18.2", "@babel/traverse@^7.7.2": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.2.tgz#b77a52604b5cc836a9e1e08dca01cba67a12d2e8" + integrity sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA== dependencies: "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.10" - "@babel/helper-environment-visitor" "^7.16.7" + "@babel/generator" "^7.18.2" + "@babel/helper-environment-visitor" "^7.18.2" "@babel/helper-function-name" "^7.17.9" "@babel/helper-hoist-variables" "^7.16.7" "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.17.10" - "@babel/types" "^7.17.10" + "@babel/parser" "^7.18.0" + "@babel/types" "^7.18.2" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.12.7", "@babel/types@^7.15.6", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.17.10", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": - version "7.17.10" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.10.tgz#d35d7b4467e439fcf06d195f8100e0fea7fc82c4" - integrity sha512-9O26jG0mBYfGkUYCYZRnBwbVLd1UZOICEr2Em6InB6jVfsAv1GKgwXHmrSg+WFWDmeKTA6vyTZiN8tCSM5Oo3A== +"@babel/types@^7.0.0", "@babel/types@^7.12.7", "@babel/types@^7.15.6", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.17.12", "@babel/types@^7.18.0", "@babel/types@^7.18.2", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": + version "7.18.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.4.tgz#27eae9b9fd18e9dccc3f9d6ad051336f307be354" + integrity sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw== dependencies: "@babel/helper-validator-identifier" "^7.16.7" to-fast-properties "^2.0.0" @@ -1195,14 +1199,19 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + "@commitlint/cli@^16.0.1": - version "16.2.4" - resolved "https://registry.yarnpkg.com/@commitlint/cli/-/cli-16.2.4.tgz#f22707918d08c27a19779798788a7c793f1d38e6" - integrity sha512-rbvqvz9JI+uiKxV2nH65BtSU01fsADd3bxe9fWtO3rM0c+CI/H9FfzKkDLvSRmXjvk1G2/wXlCGeqO9IBT4X9g== + version "16.3.0" + resolved "https://registry.yarnpkg.com/@commitlint/cli/-/cli-16.3.0.tgz#5689f5c2abbb7880d5ff13329251e5648a784b16" + integrity sha512-P+kvONlfsuTMnxSwWE1H+ZcPMY3STFaHb2kAacsqoIkNx66O0T7sTpBxpxkMrFPyhkJiLJnJWMhk4bbvYD3BMA== dependencies: "@commitlint/format" "^16.2.1" "@commitlint/lint" "^16.2.4" - "@commitlint/load" "^16.2.4" + "@commitlint/load" "^16.3.0" "@commitlint/read" "^16.2.1" "@commitlint/types" "^16.2.1" lodash "^4.17.19" @@ -1225,6 +1234,14 @@ "@commitlint/types" "^16.2.1" ajv "^6.12.6" +"@commitlint/config-validator@^17.0.0": + version "17.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/config-validator/-/config-validator-17.0.0.tgz#49ab09f3ca0ac3449e79ea389cb4942423162ac0" + integrity sha512-78IQjoZWR4kDHp/U5y17euEWzswJpPkA9TDL5F6oZZZaLIEreWzrDZD5PWtM8MsSRl/K2LDU/UrzYju2bKLMpA== + dependencies: + "@commitlint/types" "^17.0.0" + ajv "^6.12.6" + "@commitlint/ensure@^16.2.1": version "16.2.1" resolved "https://registry.yarnpkg.com/@commitlint/ensure/-/ensure-16.2.1.tgz#0fc538173f95c1eb2694eeedb79cab478347f16f" @@ -1238,6 +1255,11 @@ resolved "https://registry.yarnpkg.com/@commitlint/execute-rule/-/execute-rule-16.2.1.tgz#60be73be4b9af97a41546e7ce59fdd33787c65f8" integrity sha512-oSls82fmUTLM6cl5V3epdVo4gHhbmBFvCvQGHBRdQ50H/690Uq1Dyd7hXMuKITCIdcnr9umyDkr8r5C6HZDF3g== +"@commitlint/execute-rule@^17.0.0": + version "17.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/execute-rule/-/execute-rule-17.0.0.tgz#186e9261fd36733922ae617497888c4bdb6e5c92" + integrity sha512-nVjL/w/zuqjCqSJm8UfpNaw66V9WzuJtQvEnCrK4jDw6qKTmZB+1JQ8m6BQVZbNBcwfYdDNKnhIhqI0Rk7lgpQ== + "@commitlint/format@^16.2.1": version "16.2.1" resolved "https://registry.yarnpkg.com/@commitlint/format/-/format-16.2.1.tgz#6e673f710c799be78e68b2682323e04f75080d07" @@ -1264,10 +1286,27 @@ "@commitlint/rules" "^16.2.4" "@commitlint/types" "^16.2.1" -"@commitlint/load@>6.1.1", "@commitlint/load@^16.2.4": - version "16.2.4" - resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-16.2.4.tgz#32c9f4c6538b21cf48cf40266312bb1adb65f435" - integrity sha512-HjANm3/29ROV+zt4yfaY/K6gpr9Dbzgtlp0kSwZGW0poDXlD/yqVYgPQ6JolJzZii5FUz5R4yVLC15hVL/w60w== +"@commitlint/load@>6.1.1": + version "17.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-17.0.0.tgz#0bbefe6d8b99276714c5ea8ef32de2bd2f082698" + integrity sha512-XaiHF4yWQOPAI0O6wXvk+NYLtJn/Xb7jgZEeKd4C1ZWd7vR7u8z5h0PkWxSr0uLZGQsElGxv3fiZ32C5+q6M8w== + dependencies: + "@commitlint/config-validator" "^17.0.0" + "@commitlint/execute-rule" "^17.0.0" + "@commitlint/resolve-extends" "^17.0.0" + "@commitlint/types" "^17.0.0" + "@types/node" ">=12" + chalk "^4.1.0" + cosmiconfig "^7.0.0" + cosmiconfig-typescript-loader "^2.0.0" + lodash "^4.17.19" + resolve-from "^5.0.0" + typescript "^4.6.4" + +"@commitlint/load@^16.3.0": + version "16.3.0" + resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-16.3.0.tgz#e674ccc9edefd64a2d8b82d175de81ec3bb70eca" + integrity sha512-3tykjV/iwbkv2FU9DG+NZ/JqmP0Nm3b7aDwgCNQhhKV5P74JAuByULkafnhn+zsFGypG1qMtI5u+BZoa9APm0A== dependencies: "@commitlint/config-validator" "^16.2.1" "@commitlint/execute-rule" "^16.2.1" @@ -1276,7 +1315,7 @@ "@types/node" ">=12" chalk "^4.0.0" cosmiconfig "^7.0.0" - cosmiconfig-typescript-loader "^1.0.0" + cosmiconfig-typescript-loader "^2.0.0" lodash "^4.17.19" resolve-from "^5.0.0" typescript "^4.4.3" @@ -1317,6 +1356,18 @@ resolve-from "^5.0.0" resolve-global "^1.0.0" +"@commitlint/resolve-extends@^17.0.0": + version "17.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/resolve-extends/-/resolve-extends-17.0.0.tgz#3a40ee08184b984acf475ebc962641f435e3a639" + integrity sha512-wi60WiJmwaQ7lzMXK8Vbc18Hq9tE2j/6iv2AFfPUGV7fvfY6Sf1iNKuUHirSqR0fquUyufIXe4y/K9A6LVIIvw== + dependencies: + "@commitlint/config-validator" "^17.0.0" + "@commitlint/types" "^17.0.0" + import-fresh "^3.0.0" + lodash "^4.17.19" + resolve-from "^5.0.0" + resolve-global "^1.0.0" + "@commitlint/rules@^16.2.4": version "16.2.4" resolved "https://registry.yarnpkg.com/@commitlint/rules/-/rules-16.2.4.tgz#c2fbbf20d9d0e8fcf25690c88a27750d4a3e867b" @@ -1347,238 +1398,275 @@ dependencies: chalk "^4.0.0" -"@cspell/cspell-bundled-dicts@^5.12.3": - version "5.12.3" - resolved "https://registry.yarnpkg.com/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-5.12.3.tgz#d4ae61d03c6f991f4b03b03ee718830522bf74d5" - integrity sha512-f3kyUHYxyGqNt2DTphpmP8hr38YTL48wr4Dq7pZDbqDjLkerq9T7ufX2CZ2OfydBEdIgduX2UXwiow7IfdwY/A== - dependencies: - "@cspell/dict-ada" "^1.1.2" - "@cspell/dict-aws" "^1.0.14" - "@cspell/dict-bash" "^1.0.15" - "@cspell/dict-companies" "^1.0.40" - "@cspell/dict-cpp" "^1.1.40" - "@cspell/dict-cryptocurrencies" "^1.0.10" - "@cspell/dict-csharp" "^1.0.11" - "@cspell/dict-css" "^1.0.12" - "@cspell/dict-django" "^1.0.26" - "@cspell/dict-dotnet" "^1.0.31" - "@cspell/dict-elixir" "^1.0.25" +"@commitlint/types@^17.0.0": + version "17.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/types/-/types-17.0.0.tgz#3b4604c1a0f06c340ce976e6c6903d4f56e3e690" + integrity sha512-hBAw6U+SkAT5h47zDMeOu3HSiD0SODw4Aq7rRNh1ceUmL7GyLKYhPbUvlRWqZ65XjBLPHZhFyQlRaPNz8qvUyQ== + dependencies: + chalk "^4.1.0" + +"@cspell/cspell-bundled-dicts@^5.21.2": + version "5.21.2" + resolved "https://registry.yarnpkg.com/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-5.21.2.tgz#2254c392e2a617b5ffe591a438840028fe8dc4b8" + integrity sha512-Y5TU6wV/H+RV1VOB32MowiKofBsEZId4x4ReWCyw4KUtJegeljajCfhHwiQaZuvA69E13cJnOMDwi9qozj4kjw== + dependencies: + "@cspell/dict-ada" "^2.0.0" + "@cspell/dict-aws" "^2.0.0" + "@cspell/dict-bash" "^2.0.2" + "@cspell/dict-companies" "^2.0.4" + "@cspell/dict-cpp" "^3.1.0" + "@cspell/dict-cryptocurrencies" "^2.0.0" + "@cspell/dict-csharp" "^3.0.1" + "@cspell/dict-css" "^2.0.0" + "@cspell/dict-dart" "^1.1.0" + "@cspell/dict-django" "^2.0.0" + "@cspell/dict-dotnet" "^2.0.1" + "@cspell/dict-elixir" "^2.0.1" "@cspell/dict-en-gb" "^1.1.33" - "@cspell/dict-en_us" "^2.1.1" - "@cspell/dict-filetypes" "^1.1.8" - "@cspell/dict-fonts" "^1.0.14" - "@cspell/dict-fullstack" "^1.0.38" - "@cspell/dict-golang" "^1.1.24" - "@cspell/dict-haskell" "^1.0.13" - "@cspell/dict-html" "^1.1.9" - "@cspell/dict-html-symbol-entities" "^1.0.23" - "@cspell/dict-java" "^1.0.23" - "@cspell/dict-latex" "^1.0.25" - "@cspell/dict-lorem-ipsum" "^1.0.22" - "@cspell/dict-lua" "^1.0.16" - "@cspell/dict-node" "^1.0.12" - "@cspell/dict-npm" "^1.0.16" - "@cspell/dict-php" "^1.0.24" - "@cspell/dict-powershell" "^1.0.18" - "@cspell/dict-public-licenses" "^1.0.3" - "@cspell/dict-python" "^2.0.3" - "@cspell/dict-ruby" "^1.0.14" - "@cspell/dict-rust" "^1.0.23" - "@cspell/dict-scala" "^1.0.21" - "@cspell/dict-software-terms" "^1.0.47" - "@cspell/dict-typescript" "^1.0.19" - -"@cspell/cspell-types@^5.12.3": - version "5.12.3" - resolved "https://registry.yarnpkg.com/@cspell/cspell-types/-/cspell-types-5.12.3.tgz#bfbebfa29d2f280d99785fdbc3e97bea60b47e5b" - integrity sha512-4l43apk3QGMkpszirKjrRGWmzZVuCyvoa0+kgWCl28dviLKsVonop8liBJaBzjmZbdpe27IKpMrNtj0fOus+fw== - -"@cspell/dict-ada@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@cspell/dict-ada/-/dict-ada-1.1.2.tgz#89556226c1d5f856ce1f7afa85543b04fa477092" - integrity sha512-UDrcYcKIVyXDz5mInJabRNQpJoehjBFvja5W+GQyu9pGcx3BS3cAU8mWENstGR0Qc/iFTxB010qwF8F3cHA/aA== - -"@cspell/dict-aws@^1.0.14": - version "1.0.14" - resolved "https://registry.yarnpkg.com/@cspell/dict-aws/-/dict-aws-1.0.14.tgz#beddede1053ce3622400e36c65da9fd2954e939d" - integrity sha512-K21CfB4ZpKYwwDQiPfic2zJA/uxkbsd4IQGejEvDAhE3z8wBs6g6BwwqdVO767M9NgZqc021yAVpr79N5pWe3w== - -"@cspell/dict-bash@^1.0.15": - version "1.0.15" - resolved "https://registry.yarnpkg.com/@cspell/dict-bash/-/dict-bash-1.0.15.tgz#ac70ab1572d9b8d0e3cf7777383b6caa2daad022" - integrity sha512-rY5Bq4RWTgJTioG8vqFbCmnalc/UEM+iBuAZBYvBfT3nU/6SN00Zjyvlh823ir2ODkUryT29CwRYwXcPnuM04w== - -"@cspell/dict-companies@^1.0.40": - version "1.0.40" - resolved "https://registry.yarnpkg.com/@cspell/dict-companies/-/dict-companies-1.0.40.tgz#edd7f47fc683dfa1b02cd48fb12ad732d2eece61" - integrity sha512-Aw07qiTroqSST2P5joSrC4uOA05zTXzI2wMb+me3q4Davv1D9sCkzXY0TGoC2vzhNv5ooemRi9KATGaBSdU1sw== - -"@cspell/dict-cpp@^1.1.40": - version "1.1.40" - resolved "https://registry.yarnpkg.com/@cspell/dict-cpp/-/dict-cpp-1.1.40.tgz#f9a859e19d31b83f07a106e4c3c8720a2d93595b" - integrity sha512-sscfB3woNDNj60/yGXAdwNtIRWZ89y35xnIaJVDMk5TPMMpaDvuk0a34iOPIq0g4V+Y8e3RyAg71SH6ADwSjGw== - -"@cspell/dict-cryptocurrencies@^1.0.10": - version "1.0.10" - resolved "https://registry.yarnpkg.com/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-1.0.10.tgz#04426fdfee8752818b375686d34a154b2fb40c7d" - integrity sha512-47ABvDJOkaST/rXipNMfNvneHUzASvmL6K/CbOFpYKfsd0x23Jc9k1yaOC7JAm82XSC/8a7+3Yu+Fk2jVJNnsA== + "@cspell/dict-en_us" "^2.2.5" + "@cspell/dict-filetypes" "^2.0.1" + "@cspell/dict-fonts" "^2.0.0" + "@cspell/dict-fullstack" "^2.0.5" + "@cspell/dict-git" "^1.0.1" + "@cspell/dict-golang" "^3.0.1" + "@cspell/dict-haskell" "^2.0.0" + "@cspell/dict-html" "^3.0.1" + "@cspell/dict-html-symbol-entities" "^3.0.0" + "@cspell/dict-java" "^2.0.0" + "@cspell/dict-latex" "^2.0.3" + "@cspell/dict-lorem-ipsum" "^2.0.0" + "@cspell/dict-lua" "^2.0.0" + "@cspell/dict-node" "^2.0.1" + "@cspell/dict-npm" "^2.0.3" + "@cspell/dict-php" "^2.0.0" + "@cspell/dict-powershell" "^2.0.0" + "@cspell/dict-public-licenses" "^1.0.4" + "@cspell/dict-python" "^3.0.5" + "@cspell/dict-r" "^1.0.2" + "@cspell/dict-ruby" "^2.0.1" + "@cspell/dict-rust" "^2.0.0" + "@cspell/dict-scala" "^2.0.0" + "@cspell/dict-software-terms" "^2.1.7" + "@cspell/dict-swift" "^1.0.2" + "@cspell/dict-typescript" "^2.0.0" + "@cspell/dict-vue" "^2.0.2" + +"@cspell/cspell-pipe@^5.21.2": + version "5.21.2" + resolved "https://registry.yarnpkg.com/@cspell/cspell-pipe/-/cspell-pipe-5.21.2.tgz#7adfbc66426ee28549fd72a39deec7b98a76b320" + integrity sha512-MN1SXeqqurWYNknbUMPHRFyTvURbO53/1Aw3zEoCeVUSiGbD5rrb1N+t0YDbOphWrkkrJAZk82/2ZBJ2USE/vg== + +"@cspell/cspell-types@^5.21.2": + version "5.21.2" + resolved "https://registry.yarnpkg.com/@cspell/cspell-types/-/cspell-types-5.21.2.tgz#899b4c41b59ca6e0b81c12f1973fda63535e6f3e" + integrity sha512-g2h4qNR6C53IcSM3KR0DZ9gsqp+2FyKD371htJOmSJGmWb4s45QY0hsPr12A2J8/bT+E3uMtHn9KxJeQ7t0SzA== + +"@cspell/dict-ada@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-ada/-/dict-ada-2.0.0.tgz#5d31967cbd7a0d12f4b4de3fd5b09e59239cf78b" + integrity sha512-4gfJEYXVwz6IN2LBaT6QoUV4pqaR35i0z0u9O684vLuVczvNJIHa4vNaSEFBr9d6xxncUyqstgP9P73ajJjh9A== -"@cspell/dict-csharp@^1.0.11": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@cspell/dict-csharp/-/dict-csharp-1.0.11.tgz#cacdf477a31ca8326c2c91bee0b42b9f6b3c4a7c" - integrity sha512-nub+ZCiTgmT87O+swI+FIAzNwaZPWUGckJU4GN402wBq420V+F4ZFqNV7dVALJrGaWH7LvADRtJxi6cZVHJKeA== +"@cspell/dict-aws@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-aws/-/dict-aws-2.0.0.tgz#9af72af4e59e96029dd4335271d87784843cb7dd" + integrity sha512-NKz7pDZ7pwj/b33i3f4WLpC1rOOUMmENwYgftxU+giU2YBeKM2wZbMTSEIzsrel56r0UlQYmdIVlP/B4nnVaoQ== -"@cspell/dict-css@^1.0.12": - version "1.0.12" - resolved "https://registry.yarnpkg.com/@cspell/dict-css/-/dict-css-1.0.12.tgz#ec01cec102c8b128aad5e29c97dfb7a982887e12" - integrity sha512-K6yuxej7n454O7dwKG6lHacHrAOMZ0PhMEbmV6qH2JH0U4TtWXfBASYugHvXZCDDx1UObpiJP+3tQJiBqfGpHA== +"@cspell/dict-bash@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@cspell/dict-bash/-/dict-bash-2.0.3.tgz#a54d6b8899569e348fcd33c95daaeef42075d75b" + integrity sha512-iw78lmxm49q2LhHTQCSu9zs85E8Sm6ui82OvxajU9rdhckFzZoj/KCQi9P0gFuL+w3WmQObHqdH2/sxK4oi2wA== -"@cspell/dict-django@^1.0.26": - version "1.0.26" - resolved "https://registry.yarnpkg.com/@cspell/dict-django/-/dict-django-1.0.26.tgz#b97ce0112fbe8c3c3ada0387c68971b5e27483ab" - integrity sha512-mn9bd7Et1L2zuibc08GVHTiD2Go3/hdjyX5KLukXDklBkq06r+tb0OtKtf1zKodtFDTIaYekGADhNhA6AnKLkg== +"@cspell/dict-companies@^2.0.4": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@cspell/dict-companies/-/dict-companies-2.0.5.tgz#0365e74a55b43d4493d44ea1071998bab16d6227" + integrity sha512-H8+LU+gDUeJ8RcV1kMSIiHa5PE/8tYyA2tg/s6ssHtsgsJ206I+cRFV8yAlu0mUUCXD617+KKXmclZ0eZ7ku4w== + +"@cspell/dict-cpp@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-cpp/-/dict-cpp-3.1.0.tgz#0b2983dbd942ae77c7cf0b349786344a1ba7974e" + integrity sha512-lav99zUQ+iPq6dkQRnTN0+KE9th0UG6Nwl34afyEGJ8CN5Dcq/RJjCVvOkLw6vPvs505xrvQcZW1huftQK8WVg== -"@cspell/dict-dotnet@^1.0.31": - version "1.0.32" - resolved "https://registry.yarnpkg.com/@cspell/dict-dotnet/-/dict-dotnet-1.0.32.tgz#412af0bf1f65c5902c8ef8a4f1decae2892790e2" - integrity sha512-9H9vXrgJB4KF8xsyTToXO53cXD33iyfrpT4mhCds+YLUw3P3x3E9myszgJzshnrxYBvQZ+QMII57Qr6SjZVk4Q== +"@cspell/dict-cryptocurrencies@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-2.0.0.tgz#a74eecb42a46a96d08b6613fdb5c554529d3afff" + integrity sha512-nREysmmfOp7L2YCRAUufQahwD5/Punzb5AZ6eyg4zUamdRWHgBFphb5/9h2flt1vgdUfhc6hZcML21Ci7iXjaA== -"@cspell/dict-elixir@^1.0.25": - version "1.0.25" - resolved "https://registry.yarnpkg.com/@cspell/dict-elixir/-/dict-elixir-1.0.25.tgz#bec4fd754c99f646e553184df12df88b54da1c04" - integrity sha512-ZmawoBYjM5k+8fNudRMkK+PpHjhyAFAZt2rUu1EGj2rbCvE3Fn2lhRbDjbreN7nWRvcLRTW+xuPXtKP11X0ahQ== +"@cspell/dict-csharp@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@cspell/dict-csharp/-/dict-csharp-3.0.1.tgz#94a673e02bb7cc03c25bc699bc1b5bd786c2c5fd" + integrity sha512-xkfQu03F388w4sdVQSSjrVMkxAxpTYB2yW7nw0XYtTjl3L/jBgvTr/j1BTjdFbQhdNf10Lg0Ak1kXOjmHodVqA== + +"@cspell/dict-css@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-css/-/dict-css-2.0.0.tgz#91dca013f16b51144eaea160e144b830f2dad027" + integrity sha512-MrFyswFHnPh4H0u6IlV4eHy+ZCUrrHzeL161LyTOqCvaKpbZavMgNYXzZqTF9xafO0iLgwKrl+Gkclu1KVBg0Q== + +"@cspell/dict-dart@^1.1.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@cspell/dict-dart/-/dict-dart-1.1.1.tgz#d4da9cf72e5df369b6d9ebe588f9c1474adf3556" + integrity sha512-XBOCpezXrgFN18kGEwqMpTUGZdw4BjCoJrNOo6qBdcdZySCrEHLwELraLOkcSba2kM4stmTp0t59FkwtP8TKOA== + +"@cspell/dict-django@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-django/-/dict-django-2.0.0.tgz#a5f5f693a686e5873f9dfb547ee3b3142ef760b1" + integrity sha512-GkJdJv6cmzrKcmq2/oxTXjKF5uv71r4eTqnFmgPbNBW1t+G4VYpzOf0QrVQrhx2RC4DdW5XfcTf+iS0FxHOTmw== + +"@cspell/dict-dotnet@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@cspell/dict-dotnet/-/dict-dotnet-2.0.1.tgz#8ef56df758b63f0a2ba4d8681a427a6861ed34d5" + integrity sha512-b1n4crJRW0WZVf9Gp/52j/tDtjYiZ3N81fIyfqPlBrjsh/5AivfA697DYwQ2mr8ngNX7RsqRtYNQjealA1rEnQ== + +"@cspell/dict-elixir@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@cspell/dict-elixir/-/dict-elixir-2.0.1.tgz#1a9b422215b5edabb84568cfa5c0c70bc164a2ce" + integrity sha512-eTTTxZt1FqGkM780yFDxsGHvTbWqvlK8YISSccK8FyrB6ULW+uflQlNS5AnWg3uWKC48b7pQott+odYCsPJ+Ow== "@cspell/dict-en-gb@^1.1.33": version "1.1.33" resolved "https://registry.yarnpkg.com/@cspell/dict-en-gb/-/dict-en-gb-1.1.33.tgz#7f1fd90fc364a5cb77111b5438fc9fcf9cc6da0e" integrity sha512-tKSSUf9BJEV+GJQAYGw5e+ouhEe2ZXE620S7BLKe3ZmpnjlNG9JqlnaBhkIMxKnNFkLY2BP/EARzw31AZnOv4g== -"@cspell/dict-en_us@^2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@cspell/dict-en_us/-/dict-en_us-2.1.1.tgz#3db0fec45a821ad66747e42d303d2448d37a158e" - integrity sha512-7kHOqve9DVFsb1e/wKME3CZhj48zOqvXNaA1Cd82ZkaHf3aL7pUBx3cxI7Xopj/dcK1ZkhUKh+2nBxPIWIibNg== +"@cspell/dict-en_us@^2.2.5": + version "2.2.5" + resolved "https://registry.yarnpkg.com/@cspell/dict-en_us/-/dict-en_us-2.2.5.tgz#7a1c325d54a7c9b8171da6e61f095ad34395ff68" + integrity sha512-gRHem02ZY83AQUTYBxtiVNmtM6gWFCJKumRoAKLj7vWYelmNLcCBsMA3BOOOJ7cZNKCI04lDEdh0u2f2akKZtQ== -"@cspell/dict-filetypes@^1.1.8": - version "1.1.8" - resolved "https://registry.yarnpkg.com/@cspell/dict-filetypes/-/dict-filetypes-1.1.8.tgz#c161ab48667b6539cbc91a70ff0b037fa436a64e" - integrity sha512-EllahNkhzvLWo0ptwu0l3oEeAJOQSUpZnDfnKRIh6mJVehuSovNHwA9vrdZ8jBUjuqcfaN2e7c32zN0D/qvWJQ== +"@cspell/dict-filetypes@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@cspell/dict-filetypes/-/dict-filetypes-2.0.1.tgz#a77467dad8fee31c28d623f85a15ce6fca3e2fdc" + integrity sha512-bQ7K3U/3hKO2lpQjObf0veNP/n50qk5CVezSwApMBckf/sAVvDTR1RGAvYdr+vdQnkdQrk6wYmhbshXi0sLDVg== -"@cspell/dict-fonts@^1.0.14": - version "1.0.14" - resolved "https://registry.yarnpkg.com/@cspell/dict-fonts/-/dict-fonts-1.0.14.tgz#7b18129910d30bd23cd9187d0c0009dfc3fef4ba" - integrity sha512-VhIX+FVYAnqQrOuoFEtya6+H72J82cIicz9QddgknsTqZQ3dvgp6lmVnsQXPM3EnzA8n1peTGpLDwHzT7ociLA== +"@cspell/dict-fonts@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-fonts/-/dict-fonts-2.0.0.tgz#76e7781b44cdda6933144e15cba80e978c29bd15" + integrity sha512-AgkTalphfDPtKFPYmEExDcj8rRCh86xlOSXco8tehOEkYVYbksOk9XH0YVH34RFpy93YBd2nnVGLgyGVwagcPw== -"@cspell/dict-fullstack@^1.0.38": - version "1.0.38" - resolved "https://registry.yarnpkg.com/@cspell/dict-fullstack/-/dict-fullstack-1.0.38.tgz#a26d9db5fdc51e8743f57e51b0fa44a1d4791cf6" - integrity sha512-4reajWiUxwWrSyZaWm9e15kaWzjYcZbzlB+CVcxE1+0NqdIoqlEESDhbnrAjKPSq+jspKtes7nQ1CdZEOj1gCA== - -"@cspell/dict-golang@^1.1.24": - version "1.1.24" - resolved "https://registry.yarnpkg.com/@cspell/dict-golang/-/dict-golang-1.1.24.tgz#3830812aec816eca46a6d793fcc7710c09d4f5b9" - integrity sha512-qq3Cjnx2U1jpeWAGJL1GL0ylEhUMqyaR36Xij6Y6Aq4bViCRp+HRRqk0x5/IHHbOrti45h3yy7ii1itRFo+Xkg== - -"@cspell/dict-haskell@^1.0.13": - version "1.0.13" - resolved "https://registry.yarnpkg.com/@cspell/dict-haskell/-/dict-haskell-1.0.13.tgz#bd159ef474ef427757dd4bc6a66cda977946c927" - integrity sha512-kvl8T84cnYRPpND/P3D86P6WRSqebsbk0FnMfy27zo15L5MLAb3d3MOiT1kW3vEWfQgzUD7uddX/vUiuroQ8TA== - -"@cspell/dict-html-symbol-entities@^1.0.23": - version "1.0.23" - resolved "https://registry.yarnpkg.com/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-1.0.23.tgz#0efbdbc7712c9fbe545e14acac637226ac948f2d" - integrity sha512-PV0UBgcBFbBLf/m1wfkVMM8w96kvfHoiCGLWO6BR3Q9v70IXoE4ae0+T+f0CkxcEkacMqEQk/I7vuE9MzrjaNw== - -"@cspell/dict-html@^1.1.9": - version "1.1.9" - resolved "https://registry.yarnpkg.com/@cspell/dict-html/-/dict-html-1.1.9.tgz#e506ca550ffcdad820ba0aa157a48be869f23bf2" - integrity sha512-vvnYia0tyIS5Fdoz+gEQm77MGZZE66kOJjuNpIYyRHCXFAhWdYz3SmkRm6YKJSWSvuO+WBJYTKDvkOxSh3Fx/w== - -"@cspell/dict-java@^1.0.23": - version "1.0.23" - resolved "https://registry.yarnpkg.com/@cspell/dict-java/-/dict-java-1.0.23.tgz#ec95ff2f2c34d5e8e08ba817980b37e387e608cb" - integrity sha512-LcOg9srYLDoNGd8n3kbfDBlZD+LOC9IVcnFCdua1b/luCHNVmlgBx7e677qPu7olpMYOD5TQIVW2OmM1+/6MFA== - -"@cspell/dict-latex@^1.0.25": - version "1.0.25" - resolved "https://registry.yarnpkg.com/@cspell/dict-latex/-/dict-latex-1.0.25.tgz#6ecf5b8b8fdf46cb8a0f070052dd687e25089e59" - integrity sha512-cEgg91Migqcp1SdVV7dUeMxbPDhxdNo6Fgq2eygAXQjIOFK520FFvh/qxyBvW90qdZbIRoU2AJpchyHfGuwZFA== - -"@cspell/dict-lorem-ipsum@^1.0.22": - version "1.0.22" - resolved "https://registry.yarnpkg.com/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-1.0.22.tgz#a89f53dadda7d5bfdb978ab61f19d74d2fb69eab" - integrity sha512-yqzspR+2ADeAGUxLTfZ4pXvPl7FmkENMRcGDECmddkOiuEwBCWMZdMP5fng9B0Q6j91hQ8w9CLvJKBz10TqNYg== - -"@cspell/dict-lua@^1.0.16": - version "1.0.16" - resolved "https://registry.yarnpkg.com/@cspell/dict-lua/-/dict-lua-1.0.16.tgz#c0ca43628f8927fc10731fd27cd9ee0af651bf6a" - integrity sha512-YiHDt8kmHJ8nSBy0tHzaxiuitYp+oJ66ffCYuFWTNB3//Y0SI4OGHU3omLsQVeXIfCeVrO4DrVvRDoCls9B5zQ== - -"@cspell/dict-node@^1.0.12": - version "1.0.12" - resolved "https://registry.yarnpkg.com/@cspell/dict-node/-/dict-node-1.0.12.tgz#a7236be30340ff8fe365f62c8d13121fdbe7f51c" - integrity sha512-RPNn/7CSkflAWk0sbSoOkg0ORrgBARUjOW3QjB11KwV1gSu8f5W/ij/S50uIXtlrfoBLqd4OyE04jyON+g/Xfg== +"@cspell/dict-fullstack@^2.0.5": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@cspell/dict-fullstack/-/dict-fullstack-2.0.6.tgz#0bec93306cba070ed6aa0b619d8080c86310ab5d" + integrity sha512-R2E2xvbHvvRwwurxfpBJDRIJjXBMfEPF5WNV3LTOEMRqkZtoYCeJK9aqc8LHlmJMtAbnN1cx//BCDIyTJ0rO0A== -"@cspell/dict-npm@^1.0.16": - version "1.0.16" - resolved "https://registry.yarnpkg.com/@cspell/dict-npm/-/dict-npm-1.0.16.tgz#86870686cd0af6354a206ab297872db1d84e9c1b" - integrity sha512-RwkuZGcYBxL3Yux3cSG/IOWGlQ1e9HLCpHeyMtTVGYKAIkFAVUnGrz20l16/Q7zUG7IEktBz5O42kAozrEnqMQ== +"@cspell/dict-git@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@cspell/dict-git/-/dict-git-1.0.1.tgz#9de5ab2532abcdc8b10bd83ccb1f5e5dae0b6067" + integrity sha512-Rk+eTof/9inF11lvxmkCRK+gODatA3qai8kSASv6OG/JfPvpj7fTHErx/rdgPw/LOTDUafnoTjTYmj7B2MOQXg== -"@cspell/dict-php@^1.0.24": - version "1.0.24" - resolved "https://registry.yarnpkg.com/@cspell/dict-php/-/dict-php-1.0.24.tgz#40c15a4c5e1e2deba28841e2b498595b13f0ff88" - integrity sha512-vHCqETX1idT9tN1plkxUFnXMIHjbbrNOINZh1PYSvVlBrOdahSaL/g6dOJZC5QTaaidoU4WXUlgnNb/7JN4Plg== +"@cspell/dict-golang@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@cspell/dict-golang/-/dict-golang-3.0.1.tgz#acde95eb340c4512d132586a8326b1b3d971c0f7" + integrity sha512-0KNfXTbxHW2l8iVjxeOf+KFv9Qrw3z5cyKnkuYJWlBTSB5KcUBfeKCb4fsds26VdANqiy6U91b4gDx5kNEmBjQ== -"@cspell/dict-powershell@^1.0.18": - version "1.0.19" - resolved "https://registry.yarnpkg.com/@cspell/dict-powershell/-/dict-powershell-1.0.19.tgz#b50d14b3b20e33f86b80318ccd7ef986ecba2549" - integrity sha512-zF/raM/lkhXeHf4I43OtK0gP9rBeEJFArscTVwLWOCIvNk21MJcNoTYoaGw+c056+Q+hJL0psGLO7QN+mxYH1A== +"@cspell/dict-haskell@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-haskell/-/dict-haskell-2.0.0.tgz#9e7e58eba2b4633221650dcdcc43f73588b48119" + integrity sha512-cjX1Br+gSWqtcmJD/IMHz1UoP3pUaKIIKy/JfhEs7ANtRt6hhfEKe9dl2kQzDkkKt4pXol+YgdYxL/sVc/nLgQ== -"@cspell/dict-public-licenses@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@cspell/dict-public-licenses/-/dict-public-licenses-1.0.3.tgz#d02ee79f7b7aecd696695e5aba135e6553e154ec" - integrity sha512-sXjxOHJ9Q4rZvE1UbwpwJQ8EXO3fadKBjJIWmz0z+dZAbvTrmz5Ln1Ef9ruJvLPfwAps8m3TCV6Diz60RAQqHg== +"@cspell/dict-html-symbol-entities@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-3.0.0.tgz#55d5d96c37ecbde00492c4238e229908eea9cedb" + integrity sha512-04K7cPTcbYXmHICfiob4gZA1yaj4hpfM+Nl5WIJ1EAZsSGHdqmGEF28GuCjyQ8ZeKiJAsPt/vXuLBbjxkHqZyQ== -"@cspell/dict-python@^2.0.3": +"@cspell/dict-html@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@cspell/dict-html/-/dict-html-3.0.1.tgz#d5d10ef9b62361d8250cf9fe8564606993faa9df" + integrity sha512-sbuFd+nSjgbrGf5eYwSddFhm1eLLePKWyH6Zn8Zb0OODrBK5e4vGn1/scI/MOH5a2IvNs8W9wp84uMBFJcQZtw== + +"@cspell/dict-java@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-java/-/dict-java-2.0.0.tgz#76252cee8f04e099ac6dae0f45f22257088060a7" + integrity sha512-9f5LDATlAiXRGqxLxgqbOLlQxuMW2zcN7tBgxwtN+4u90vM03ZUOR/gKIuDV/y0ZuAiWBIjA73cjk8DJ13Q1eA== + +"@cspell/dict-latex@^2.0.3": version "2.0.4" - resolved "https://registry.yarnpkg.com/@cspell/dict-python/-/dict-python-2.0.4.tgz#9c2dc78445ef731b618386628bec8ae9fafa63b7" - integrity sha512-71X/VnyFPm6OPEkqmoVXCJz28RvBgktxy6zF6D5TLt97LbWg2JyRrWSXaf2+seVoLnJQ5CHACxcs+jyEyLhBJA== - -"@cspell/dict-ruby@^1.0.14": - version "1.0.14" - resolved "https://registry.yarnpkg.com/@cspell/dict-ruby/-/dict-ruby-1.0.14.tgz#6ecbda6e0a01e4692abd4a14b64ff8f61d86e161" - integrity sha512-XHBGN4U1y9rjRuqrCA+3yIm2TCdhwwHXpOEcWkNeyXm8K03yPnIrKFS+kap8GTTrLpfNDuFsrmkkQTa7ssXLRA== - -"@cspell/dict-rust@^1.0.23": - version "1.0.23" - resolved "https://registry.yarnpkg.com/@cspell/dict-rust/-/dict-rust-1.0.23.tgz#bcef79f74932d90a07f86efa11a8696788079ad8" - integrity sha512-lR4boDzs79YD6+30mmiSGAMMdwh7HTBAPUFSB0obR3Kidibfc3GZ+MHWZXay5dxZ4nBKM06vyjtanF9VJ8q1Iw== - -"@cspell/dict-scala@^1.0.21": - version "1.0.21" - resolved "https://registry.yarnpkg.com/@cspell/dict-scala/-/dict-scala-1.0.21.tgz#bfda392329061e2352fbcd33d228617742c93831" - integrity sha512-5V/R7PRbbminTpPS3ywgdAalI9BHzcEjEj9ug4kWYvBIGwSnS7T6QCFCiu+e9LvEGUqQC+NHgLY4zs1NaBj2vA== - -"@cspell/dict-software-terms@^1.0.47": - version "1.0.48" - resolved "https://registry.yarnpkg.com/@cspell/dict-software-terms/-/dict-software-terms-1.0.48.tgz#dc45a91c64f9f86df3a047879d9f34aa17435bd0" - integrity sha512-pfF3Ys2gRffu5ElqkH7FQMDMi/iZMyOzpGMb3FSH0PJ2AnRQ5rRNWght1h2L36YxvXl0mWVaFrrfwiOyRIc8ZQ== - -"@cspell/dict-typescript@^1.0.19": - version "1.0.19" - resolved "https://registry.yarnpkg.com/@cspell/dict-typescript/-/dict-typescript-1.0.19.tgz#44f3ad1c93ffc89ebf98fa6964e1634e6612fc30" - integrity sha512-qmJApzoVskDeJnLZzZMaafEDGbEg5Elt4c3Mpg49SWzIHm1N4VXCp5CcFfHsOinJ30dGrs3ARAJGJZIw56kK6A== + resolved "https://registry.yarnpkg.com/@cspell/dict-latex/-/dict-latex-2.0.4.tgz#b201fa2cc25ab8753b0a09f3c32ee0e068c5d20e" + integrity sha512-uqnfQiDQwHL4QTtXQyJdTx6Ol9WDu4c2jMSsL20BIe1wXGaGuGNSIwHEiJyGv7VEBpZTpqx38I4mpKdAERG+gw== + +"@cspell/dict-lorem-ipsum@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-2.0.0.tgz#47f2a9ec24808cdf8417457ae8f5a588f33c338c" + integrity sha512-jKogAKtqvgPMleL6usyj3rZ0m8sVUR6drrD+wMnWSfdx1BmUyTsYiuh/mPEfLAebaYHELWSLQG3rDZRvV9Riqg== -"@cspotcode/source-map-consumer@0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" - integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== +"@cspell/dict-lua@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-lua/-/dict-lua-2.0.0.tgz#b96d0363a28ac7e0483ad03edb21705c4f951459" + integrity sha512-7WUEBEspSKtsq104WdIys1+DLqAxpJPzw74Py1TuE3fI5GvlzeSZkRFP2ya54GB2lCO4C3mq4M8EnitpibVDfw== -"@cspotcode/source-map-support@0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5" - integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== +"@cspell/dict-node@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@cspell/dict-node/-/dict-node-2.0.1.tgz#eda891ebdbce83f20829cb6c85cd209da8cf5cdd" + integrity sha512-ztBWzhvI+YaMehICSJ65cohhjQqoztxf9vrS3YckOiVGBFvUMaFVNdX9klQkvrLcS/O4+2PzoGeIEkmf99amLA== + +"@cspell/dict-npm@^2.0.3": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@cspell/dict-npm/-/dict-npm-2.0.5.tgz#d5b77025fcb46db843091e002409faffcfccade0" + integrity sha512-KuPL5fKaqyG9ACrrinNt84FhVdh23VRtxDLO8MtGUdStca9tjfjPdmP2YF/5VkEKmpKYkfFKVcBUk9RgVkx5bw== + +"@cspell/dict-php@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-php/-/dict-php-2.0.0.tgz#5d42f7df7c1da89fe19c2ccfe1bf61231d183990" + integrity sha512-29WgU77eTO985LvMHwPi1pcpfopfCWfTdffDyqya0JIfOSaFUrlYKzGPkE4mRxcz2G3hXsaM0SRvBNdIRwEdUg== + +"@cspell/dict-powershell@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-powershell/-/dict-powershell-2.0.0.tgz#6e8ae7381b1928dfaf8f5a625f8fae6e8d93f224" + integrity sha512-6uvEhLiGmG3u9TFkM1TYcky6aL9Yk7Sk3KJwoTYBaQJY2KqrprgyQtW6yxIw9oU52VRHlq3KKvSAA9Q26+SIkQ== + +"@cspell/dict-public-licenses@^1.0.4": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@cspell/dict-public-licenses/-/dict-public-licenses-1.0.5.tgz#b4eeb08107b83966913689fcb09f495da249233d" + integrity sha512-N9bttzzhmCq/BN/TeP43075kj9TeaR8l9v0SPre05BRWsChVrWuMM1UvsT4ADXnsYJNl1xcn+q191S/fIzQhBg== + +"@cspell/dict-python@^3.0.5": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@cspell/dict-python/-/dict-python-3.0.6.tgz#884f398e053a5d500adc9de47d1f1049a7afcc9c" + integrity sha512-tzxJ4sd9ZGhAUKg/WJJpQGDNtoHvM8Wn+iS2+PnQj2/LTHBW4mnaCogsGsBtYu8C4b2+BEQs+tc5808AeEfLug== + +"@cspell/dict-r@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@cspell/dict-r/-/dict-r-1.0.3.tgz#1480016695ee119cf63fa8c71b161d033bbb9029" + integrity sha512-u2qeXd4cx/TvTVcmkvA+sK6f4K1uMAMO6QPMSr1pSvqGElPRP1mIBXmuiSuBzLO3LbsJuUEHw5Cp3/bxIB6rNA== + +"@cspell/dict-ruby@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@cspell/dict-ruby/-/dict-ruby-2.0.1.tgz#1cbd4d8803428bd421a5562b2d2bb4b3bae80bce" + integrity sha512-qGqhYfFeoBOashv/l0Kj5o4ilyvfq0s+t+r32juPOkOnbHz+hzxnJo2tMMg/L/UdjVV7Y8ovg4LDBC/seVrMYQ== + +"@cspell/dict-rust@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-rust/-/dict-rust-2.0.0.tgz#89acc6c251164b09c424d23abb5ee560a4484ee6" + integrity sha512-EWlQivTKXMU3TTcq/Pi6KPKTQADknasQ700UrxRPzxhwQ4sKVZ88GDu6VZJlsbFUz8Vko289KS6wjiox/7WpmQ== + +"@cspell/dict-scala@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-scala/-/dict-scala-2.0.0.tgz#b8098103bb03a13406c1c79f1769052353aafac4" + integrity sha512-MUwA2YKpqaQOSR4V1/CVGRNk8Ii5kf6I8Ch+4/BhRZRQXuwWbi21rDRYWPqdQWps7VNzAbbMA+PQDWsD5YY38g== + +"@cspell/dict-software-terms@^2.1.7": + version "2.1.8" + resolved "https://registry.yarnpkg.com/@cspell/dict-software-terms/-/dict-software-terms-2.1.8.tgz#2db1d3ce7c125552e86503bb09379041787e1a07" + integrity sha512-D9ECefkdbr5B0yLimy7nmEBl3AHPsweMG1wHatlCIT9uFwwqaq5e+ngbYrntEhMa6afkYY+LGOLbZ1L1dfpLVg== + +"@cspell/dict-swift@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@cspell/dict-swift/-/dict-swift-1.0.3.tgz#b819da0ca2c5dfecdd61bec55181636a06d23677" + integrity sha512-yOBLSaRD0AnkkkndJ8PuB82Evp6lA2xItf2AWsnPfCCgxp5Ojk6uUBC/WQBSkzkCAOGbXyHsu9D97tsOx2c6cw== + +"@cspell/dict-typescript@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-typescript/-/dict-typescript-2.0.0.tgz#c1ce88dcb1b480623eb537670d11844047539a53" + integrity sha512-WFBahxsnD2y4Os14tE5Zxh31Ggn4DzGOAu3UoxYl1lLLxaszx4RH7LmAeFuznySboiaBeRBbpfJOjQA796O6VQ== + +"@cspell/dict-vue@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@cspell/dict-vue/-/dict-vue-2.0.2.tgz#8618b9f4825b3d80e1788082c19ac9c15832463e" + integrity sha512-/MB0RS0Gn01s4pgmjy0FvsLfr3RRMrRphEuvTRserNcM8XVtoIVAtrjig/Gg0DPwDrN8Clm0L1j7iQay6S8D0g== + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== dependencies: - "@cspotcode/source-map-consumer" "0.8.0" + "@jridgewell/trace-mapping" "0.3.9" "@cypress/request@^2.88.5": version "2.88.10" @@ -1612,215 +1700,215 @@ debug "^3.1.0" lodash.once "^4.1.1" -"@docsearch/css@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.0.0.tgz#fe57b474802ffd706d3246eab25d52fac8aa3698" - integrity sha512-1kkV7tkAsiuEd0shunYRByKJe3xQDG2q7wYg24SOw1nV9/2lwEd4WrUYRJC/ukGTl2/kHeFxsaUvtiOy0y6fFA== +"@docsearch/css@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.1.0.tgz#6781cad43fc2e034d012ee44beddf8f93ba21f19" + integrity sha512-bh5IskwkkodbvC0FzSg1AxMykfDl95hebEKwxNoq4e5QaGzOXSBgW8+jnMFZ7JU4sTBiB04vZWoUSzNrPboLZA== -"@docsearch/react@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.0.0.tgz#d02ebdc67573412185a6a4df13bc254c7c0da491" - integrity sha512-yhMacqS6TVQYoBh/o603zszIb5Bl8MIXuOc6Vy617I74pirisDzzcNh0NEaYQt50fVVR3khUbeEhUEWEWipESg== +"@docsearch/react@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.1.0.tgz#da943a64c01ee82b04e53b691806469272f943f7" + integrity sha512-bjB6ExnZzf++5B7Tfoi6UXgNwoUnNOfZ1NyvnvPhWgCMy5V/biAtLL4o7owmZSYdAKeFSvZ5Lxm0is4su/dBWg== dependencies: - "@algolia/autocomplete-core" "1.5.2" - "@algolia/autocomplete-preset-algolia" "1.5.2" - "@docsearch/css" "3.0.0" + "@algolia/autocomplete-core" "1.6.3" + "@docsearch/css" "3.1.0" algoliasearch "^4.0.0" -"@docusaurus/core@2.0.0-beta.18", "@docusaurus/core@^2.0.0-beta.18": - version "2.0.0-beta.18" - resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.0.0-beta.18.tgz#44c6eefe29257462df630640a35f0c86bd80639a" - integrity sha512-puV7l+0/BPSi07Xmr8tVktfs1BzhC8P5pm6Bs2CfvysCJ4nefNCD1CosPc1PGBWy901KqeeEJ1aoGwj9tU3AUA== +"@docusaurus/core@2.0.0-beta.21", "@docusaurus/core@^2.0.0-beta.18": + version "2.0.0-beta.21" + resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.0.0-beta.21.tgz#50897317b22dbd94b1bf91bb30c2a0fddd15a806" + integrity sha512-qysDMVp1M5UozK3u/qOxsEZsHF7jeBvJDS+5ItMPYmNKvMbNKeYZGA0g6S7F9hRDwjIlEbvo7BaX0UMDcmTAWA== dependencies: - "@babel/core" "^7.17.8" - "@babel/generator" "^7.17.7" + "@babel/core" "^7.18.2" + "@babel/generator" "^7.18.2" "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-transform-runtime" "^7.17.0" - "@babel/preset-env" "^7.16.11" - "@babel/preset-react" "^7.16.7" - "@babel/preset-typescript" "^7.16.7" - "@babel/runtime" "^7.17.8" - "@babel/runtime-corejs3" "^7.17.8" - "@babel/traverse" "^7.17.3" - "@docusaurus/cssnano-preset" "2.0.0-beta.18" - "@docusaurus/logger" "2.0.0-beta.18" - "@docusaurus/mdx-loader" "2.0.0-beta.18" + "@babel/plugin-transform-runtime" "^7.18.2" + "@babel/preset-env" "^7.18.2" + "@babel/preset-react" "^7.17.12" + "@babel/preset-typescript" "^7.17.12" + "@babel/runtime" "^7.18.3" + "@babel/runtime-corejs3" "^7.18.3" + "@babel/traverse" "^7.18.2" + "@docusaurus/cssnano-preset" "2.0.0-beta.21" + "@docusaurus/logger" "2.0.0-beta.21" + "@docusaurus/mdx-loader" "2.0.0-beta.21" "@docusaurus/react-loadable" "5.5.2" - "@docusaurus/utils" "2.0.0-beta.18" - "@docusaurus/utils-common" "2.0.0-beta.18" - "@docusaurus/utils-validation" "2.0.0-beta.18" + "@docusaurus/utils" "2.0.0-beta.21" + "@docusaurus/utils-common" "2.0.0-beta.21" + "@docusaurus/utils-validation" "2.0.0-beta.21" "@slorber/static-site-generator-webpack-plugin" "^4.0.4" "@svgr/webpack" "^6.2.1" - autoprefixer "^10.4.4" - babel-loader "^8.2.4" - babel-plugin-dynamic-import-node "2.3.0" + autoprefixer "^10.4.7" + babel-loader "^8.2.5" + babel-plugin-dynamic-import-node "^2.3.3" boxen "^6.2.1" + chalk "^4.1.2" chokidar "^3.5.3" - clean-css "^5.2.4" - cli-table3 "^0.6.1" + clean-css "^5.3.0" + cli-table3 "^0.6.2" combine-promises "^1.1.0" commander "^5.1.0" - copy-webpack-plugin "^10.2.4" - core-js "^3.21.1" + copy-webpack-plugin "^11.0.0" + core-js "^3.22.7" css-loader "^6.7.1" - css-minimizer-webpack-plugin "^3.4.1" - cssnano "^5.1.5" - del "^6.0.0" + css-minimizer-webpack-plugin "^4.0.0" + cssnano "^5.1.9" + del "^6.1.1" detect-port "^1.3.0" escape-html "^1.0.3" eta "^1.12.3" file-loader "^6.2.0" - fs-extra "^10.0.1" + fs-extra "^10.1.0" html-minifier-terser "^6.1.0" - html-tags "^3.1.0" + html-tags "^3.2.0" html-webpack-plugin "^5.5.0" import-fresh "^3.3.0" - is-root "^2.1.0" leven "^3.1.0" lodash "^4.17.21" mini-css-extract-plugin "^2.6.0" - nprogress "^0.2.0" - postcss "^8.4.12" - postcss-loader "^6.2.1" + postcss "^8.4.14" + postcss-loader "^7.0.0" prompts "^2.4.2" - react-dev-utils "^12.0.0" - react-helmet-async "^1.2.3" + react-dev-utils "^12.0.1" + react-helmet-async "^1.3.0" react-loadable "npm:@docusaurus/react-loadable@5.5.2" react-loadable-ssr-addon-v5-slorber "^1.0.1" - react-router "^5.2.0" + react-router "^5.3.3" react-router-config "^5.1.1" - react-router-dom "^5.2.0" + react-router-dom "^5.3.3" remark-admonitions "^1.2.1" rtl-detect "^1.0.4" - semver "^7.3.5" + semver "^7.3.7" serve-handler "^6.1.3" shelljs "^0.8.5" terser-webpack-plugin "^5.3.1" - tslib "^2.3.1" + tslib "^2.4.0" update-notifier "^5.1.0" url-loader "^4.1.1" wait-on "^6.0.1" - webpack "^5.70.0" + webpack "^5.72.1" webpack-bundle-analyzer "^4.5.0" - webpack-dev-server "^4.7.4" + webpack-dev-server "^4.9.0" webpack-merge "^5.8.0" webpackbar "^5.0.2" -"@docusaurus/cssnano-preset@2.0.0-beta.18": - version "2.0.0-beta.18" - resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-beta.18.tgz#235ac9064fe8f8da618349ce5305be3ed3a44e29" - integrity sha512-VxhYmpyx16Wv00W9TUfLVv0NgEK/BwP7pOdWoaiELEIAMV7SO1+6iB8gsFUhtfKZ31I4uPVLMKrCyWWakoFeFA== +"@docusaurus/cssnano-preset@2.0.0-beta.21": + version "2.0.0-beta.21" + resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-beta.21.tgz#38113877a5857c3f9d493522085d20909dcec474" + integrity sha512-fhTZrg1vc6zYYZIIMXpe1TnEVGEjqscBo0s1uomSwKjjtMgu7wkzc1KKJYY7BndsSA+fVVkZ+OmL/kAsmK7xxw== dependencies: - cssnano-preset-advanced "^5.3.1" - postcss "^8.4.12" + cssnano-preset-advanced "^5.3.5" + postcss "^8.4.14" postcss-sort-media-queries "^4.2.1" + tslib "^2.4.0" -"@docusaurus/logger@2.0.0-beta.18": - version "2.0.0-beta.18" - resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-2.0.0-beta.18.tgz#12302f312a083eb018caa28505b63f5dd4ab6a91" - integrity sha512-frNe5vhH3mbPmH980Lvzaz45+n1PQl3TkslzWYXQeJOkFX17zUd3e3U7F9kR1+DocmAqHkgAoWuXVcvEoN29fg== +"@docusaurus/logger@2.0.0-beta.21": + version "2.0.0-beta.21" + resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-2.0.0-beta.21.tgz#f6ab4133917965349ae03fd9111a940b24d4fd12" + integrity sha512-HTFp8FsSMrAj7Uxl5p72U+P7rjYU/LRRBazEoJbs9RaqoKEdtZuhv8MYPOCh46K9TekaoquRYqag2o23Qt4ggA== dependencies: chalk "^4.1.2" - tslib "^2.3.1" + tslib "^2.4.0" -"@docusaurus/mdx-loader@2.0.0-beta.18": - version "2.0.0-beta.18" - resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-beta.18.tgz#4a9fc0607e0a210a7d7db3108415208dd36e33d3" - integrity sha512-pOmAQM4Y1jhuZTbEhjh4ilQa74Mh6Q0pMZn1xgIuyYDdqvIOrOlM/H0i34YBn3+WYuwsGim4/X0qynJMLDUA4A== +"@docusaurus/mdx-loader@2.0.0-beta.21": + version "2.0.0-beta.21" + resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-beta.21.tgz#52af341e21f22be882d2155a7349bea10f5d77a3" + integrity sha512-AI+4obJnpOaBOAYV6df2ux5Y1YJCBS+MhXFf0yhED12sVLJi2vffZgdamYd/d/FwvWDw6QLs/VD2jebd7P50yQ== dependencies: - "@babel/parser" "^7.17.8" - "@babel/traverse" "^7.17.3" - "@docusaurus/logger" "2.0.0-beta.18" - "@docusaurus/utils" "2.0.0-beta.18" + "@babel/parser" "^7.18.3" + "@babel/traverse" "^7.18.2" + "@docusaurus/logger" "2.0.0-beta.21" + "@docusaurus/utils" "2.0.0-beta.21" "@mdx-js/mdx" "^1.6.22" escape-html "^1.0.3" file-loader "^6.2.0" - fs-extra "^10.0.1" + fs-extra "^10.1.0" image-size "^1.0.1" mdast-util-to-string "^2.0.0" - remark-emoji "^2.1.0" + remark-emoji "^2.2.0" stringify-object "^3.3.0" - tslib "^2.3.1" - unist-util-visit "^2.0.2" + tslib "^2.4.0" + unist-util-visit "^2.0.3" url-loader "^4.1.1" - webpack "^5.70.0" + webpack "^5.72.1" -"@docusaurus/module-type-aliases@2.0.0-beta.18", "@docusaurus/module-type-aliases@^2.0.0-beta.18": - version "2.0.0-beta.18" - resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-2.0.0-beta.18.tgz#001379229c58cbc3ed565e19437cbda86d5e8742" - integrity sha512-e6mples8FZRyT7QyqidGS6BgkROjM+gljJsdOqoctbtBp+SZ5YDjwRHOmoY7eqEfsQNOaFZvT2hK38ui87hCRA== +"@docusaurus/module-type-aliases@2.0.0-beta.21", "@docusaurus/module-type-aliases@^2.0.0-beta.18": + version "2.0.0-beta.21" + resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-2.0.0-beta.21.tgz#345f1c1a99407775d1d3ffc1a90c2df93d50a9b8" + integrity sha512-gRkWICgQZiqSJgrwRKWjXm5gAB+9IcfYdUbCG0PRPP/G8sNs9zBIOY4uT4Z5ox2CWFEm44U3RTTxj7BiLVMBXw== dependencies: - "@docusaurus/types" "2.0.0-beta.18" + "@docusaurus/types" "2.0.0-beta.21" "@types/react" "*" "@types/react-router-config" "*" "@types/react-router-dom" "*" react-helmet-async "*" -"@docusaurus/plugin-content-blog@2.0.0-beta.18": - version "2.0.0-beta.18" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.18.tgz#95fe3dfc8bae9bf153c65a3a441234c450cbac0a" - integrity sha512-qzK83DgB+mxklk3PQC2nuTGPQD/8ogw1nXSmaQpyXAyhzcz4CXAZ9Swl/Ee9A/bvPwQGnSHSP3xqIYl8OkFtfw== - dependencies: - "@docusaurus/core" "2.0.0-beta.18" - "@docusaurus/logger" "2.0.0-beta.18" - "@docusaurus/mdx-loader" "2.0.0-beta.18" - "@docusaurus/utils" "2.0.0-beta.18" - "@docusaurus/utils-common" "2.0.0-beta.18" - "@docusaurus/utils-validation" "2.0.0-beta.18" - cheerio "^1.0.0-rc.10" +"@docusaurus/plugin-content-blog@2.0.0-beta.21": + version "2.0.0-beta.21" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.21.tgz#86211deeea901ddcd77ca387778e121e93ee8d01" + integrity sha512-IP21yJViP3oBmgsWBU5LhrG1MZXV4mYCQSoCAboimESmy1Z11RCNP2tXaqizE3iTmXOwZZL+SNBk06ajKCEzWg== + dependencies: + "@docusaurus/core" "2.0.0-beta.21" + "@docusaurus/logger" "2.0.0-beta.21" + "@docusaurus/mdx-loader" "2.0.0-beta.21" + "@docusaurus/utils" "2.0.0-beta.21" + "@docusaurus/utils-common" "2.0.0-beta.21" + "@docusaurus/utils-validation" "2.0.0-beta.21" + cheerio "^1.0.0-rc.11" feed "^4.2.2" - fs-extra "^10.0.1" + fs-extra "^10.1.0" lodash "^4.17.21" reading-time "^1.5.0" remark-admonitions "^1.2.1" - tslib "^2.3.1" + tslib "^2.4.0" + unist-util-visit "^2.0.3" utility-types "^3.10.0" - webpack "^5.70.0" - -"@docusaurus/plugin-content-docs@2.0.0-beta.18", "@docusaurus/plugin-content-docs@^2.0.0-beta.18": - version "2.0.0-beta.18" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-beta.18.tgz#fef52d945da2928e0f4f3f9a9384d9ee7f2d4288" - integrity sha512-z4LFGBJuzn4XQiUA7OEA2SZTqlp+IYVjd3NrCk/ZUfNi1tsTJS36ATkk9Y6d0Nsp7K2kRXqaXPsz4adDgeIU+Q== - dependencies: - "@docusaurus/core" "2.0.0-beta.18" - "@docusaurus/logger" "2.0.0-beta.18" - "@docusaurus/mdx-loader" "2.0.0-beta.18" - "@docusaurus/utils" "2.0.0-beta.18" - "@docusaurus/utils-validation" "2.0.0-beta.18" + webpack "^5.72.1" + +"@docusaurus/plugin-content-docs@2.0.0-beta.21", "@docusaurus/plugin-content-docs@^2.0.0-beta.18": + version "2.0.0-beta.21" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-beta.21.tgz#b3171fa9aed99e367b6eb7111187bd0e3dcf2949" + integrity sha512-aa4vrzJy4xRy81wNskyhE3wzRf3AgcESZ1nfKh8xgHUkT7fDTZ1UWlg50Jb3LBCQFFyQG2XQB9N6llskI/KUnw== + dependencies: + "@docusaurus/core" "2.0.0-beta.21" + "@docusaurus/logger" "2.0.0-beta.21" + "@docusaurus/mdx-loader" "2.0.0-beta.21" + "@docusaurus/utils" "2.0.0-beta.21" + "@docusaurus/utils-validation" "2.0.0-beta.21" combine-promises "^1.1.0" - fs-extra "^10.0.1" + fs-extra "^10.1.0" import-fresh "^3.3.0" js-yaml "^4.1.0" lodash "^4.17.21" remark-admonitions "^1.2.1" - tslib "^2.3.1" + tslib "^2.4.0" utility-types "^3.10.0" - webpack "^5.70.0" - -"@docusaurus/plugin-content-pages@2.0.0-beta.18", "@docusaurus/plugin-content-pages@^2.0.0-beta.18": - version "2.0.0-beta.18" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-beta.18.tgz#0fef392be3fea3d85c212caf4eb744ead920c30b" - integrity sha512-CJ2Xeb9hQrMeF4DGywSDVX2TFKsQpc8ZA7czyeBAAbSFsoRyxXPYeSh8aWljqR4F1u/EKGSKy0Shk/D4wumaHw== - dependencies: - "@docusaurus/core" "2.0.0-beta.18" - "@docusaurus/mdx-loader" "2.0.0-beta.18" - "@docusaurus/utils" "2.0.0-beta.18" - "@docusaurus/utils-validation" "2.0.0-beta.18" - fs-extra "^10.0.1" + webpack "^5.72.1" + +"@docusaurus/plugin-content-pages@2.0.0-beta.21", "@docusaurus/plugin-content-pages@^2.0.0-beta.18": + version "2.0.0-beta.21" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-beta.21.tgz#df6b4c5c4cde8a0ea491a30002e84941ca7bf0cf" + integrity sha512-DmXOXjqNI+7X5hISzCvt54QIK6XBugu2MOxjxzuqI7q92Lk/EVdraEj5mthlH8IaEH/VlpWYJ1O9TzLqX5vH2g== + dependencies: + "@docusaurus/core" "2.0.0-beta.21" + "@docusaurus/mdx-loader" "2.0.0-beta.21" + "@docusaurus/utils" "2.0.0-beta.21" + "@docusaurus/utils-validation" "2.0.0-beta.21" + fs-extra "^10.1.0" remark-admonitions "^1.2.1" - tslib "^2.3.1" - webpack "^5.70.0" + tslib "^2.4.0" + webpack "^5.72.1" "@docusaurus/plugin-debug@^2.0.0-beta.18": - version "2.0.0-beta.18" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-beta.18.tgz#d4582532e59b538a23398f7c444b005367efa922" - integrity sha512-inLnLERgG7q0WlVmK6nYGHwVqREz13ivkynmNygEibJZToFRdgnIPW+OwD8QzgC5MpQTJw7+uYjcitpBumy1Gw== + version "2.0.0-beta.21" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-beta.21.tgz#dfa212fd90fe2f54439aacdc8c143e8ce96b0d27" + integrity sha512-P54J4q4ecsyWW0Jy4zbimSIHna999AfbxpXGmF1IjyHrjoA3PtuakV1Ai51XrGEAaIq9q6qMQkEhbUd3CffGAw== dependencies: - "@docusaurus/core" "2.0.0-beta.18" - "@docusaurus/utils" "2.0.0-beta.18" - fs-extra "^10.0.1" + "@docusaurus/core" "2.0.0-beta.21" + "@docusaurus/utils" "2.0.0-beta.21" + fs-extra "^10.1.0" react-json-view "^1.21.3" - tslib "^2.3.1" + tslib "^2.4.0" "@docusaurus/react-loadable@5.5.2", "react-loadable@npm:@docusaurus/react-loadable@5.5.2": version "5.5.2" @@ -1831,122 +1919,126 @@ prop-types "^15.6.2" "@docusaurus/remark-plugin-npm2yarn@^2.0.0-beta.18": - version "2.0.0-beta.18" - resolved "https://registry.yarnpkg.com/@docusaurus/remark-plugin-npm2yarn/-/remark-plugin-npm2yarn-2.0.0-beta.18.tgz#f898f186ffb4d5e7938be050c71be222c55f4d03" - integrity sha512-GmlbPzB8ImH6ey0LhOTe5NOIY30TwVNXarpm63zG1HYEUOT/H8X8w2NQPlT6RyhH9FtDi4bKMzfEP4ImpJGgCQ== + version "2.0.0-beta.21" + resolved "https://registry.yarnpkg.com/@docusaurus/remark-plugin-npm2yarn/-/remark-plugin-npm2yarn-2.0.0-beta.21.tgz#10eb88a2dab6193568eff76b6a83b79e313ef765" + integrity sha512-CqvmoFEj05NzaQBKxnsfI90aM8KHJZWyCzED/Qg5odUD9VtR9zNQJ1Nu/X1ctqCN7FBIxBYk2tz1Xb1+zCP8gg== dependencies: npm-to-yarn "^1.0.1" - tslib "^2.3.1" - unist-util-visit "^2.0.2" + tslib "^2.4.0" + unist-util-visit "^2.0.3" "@docusaurus/theme-classic@^2.0.0-beta.18": - version "2.0.0-beta.18" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-2.0.0-beta.18.tgz#a3632e83923ed4372f80999128375cd0b378d3f8" - integrity sha512-WJWofvSGKC4Luidk0lyUwkLnO3DDynBBHwmt4QrV+aAVWWSOHUjA2mPOF6GLGuzkZd3KfL9EvAfsU0aGE1Hh5g== - dependencies: - "@docusaurus/core" "2.0.0-beta.18" - "@docusaurus/plugin-content-blog" "2.0.0-beta.18" - "@docusaurus/plugin-content-docs" "2.0.0-beta.18" - "@docusaurus/plugin-content-pages" "2.0.0-beta.18" - "@docusaurus/theme-common" "2.0.0-beta.18" - "@docusaurus/theme-translations" "2.0.0-beta.18" - "@docusaurus/utils" "2.0.0-beta.18" - "@docusaurus/utils-common" "2.0.0-beta.18" - "@docusaurus/utils-validation" "2.0.0-beta.18" + version "2.0.0-beta.21" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-2.0.0-beta.21.tgz#6df5b9ea2d389dafb6f59badeabb3eda060b5017" + integrity sha512-Ge0WNdTefD0VDQfaIMRRWa8tWMG9+8/OlBRd5MK88/TZfqdBq7b/gnCSaalQlvZwwkj6notkKhHx72+MKwWUJA== + dependencies: + "@docusaurus/core" "2.0.0-beta.21" + "@docusaurus/plugin-content-blog" "2.0.0-beta.21" + "@docusaurus/plugin-content-docs" "2.0.0-beta.21" + "@docusaurus/plugin-content-pages" "2.0.0-beta.21" + "@docusaurus/theme-common" "2.0.0-beta.21" + "@docusaurus/theme-translations" "2.0.0-beta.21" + "@docusaurus/utils" "2.0.0-beta.21" + "@docusaurus/utils-common" "2.0.0-beta.21" + "@docusaurus/utils-validation" "2.0.0-beta.21" "@mdx-js/react" "^1.6.22" clsx "^1.1.1" copy-text-to-clipboard "^3.0.1" - infima "0.2.0-alpha.38" + infima "0.2.0-alpha.39" lodash "^4.17.21" - postcss "^8.4.12" - prism-react-renderer "^1.3.1" - prismjs "^1.27.0" - react-router-dom "^5.2.0" + nprogress "^0.2.0" + postcss "^8.4.14" + prism-react-renderer "^1.3.3" + prismjs "^1.28.0" + react-router-dom "^5.3.3" rtlcss "^3.5.0" + tslib "^2.4.0" -"@docusaurus/theme-common@2.0.0-beta.18", "@docusaurus/theme-common@^2.0.0-beta.18": - version "2.0.0-beta.18" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-2.0.0-beta.18.tgz#abf74f82c37d2ce813f92447cb020831290059fb" - integrity sha512-3pI2Q6ttScDVTDbuUKAx+TdC8wmwZ2hfWk8cyXxksvC9bBHcyzXhSgcK8LTsszn2aANyZ3e3QY2eNSOikTFyng== +"@docusaurus/theme-common@2.0.0-beta.21", "@docusaurus/theme-common@^2.0.0-beta.18": + version "2.0.0-beta.21" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-2.0.0-beta.21.tgz#508478251982d01655ef505ccb2420db38623db8" + integrity sha512-fTKoTLRfjuFG6c3iwnVjIIOensxWMgdBKLfyE5iih3Lq7tQgkE7NyTGG9BKLrnTJ7cAD2UXdXM9xbB7tBf1qzg== dependencies: - "@docusaurus/module-type-aliases" "2.0.0-beta.18" - "@docusaurus/plugin-content-blog" "2.0.0-beta.18" - "@docusaurus/plugin-content-docs" "2.0.0-beta.18" - "@docusaurus/plugin-content-pages" "2.0.0-beta.18" + "@docusaurus/module-type-aliases" "2.0.0-beta.21" + "@docusaurus/plugin-content-blog" "2.0.0-beta.21" + "@docusaurus/plugin-content-docs" "2.0.0-beta.21" + "@docusaurus/plugin-content-pages" "2.0.0-beta.21" clsx "^1.1.1" parse-numeric-range "^1.3.0" - prism-react-renderer "^1.3.1" - tslib "^2.3.1" + prism-react-renderer "^1.3.3" + tslib "^2.4.0" utility-types "^3.10.0" "@docusaurus/theme-search-algolia@^2.0.0-beta.18": - version "2.0.0-beta.18" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-beta.18.tgz#cbdda8982deac4556848e04853b7f32d93886c02" - integrity sha512-2w97KO/gnjI49WVtYQqENpQ8iO1Sem0yaTxw7/qv/ndlmIAQD0syU4yx6GsA7bTQCOGwKOWWzZSetCgUmTnWgA== - dependencies: - "@docsearch/react" "^3.0.0" - "@docusaurus/core" "2.0.0-beta.18" - "@docusaurus/logger" "2.0.0-beta.18" - "@docusaurus/plugin-content-docs" "2.0.0-beta.18" - "@docusaurus/theme-common" "2.0.0-beta.18" - "@docusaurus/theme-translations" "2.0.0-beta.18" - "@docusaurus/utils" "2.0.0-beta.18" - "@docusaurus/utils-validation" "2.0.0-beta.18" - algoliasearch "^4.13.0" - algoliasearch-helper "^3.7.4" + version "2.0.0-beta.21" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-beta.21.tgz#2891f11372e2542e4e1426c3100b72c2d30d4d68" + integrity sha512-T1jKT8MVSSfnztSqeebUOpWHPoHKtwDXtKYE0xC99JWoZ+mMfv8AFhVSoSddn54jLJjV36mxg841eHQIySMCpQ== + dependencies: + "@docsearch/react" "^3.1.0" + "@docusaurus/core" "2.0.0-beta.21" + "@docusaurus/logger" "2.0.0-beta.21" + "@docusaurus/plugin-content-docs" "2.0.0-beta.21" + "@docusaurus/theme-common" "2.0.0-beta.21" + "@docusaurus/theme-translations" "2.0.0-beta.21" + "@docusaurus/utils" "2.0.0-beta.21" + "@docusaurus/utils-validation" "2.0.0-beta.21" + algoliasearch "^4.13.1" + algoliasearch-helper "^3.8.2" clsx "^1.1.1" eta "^1.12.3" - fs-extra "^10.0.1" + fs-extra "^10.1.0" lodash "^4.17.21" - tslib "^2.3.1" + tslib "^2.4.0" utility-types "^3.10.0" -"@docusaurus/theme-translations@2.0.0-beta.18": - version "2.0.0-beta.18" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-2.0.0-beta.18.tgz#292699ce89b013262683faf7f4ee7b75a8745a79" - integrity sha512-1uTEUXlKC9nco1Lx9H5eOwzB+LP4yXJG5wfv1PMLE++kJEdZ40IVorlUi3nJnaa9/lJNq5vFvvUDrmeNWsxy/Q== +"@docusaurus/theme-translations@2.0.0-beta.21": + version "2.0.0-beta.21" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-2.0.0-beta.21.tgz#5da60ffc58de256b96316c5e0fe2733c1e83f22c" + integrity sha512-dLVT9OIIBs6MpzMb1bAy+C0DPJK3e3DNctG+ES0EP45gzEqQxzs4IsghpT+QDaOsuhNnAlosgJpFWX3rqxF9xA== dependencies: - fs-extra "^10.0.1" - tslib "^2.3.1" + fs-extra "^10.1.0" + tslib "^2.4.0" -"@docusaurus/types@2.0.0-beta.18": - version "2.0.0-beta.18" - resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-2.0.0-beta.18.tgz#9446928a6b751eefde390420b39eac32ba26abb2" - integrity sha512-zkuSmPQYP3+z4IjGHlW0nGzSSpY7Sit0Nciu/66zSb5m07TK72t6T1MlpCAn/XijcB9Cq6nenC3kJh66nGsKYg== +"@docusaurus/types@2.0.0-beta.21": + version "2.0.0-beta.21" + resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-2.0.0-beta.21.tgz#36659c6c012663040dcd4cbc97b5d7a555dae229" + integrity sha512-/GH6Npmq81eQfMC/ikS00QSv9jNyO1RXEpNSx5GLA3sFX8Iib26g2YI2zqNplM8nyxzZ2jVBuvUoeODTIbTchQ== dependencies: commander "^5.1.0" + history "^4.9.0" joi "^17.6.0" + react-helmet-async "^1.3.0" utility-types "^3.10.0" - webpack "^5.70.0" + webpack "^5.72.1" webpack-merge "^5.8.0" -"@docusaurus/utils-common@2.0.0-beta.18": - version "2.0.0-beta.18" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-2.0.0-beta.18.tgz#46cf0bed2a7c532b2b85eab5bb914ff118b2c4e9" - integrity sha512-pK83EcOIiKCLGhrTwukZMo5jqd1sqqqhQwOVyxyvg+x9SY/lsnNzScA96OEfm+qQLBwK1OABA7Xc1wfkgkUxvw== +"@docusaurus/utils-common@2.0.0-beta.21": + version "2.0.0-beta.21" + resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-2.0.0-beta.21.tgz#81e86ed04ad62b75e9ba6a5e7689dc23d5f36a0a" + integrity sha512-5w+6KQuJb6pUR2M8xyVuTMvO5NFQm/p8TOTDFTx60wt3p0P1rRX00v6FYsD4PK6pgmuoKjt2+Ls8dtSXc4qFpQ== dependencies: - tslib "^2.3.1" + tslib "^2.4.0" -"@docusaurus/utils-validation@2.0.0-beta.18": - version "2.0.0-beta.18" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.0.0-beta.18.tgz#0dabf113d2c53ee685a715cd4caae6e219e9e41e" - integrity sha512-3aDrXjJJ8Cw2MAYEk5JMNnr8UHPxmVNbPU/PIHFWmWK09nJvs3IQ8nc9+8I30aIjRdIyc/BIOCxgvAcJ4hsxTA== +"@docusaurus/utils-validation@2.0.0-beta.21": + version "2.0.0-beta.21" + resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.0.0-beta.21.tgz#10169661be5f8a233f4c12202ee5802ccb77400f" + integrity sha512-6NG1FHTRjv1MFzqW//292z7uCs77vntpWEbZBHk3n67aB1HoMn5SOwjLPtRDjbCgn6HCHFmdiJr6euCbjhYolg== dependencies: - "@docusaurus/logger" "2.0.0-beta.18" - "@docusaurus/utils" "2.0.0-beta.18" + "@docusaurus/logger" "2.0.0-beta.21" + "@docusaurus/utils" "2.0.0-beta.21" joi "^17.6.0" js-yaml "^4.1.0" - tslib "^2.3.1" + tslib "^2.4.0" -"@docusaurus/utils@2.0.0-beta.18": - version "2.0.0-beta.18" - resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.0.0-beta.18.tgz#c3fe0e9fac30db4510962263993fd0ee2679eebb" - integrity sha512-v2vBmH7xSbPwx3+GB90HgLSQdj+Rh5ELtZWy7M20w907k0ROzDmPQ/8Ke2DK3o5r4pZPGnCrsB3SaYI83AEmAA== +"@docusaurus/utils@2.0.0-beta.21": + version "2.0.0-beta.21" + resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.0.0-beta.21.tgz#8fc4499c4cfedd29805025d930f8008cad255044" + integrity sha512-M/BrVCDmmUPZLxtiStBgzpQ4I5hqkggcpnQmEN+LbvbohjbtVnnnZQ0vptIziv1w8jry/woY+ePsyOO7O/yeLQ== dependencies: - "@docusaurus/logger" "2.0.0-beta.18" + "@docusaurus/logger" "2.0.0-beta.21" "@svgr/webpack" "^6.2.1" file-loader "^6.2.0" - fs-extra "^10.0.1" + fs-extra "^10.1.0" github-slugger "^1.4.0" globby "^11.1.0" gray-matter "^4.0.3" @@ -1955,34 +2047,34 @@ micromatch "^4.0.5" resolve-pathname "^3.0.0" shelljs "^0.8.5" - tslib "^2.3.1" + tslib "^2.4.0" url-loader "^4.1.1" - webpack "^5.70.0" + webpack "^5.72.1" -"@eslint/eslintrc@^1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.0.5.tgz#33f1b838dbf1f923bfa517e008362b78ddbbf318" - integrity sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ== +"@eslint/eslintrc@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.0.tgz#29f92c30bb3e771e4a2048c95fa6855392dfac4f" + integrity sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.2.0" - globals "^13.9.0" - ignore "^4.0.6" + espree "^9.3.2" + globals "^13.15.0" + ignore "^5.2.0" import-fresh "^3.2.1" js-yaml "^4.1.0" - minimatch "^3.0.4" + minimatch "^3.1.2" strip-json-comments "^3.1.1" "@gar/promisify@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.2.tgz#30aa825f11d438671d585bd44e7fd564535fc210" - integrity sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw== + version "1.1.3" + resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" + integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== "@hapi/hoek@^9.0.0": - version "9.2.1" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.2.1.tgz#9551142a1980503752536b5050fd99f4a7f13b17" - integrity sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw== + version "9.3.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" + integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== "@hapi/topo@^5.0.0": version "5.1.0" @@ -1992,9 +2084,9 @@ "@hapi/hoek" "^9.0.0" "@humanwhocodes/config-array@^0.9.2": - version "0.9.2" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.2.tgz#68be55c737023009dfc5fe245d51181bb6476914" - integrity sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA== + version "0.9.5" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7" + integrity sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw== dependencies: "@humanwhocodes/object-schema" "^1.2.1" debug "^4.1.1" @@ -2089,6 +2181,13 @@ "@types/node" "*" jest-mock "^27.5.1" +"@jest/expect-utils@^28.1.0": + version "28.1.0" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-28.1.0.tgz#a5cde811195515a9809b96748ae8bcc331a3538a" + integrity sha512-5BrG48dpC0sB80wpeIX5FU6kolDJI4K0n5BM9a5V38MGx0pyRvUBSS0u2aNTdDzmOrCjhOg8pGs6a20ivYkdmw== + dependencies: + jest-get-type "^28.0.2" + "@jest/fake-timers@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.5.1.tgz#76979745ce0579c8a94a4678af7a748eda8ada74" @@ -2171,6 +2270,13 @@ terminal-link "^2.0.0" v8-to-istanbul "^8.1.0" +"@jest/schemas@^28.0.2": + version "28.0.2" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-28.0.2.tgz#08c30df6a8d07eafea0aef9fb222c5e26d72e613" + integrity sha512-YVDJZjd4izeTDkij00vHHAymNXQ6WWsdChFRK86qck6Jpr3DCL5W3Is3vslviRlP+bLuMYRLbdp98amMvqudhA== + dependencies: + "@sinclair/typebox" "^0.23.3" + "@jest/source-map@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.5.1.tgz#6608391e465add4205eae073b55e7f279e04e8cf" @@ -2231,6 +2337,27 @@ source-map "^0.6.1" write-file-atomic "^3.0.0" +"@jest/transform@^28.1.0": + version "28.1.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-28.1.0.tgz#224a3c9ba4cc98e2ff996c0a89a2d59db15c74ce" + integrity sha512-omy2xe5WxlAfqmsTjTPxw+iXRTRnf+NtX0ToG+4S0tABeb4KsKmPUHq5UBuwunHg3tJRwgEQhEp0M/8oiatLEA== + dependencies: + "@babel/core" "^7.11.6" + "@jest/types" "^28.1.0" + "@jridgewell/trace-mapping" "^0.3.7" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^28.1.0" + jest-regex-util "^28.0.2" + jest-util "^28.1.0" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + write-file-atomic "^4.0.1" + "@jest/types@^27.1.1", "@jest/types@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80" @@ -2242,6 +2369,18 @@ "@types/yargs" "^16.0.0" chalk "^4.0.0" +"@jest/types@^28.1.0": + version "28.1.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-28.1.0.tgz#508327a89976cbf9bd3e1cc74641a29fd7dfd519" + integrity sha512-xmEggMPr317MIOjjDoZ4ejCSr9Lpbt/u34+dvc99t7DS8YirW5rwZEhzKPC2BMUFkUhI48qs6qLUSGw5FuL0GA== + dependencies: + "@jest/schemas" "^28.0.2" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + "@jridgewell/gen-mapping@^0.1.0": version "0.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" @@ -2250,29 +2389,59 @@ "@jridgewell/set-array" "^1.0.0" "@jridgewell/sourcemap-codec" "^1.4.10" +"@jridgewell/gen-mapping@^0.3.0": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz#cf92a983c83466b8c0ce9124fadeaf09f7c66ea9" + integrity sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg== + dependencies: + "@jridgewell/set-array" "^1.0.0" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/resolve-uri@^3.0.3": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz#68eb521368db76d040a6315cdb24bf2483037b9c" - integrity sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew== + version "3.0.7" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz#30cd49820a962aff48c8fffc5cd760151fca61fe" + integrity sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA== "@jridgewell/set-array@^1.0.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.1.tgz#36a6acc93987adcf0ba50c66908bd0b70de8afea" integrity sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ== +"@jridgewell/source-map@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.11" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec" - integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg== + version "1.4.13" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c" + integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w== -"@jridgewell/trace-mapping@^0.3.0": - version "0.3.4" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz#f6a0832dffd5b8a6aaa633b7d9f8e8e94c83a0c3" - integrity sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ== +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== dependencies: "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@jridgewell/trace-mapping@^0.3.7", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.13" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz#dcfe3e95f224c8fe97a87a5235defec999aa92ea" + integrity sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@leichtgewicht/ip-codec@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" + integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== + "@lerna/add@4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@lerna/add/-/add-4.0.0.tgz#c36f57d132502a57b9e7058d1548b7a565ef183f" @@ -2979,26 +3148,26 @@ resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b" integrity sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA== -"@microsoft/api-extractor-model@7.17.2": - version "7.17.2" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.17.2.tgz#033b39a7bac4f3eee3e5ffd406d2af61cedc727e" - integrity sha512-fYfCeBeLm7jnZligC64qHiH4/vzswFLDfyPpX+uKO36OI2kIeMHrYG0zaezmuinKvE4vg1dAz38zZeDbPvBKGg== +"@microsoft/api-extractor-model@7.17.3": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.17.3.tgz#06899902ab1c10b85690232f21c1585cc158d983" + integrity sha512-ETslFxVEZTEK6mrOARxM34Ll2W/5H2aTk9Pe9dxsMCnthE8O/CaStV4WZAGsvvZKyjelSWgPVYGowxGVnwOMlQ== dependencies: "@microsoft/tsdoc" "0.14.1" "@microsoft/tsdoc-config" "~0.16.1" - "@rushstack/node-core-library" "3.45.4" + "@rushstack/node-core-library" "3.45.5" "@microsoft/api-extractor@^7.18.16": - version "7.23.1" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.23.1.tgz#483e339cc73669c709ff215a76eb0e6d9a31de5b" - integrity sha512-J5cTjbMzSZPRZT4AKvFI1KmLGHVhV6bHnFcPo3Og9cN9QmknzpKg5BxvpBecEdFKNZxUpUrBkps2xOQ4Fjc6zg== + version "7.24.2" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.24.2.tgz#4abb24319fa77884dab6d807388056e9cd85488e" + integrity sha512-QWZh9aQZvBAdRVK+Go8NiW8YNMN//OGiNqgA3iZ2sEy8imUqkRBCybXgmw2HkEYyPnn55CFoMKvnAHvV9+4B/A== dependencies: - "@microsoft/api-extractor-model" "7.17.2" + "@microsoft/api-extractor-model" "7.17.3" "@microsoft/tsdoc" "0.14.1" "@microsoft/tsdoc-config" "~0.16.1" - "@rushstack/node-core-library" "3.45.4" + "@rushstack/node-core-library" "3.45.5" "@rushstack/rig-package" "0.3.11" - "@rushstack/ts-command-line" "4.10.10" + "@rushstack/ts-command-line" "4.11.0" colors "~1.2.1" lodash "~4.17.15" resolve "~1.17.0" @@ -3048,9 +3217,9 @@ integrity sha512-3BGrt6FLjqM6br5AhWRKTr3u5GIVkjRYeAFrMp3HjnfICrg4xOrVRwFavKT6tsp++bq5dluL5t8ME/Nha/6c1Q== "@npmcli/fs@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.0.0.tgz#589612cfad3a6ea0feafcb901d29c63fd52db09f" - integrity sha512-8ltnOpRR/oJbOp8vaGUnipOi3bqkcW+sLHFlyXIr08OGHmVJLB1Hn7QtGXbYcpVtH1gAYZTlmDXtE4YV0+AMMQ== + version "1.1.1" + resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.1.1.tgz#72f719fe935e687c56a4faecf3c03d06ba593257" + integrity sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ== dependencies: "@gar/promisify" "^1.0.1" semver "^7.3.5" @@ -3231,13 +3400,13 @@ "@octokit/types" "^6.0.3" "@octokit/core@^3.5.1": - version "3.5.1" - resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.5.1.tgz#8601ceeb1ec0e1b1b8217b960a413ed8e947809b" - integrity sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw== + version "3.6.0" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.6.0.tgz#3376cb9f3008d9b3d110370d90e0a1fcd5fe6085" + integrity sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q== dependencies: "@octokit/auth-token" "^2.4.4" "@octokit/graphql" "^4.5.8" - "@octokit/request" "^5.6.0" + "@octokit/request" "^5.6.3" "@octokit/request-error" "^2.0.5" "@octokit/types" "^6.0.3" before-after-hook "^2.2.0" @@ -3300,16 +3469,16 @@ deprecation "^2.0.0" once "^1.4.0" -"@octokit/request@^5.6.0": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.2.tgz#1aa74d5da7b9e04ac60ef232edd9a7438dcf32d8" - integrity sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA== +"@octokit/request@^5.6.0", "@octokit/request@^5.6.3": + version "5.6.3" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.3.tgz#19a022515a5bba965ac06c9d1334514eb50c48b0" + integrity sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A== dependencies: "@octokit/endpoint" "^6.0.1" "@octokit/request-error" "^2.1.0" "@octokit/types" "^6.16.1" is-plain-object "^5.0.0" - node-fetch "^2.6.1" + node-fetch "^2.6.7" universal-user-agent "^6.0.0" "@octokit/rest@^18.1.0": @@ -3398,10 +3567,10 @@ estree-walker "^2.0.1" picomatch "^2.2.2" -"@rushstack/node-core-library@3.45.4": - version "3.45.4" - resolved "https://registry.yarnpkg.com/@rushstack/node-core-library/-/node-core-library-3.45.4.tgz#a5e1246c462940d16a5acc667c1ffe460b514087" - integrity sha512-FMoEQWjK7nWAO2uFgV1eVpVhY9ZDGOdIIomi9zTej64cKJ+8/Nvu+ny0xKaUDEjw/ALftN2D2ml7L0RDpW/Z9g== +"@rushstack/node-core-library@3.45.5": + version "3.45.5" + resolved "https://registry.yarnpkg.com/@rushstack/node-core-library/-/node-core-library-3.45.5.tgz#00f92143cc21c3ad94fcd81ba168a40ac8cb77f2" + integrity sha512-KbN7Hp9vH3bD3YJfv6RnVtzzTAwGYIBl7y2HQLY4WEQqRbvE3LgI78W9l9X+cTAXCX//p0EeoiUYNTFdqJrMZg== dependencies: "@types/node" "12.20.24" colors "~1.2.1" @@ -3421,10 +3590,10 @@ resolve "~1.17.0" strip-json-comments "~3.1.1" -"@rushstack/ts-command-line@4.10.10": - version "4.10.10" - resolved "https://registry.yarnpkg.com/@rushstack/ts-command-line/-/ts-command-line-4.10.10.tgz#69da17b03ce57795b67ea2aabf7c976c81816078" - integrity sha512-F+MH7InPDXqX40qvvcEsnvPpmg566SBpfFqj2fcCh8RjM6AyOoWlXc8zx7giBD3ZN85NVAEjZAgrcLU0z+R2yg== +"@rushstack/ts-command-line@4.11.0": + version "4.11.0" + resolved "https://registry.yarnpkg.com/@rushstack/ts-command-line/-/ts-command-line-4.11.0.tgz#4cd3b9f59b41aed600042936260fdaa55ca0184d" + integrity sha512-ptG9L0mjvJ5QtK11GsAFY+jGfsnqHDS6CY6Yw1xT7a9bhjfNYnf6UPwjV+pF6UgiucfNcMDNW9lkDLxvZKKxMg== dependencies: "@types/argparse" "1.0.38" argparse "~1.0.9" @@ -3448,6 +3617,11 @@ resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== +"@sinclair/typebox@^0.23.3": + version "0.23.5" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.23.5.tgz#93f7b9f4e3285a7a9ade7557d9a8d36809cbc47d" + integrity sha512-AFBVi/iT4g20DHoujvMH1aEDn8fGJh4xsRGCP6d8RpLPMqsNPvW01Jcn0QysXTsg++/xj25NmJsGyH9xug/wKg== + "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -3461,9 +3635,9 @@ type-detect "4.0.8" "@sinonjs/fake-timers@^8.0.1": - version "8.0.1" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-8.0.1.tgz#1c1c9a91419f804e59ae8df316a07dd1c3a76b94" - integrity sha512-AU7kwFxreVd6OAXcAFlKSmZquiRUU0FvYm44k1Y1QbK7Co4m0aqfGMhjykIeQp/H6rcl+nFmj0zfdUcGVs9Dew== + version "8.1.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz#3fdc2b6cb58935b21bfb8d1625eb1300484316e7" + integrity sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg== dependencies: "@sinonjs/commons" "^1.7.0" @@ -3581,116 +3755,115 @@ "@svgr/plugin-jsx" "^6.2.1" "@svgr/plugin-svgo" "^6.2.0" -"@swc-node/core@^1.8.2": - version "1.8.2" - resolved "https://registry.yarnpkg.com/@swc-node/core/-/core-1.8.2.tgz#950ad394a8e8385658e6a951ec554bbf61a1693e" - integrity sha512-IoJ7tGHQ6JOMSmFe4VhP64uLmFKMNasS0QEgUrLFQ0h/dTvpQMynnoGBEJoPL6LfsebZ/q4uKqbpWrth6/yrAA== +"@swc-node/core@^1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@swc-node/core/-/core-1.9.0.tgz#f5208d575c1aed5a2cab7e4c04e46aca34d8c240" + integrity sha512-vRnvsMtL9OxybA/Wun1ZhlDvB6MNs4Zujnina0VKdGk+yI6s87KUhdTcbAY6dQMZhQTLFiC1Lnv/BuwCKcCEug== dependencies: - "@swc/core" "^1.2.119" + "@swc/core" "^1.2.172" "@swc-node/register@^1.4.2": - version "1.4.2" - resolved "https://registry.yarnpkg.com/@swc-node/register/-/register-1.4.2.tgz#98801cc5ad8792519511bd6ae31c01f40aa487a3" - integrity sha512-wLZz0J7BTO//1Eq7e4eBQjKF380Hr2eVemz849msQSKcVM1D7UJUt/dP2TinEVGx++/BXJ/0q37i6n9Iw0EM0w== + version "1.5.1" + resolved "https://registry.yarnpkg.com/@swc-node/register/-/register-1.5.1.tgz#8927783c1a53207ded076d8700270f7941aa0305" + integrity sha512-6IL5s4QShKGs08qAeNou3rDA3gbp2WHk6fo0XnJXQn/aC9k6FnVBbj/thGOIEDtgNhC/DKpZT8tCY1LpQnOZFg== dependencies: - "@swc-node/core" "^1.8.2" - "@swc-node/sourcemap-support" "^0.1.11" - chalk "4" - debug "^4.3.3" - pirates "^4.0.4" - tslib "^2.3.1" - typescript "^4.5.3" + "@swc-node/core" "^1.9.0" + "@swc-node/sourcemap-support" "^0.2.0" + colorette "^2.0.16" + debug "^4.3.4" + pirates "^4.0.5" + tslib "^2.4.0" -"@swc-node/sourcemap-support@^0.1.11": - version "0.1.11" - resolved "https://registry.yarnpkg.com/@swc-node/sourcemap-support/-/sourcemap-support-0.1.11.tgz#50cda396baade0636e8f53596b7a66386490c06d" - integrity sha512-b+Mn3oQl+7nUSt7hPzIbY9B30YhcFo1PT4kd9P4QmD6raycmIealOAhAdZID/JevphzsOXHQB4OqJm7Yi5tMcA== +"@swc-node/sourcemap-support@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@swc-node/sourcemap-support/-/sourcemap-support-0.2.0.tgz#e9079f739921fbe5c49d85791703fcb1540c356b" + integrity sha512-FNrxdI6XMYfoNt81L8eFKEm1d8P82I1nPwS3MrnBGzZoMWB+seQhQK+iN6M5RreJxXbfZw5lF86LRjHEQeGMqg== dependencies: source-map-support "^0.5.21" -"@swc/core-android-arm-eabi@1.2.179": - version "1.2.179" - resolved "https://registry.yarnpkg.com/@swc/core-android-arm-eabi/-/core-android-arm-eabi-1.2.179.tgz#6eadaf552e4340206b949844c85e8d7de323594a" - integrity sha512-86a0zDxgT+9xwakvAo14YmPF2H34i3nG/Vfq4WLXV5JRNQgylMIFMVWPMmCp4pRFeFnM+XunkepADoc9cxd7cg== - -"@swc/core-android-arm64@1.2.179": - version "1.2.179" - resolved "https://registry.yarnpkg.com/@swc/core-android-arm64/-/core-android-arm64-1.2.179.tgz#db548fdb5746c863d4307961ef16c3a31e2687ad" - integrity sha512-Se+b84pXxQ9t+w5gAs+U8htxc/ry7xfGGpalo7+KSzH96rsQPcuBL2MIeOxrL/E68eVsUk5RF457FoAkCobI2A== - -"@swc/core-darwin-arm64@1.2.179": - version "1.2.179" - resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.2.179.tgz#e5e73f1349e764f3502c5cd9965070eeadfe6158" - integrity sha512-Jj0ZoIXpgt+/9a6GD/L68uuoMG4Lnq4wAp/n9gQQPw5CwiLuhZELPBqsrjfKVz/I/Iz24IbAJcEEZ3iaODaxdA== - -"@swc/core-darwin-x64@1.2.179": - version "1.2.179" - resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.2.179.tgz#244ffacee94c408a60c832c4499d352652f4cf58" - integrity sha512-GBF4BPFn170l1oZDBsNaZpiyPdyIXQmDOXtg8LGVFHvFire4n2jgjw/i6Fh4sefi1B+lc1LP6KmfOuMhLaBukg== - -"@swc/core-freebsd-x64@1.2.179": - version "1.2.179" - resolved "https://registry.yarnpkg.com/@swc/core-freebsd-x64/-/core-freebsd-x64-1.2.179.tgz#7bfd7bf367a54bc2d5d128694c8dbc9b7c4af92d" - integrity sha512-2ooBzQ4iEyuXZLz6iTyu5YW4rKIOSxZbP6UbrFT8aX/FLypBktkeKyad+4WpXQNC5vRxks1VUKS9eNh2BvbWwA== - -"@swc/core-linux-arm-gnueabihf@1.2.179": - version "1.2.179" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.2.179.tgz#64129b7f9e93d3e8f4f059c6122c03616d09098d" - integrity sha512-Pf0r7eUYViCWnlTOx8LjceA3r+XGa0GXXEUfwLjQ8wZQUEhNN02hsCz6F2d9Q3WYkzNJVYXu87I6BUY+L9GWAQ== - -"@swc/core-linux-arm64-gnu@1.2.179": - version "1.2.179" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.2.179.tgz#e7b353504a9343df29009e61a29fec4bf2997264" - integrity sha512-Dqx48DJvxI0r7yFCZkopOo8/AVNlep/05BYxXv7UzZSiJpiYS8pAGwuboeOJwF83aaW7hT4vx+HLUDvUTTfSWQ== - -"@swc/core-linux-arm64-musl@1.2.179": - version "1.2.179" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.2.179.tgz#f813524f0f38f7ba1349b12507f87d4f775453df" - integrity sha512-wHYvSsP/qTQwVJKBBK1duUvbySHYL7BL8ge+IcAEjTy62K38z0mPg9j2nSqeSldBi7y1foudbKqUA9qwoAC9oQ== - -"@swc/core-linux-x64-gnu@1.2.179": - version "1.2.179" - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.2.179.tgz#db29058624383990f160a8c1153702892bf1057b" - integrity sha512-orVaK4BIa4qIW298uxvsKaeQLHqjZpxbaCATOnFibUBx2nX+P/MTHZm3WB1qgdmeKto8SEyFGkV8PAMcbFu5Rg== - -"@swc/core-linux-x64-musl@1.2.179": - version "1.2.179" - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.2.179.tgz#92cd76007443753d1bda7540fcbffad626d677b6" - integrity sha512-UG2zrpg5C0iq0BwSJpoxMgraM2jt9CItCRVaiZki7kg0wuIIdjwjXTOuf7XJ939WefLVrB0fu9uVKLfZAzuuxA== - -"@swc/core-win32-arm64-msvc@1.2.179": - version "1.2.179" - resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.2.179.tgz#66239757c57374b5a3e11b7c540d5fd5e5a41891" - integrity sha512-am0P4A/7gDrU/HlGthf2Ozxfm8/zduOdigMD/ynTgEv11+gwWVnmr+sVR1l83BnXp3H765/LoC2eu8UiAbjGHA== - -"@swc/core-win32-ia32-msvc@1.2.179": - version "1.2.179" - resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.2.179.tgz#0d1acff7ed62c35af92ee4b3478d2c7e9d0789fb" - integrity sha512-Do7Y+nMhF3+0rFl6pmtQJ6DqCbliAHpSIKx/eC3NzspS4qPSddWwcLgajWl22ueouAj/79rx+FYUSRCNOHpjTg== - -"@swc/core-win32-x64-msvc@1.2.179": - version "1.2.179" - resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.2.179.tgz#b943acee73a42763b9734a70a89d59a1228ecd14" - integrity sha512-xA/pd6ri0eJ1bqQRT8h0xVa1wclFvLddp5mUhTEfxhtajrPkdriEUCoFOo4ySJhz86cjpTIoa81iq3XLpGQsMQ== - -"@swc/core@^1.2.119", "@swc/core@^1.2.146", "@swc/core@^1.2.159": - version "1.2.179" - resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.2.179.tgz#9256b4d20a10b4b7d85e2b0fd7fc67aeaed2eb95" - integrity sha512-B1O4acip37cNfMxKYG9Ptrrmcc3mcklFnSuRT9UtHr92Nq26o7omuturK0HCoKqLVReU05psfhDzx+K6H1tbNQ== +"@swc/core-android-arm-eabi@1.2.196": + version "1.2.196" + resolved "https://registry.yarnpkg.com/@swc/core-android-arm-eabi/-/core-android-arm-eabi-1.2.196.tgz#64f58652c4f8076c9e91b8c0f10035c516d02f9c" + integrity sha512-rWM909UT01+CWxvOkQ7f6bhtceFz/jBuVhYqtOjkDleMV6UsKVfMOAkAMQBfvQmoQzvqddypCDl5tOZIoj3O0w== + +"@swc/core-android-arm64@1.2.196": + version "1.2.196" + resolved "https://registry.yarnpkg.com/@swc/core-android-arm64/-/core-android-arm64-1.2.196.tgz#a4cf6311a79b52ffa64608a202a7fea280dbc4d8" + integrity sha512-SPNMBcziCev0B439raRC2KpRrqiw6Jw8Bvw5Swrra34kUHjxxEYbxHeFBdUA0Ka1YoMJ95gCEW9fsqTlPkYBIQ== + +"@swc/core-darwin-arm64@1.2.196": + version "1.2.196" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.2.196.tgz#bd9f659642d02a7b2b5369457f46502e75740fbd" + integrity sha512-Sd22WY9frsbUQVay9LTakqFtkOnzkWw+PB1iwcpBzenOVQxbQ8i7JlxcujTkMFc2J/SAKDelq+M4TE6JEdfU6A== + +"@swc/core-darwin-x64@1.2.196": + version "1.2.196" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.2.196.tgz#8ed3f92003ddbc795796c5cbfea9a6a16be3f268" + integrity sha512-1z0ROEMIKjAqEc/jNdZwcdgWzUqw/mHmhQABm1J6lUf3UEucUAy/4cniWPHXKKRCdj7Eq7kHtU52ynQpB/ii0Q== + +"@swc/core-freebsd-x64@1.2.196": + version "1.2.196" + resolved "https://registry.yarnpkg.com/@swc/core-freebsd-x64/-/core-freebsd-x64-1.2.196.tgz#d4d988bfe11d2c7ccf1b3b2970b33baf631ca8cb" + integrity sha512-KjUo4Vgs7AuGhLJCE5yeVazTUpoiRNuaLbRxnXIC7Ua7T4JpnO9lc34aWWUhz8Gu7QLEWpLFMM52W+bwVeBi7A== + +"@swc/core-linux-arm-gnueabihf@1.2.196": + version "1.2.196" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.2.196.tgz#11d705c3a08756a57eaf48d41dfacfab1c6b2139" + integrity sha512-n7V9GyPQ7H6UvJKB15K0vHek2WihbPdv866h2LG1Lrw5mxxDs5A4o7hj4scKF355kjyj9LI+4GykT3R9MpIWzw== + +"@swc/core-linux-arm64-gnu@1.2.196": + version "1.2.196" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.2.196.tgz#6c71a44abe2120fa0199fa5ac79f2ba8c2c489e0" + integrity sha512-1ToeE8/5Ew8HEa3GQf9znijzpmNf5jnnU39mrO0dpmhiUJVgRU/IBoe45t0I8R84PRDfayqoSfq0vPt7dWSjdQ== + +"@swc/core-linux-arm64-musl@1.2.196": + version "1.2.196" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.2.196.tgz#e805fb06e41361b25eb54dc1e44c8fcb9ece5512" + integrity sha512-93Pvb0lpgL/B7Em+qAScYsf4QvE4OmuTQ+aXRz4VsKiw/+DQKt5jUmCzkYa4ecSvSur3rlqFLMU8ufPI7EF22g== + +"@swc/core-linux-x64-gnu@1.2.196": + version "1.2.196" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.2.196.tgz#b8b7e06c79ccc7111a93bccc89e422992615cbd6" + integrity sha512-JZkQ/ETPCNae8hOOfVOBHJuy9vhSJwdzWFO1Kd8PhyDyCi0caNX8Tu3mgGTZJ0UToP0ot7mC945+1w4lcuQPBA== + +"@swc/core-linux-x64-musl@1.2.196": + version "1.2.196" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.2.196.tgz#e20272e9a2dba241641cade3a33c7d5514557854" + integrity sha512-TJAfEf7l79mceXO3AXaf4Lun8ZjjaHXMlQe/3QrtblxKUFeHgFDbQeabjcgsYyNzAffPXDLsKVvmC4GJTu35DQ== + +"@swc/core-win32-arm64-msvc@1.2.196": + version "1.2.196" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.2.196.tgz#0c53dcbcfd15d476d9ebba060194d70a8df07f6f" + integrity sha512-WDQ9HZZ8SrInw2kisBPbNg8W0IgA8P9eGijQeigyvT2rT81A/Gj9G57YMq0fQclcodBLr6SJPDIHh4fC8JInFg== + +"@swc/core-win32-ia32-msvc@1.2.196": + version "1.2.196" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.2.196.tgz#fc287cb4dd6aae8fb260cb5125a09f2b2a286d54" + integrity sha512-c355907n5RCeuF99/3nFmJdiw4Ask0BwH7hs+4Y1dcOzC/FYvh2TmYZ+VTJzL78TiIekmvi4buxGqFvHePZ2Pw== + +"@swc/core-win32-x64-msvc@1.2.196": + version "1.2.196" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.2.196.tgz#12ecbf5020f9a6db653c20ed74f5077988168ba4" + integrity sha512-zQKrvEDmTqMd1lwbQ4KcBVKQ2OVoQlX1I/kZNISZlh/+UhBpKnkqQme/76wtILH9r0Lz+ujumL2ZvwoVAzAJkQ== + +"@swc/core@^1.2.146", "@swc/core@^1.2.159", "@swc/core@^1.2.172": + version "1.2.196" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.2.196.tgz#95a8b1e0609061d46e18580a3ff2fc67efa78e7d" + integrity sha512-395byH+v71OwJpXIvt+FZJZeF20Cs+LwYkURpkkmN5aKImdTuCqnNqapWsh3nfuIgDdC5k8QvrGEQNTmE8+cTw== optionalDependencies: - "@swc/core-android-arm-eabi" "1.2.179" - "@swc/core-android-arm64" "1.2.179" - "@swc/core-darwin-arm64" "1.2.179" - "@swc/core-darwin-x64" "1.2.179" - "@swc/core-freebsd-x64" "1.2.179" - "@swc/core-linux-arm-gnueabihf" "1.2.179" - "@swc/core-linux-arm64-gnu" "1.2.179" - "@swc/core-linux-arm64-musl" "1.2.179" - "@swc/core-linux-x64-gnu" "1.2.179" - "@swc/core-linux-x64-musl" "1.2.179" - "@swc/core-win32-arm64-msvc" "1.2.179" - "@swc/core-win32-ia32-msvc" "1.2.179" - "@swc/core-win32-x64-msvc" "1.2.179" + "@swc/core-android-arm-eabi" "1.2.196" + "@swc/core-android-arm64" "1.2.196" + "@swc/core-darwin-arm64" "1.2.196" + "@swc/core-darwin-x64" "1.2.196" + "@swc/core-freebsd-x64" "1.2.196" + "@swc/core-linux-arm-gnueabihf" "1.2.196" + "@swc/core-linux-arm64-gnu" "1.2.196" + "@swc/core-linux-arm64-musl" "1.2.196" + "@swc/core-linux-x64-gnu" "1.2.196" + "@swc/core-linux-x64-musl" "1.2.196" + "@swc/core-win32-arm64-msvc" "1.2.196" + "@swc/core-win32-ia32-msvc" "1.2.196" + "@swc/core-win32-x64-msvc" "1.2.196" "@swc/jest@^0.2.20": version "0.2.21" @@ -3758,9 +3931,9 @@ "@types/babel__traverse" "*" "@types/babel__generator@*": - version "7.6.3" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.3.tgz#f456b4b2ce79137f768aa130d2423d2f0ccfaba5" - integrity sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA== + version "7.6.4" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7" + integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== dependencies: "@babel/types" "^7.0.0" @@ -3773,9 +3946,9 @@ "@babel/types" "^7.0.0" "@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.14.2.tgz#ffcd470bbb3f8bf30481678fb5502278ca833a43" - integrity sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA== + version "7.17.1" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.17.1.tgz#1a0e73e8c28c7e832656db372b779bfd2ef37314" + integrity sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA== dependencies: "@babel/types" "^7.3.0" @@ -3830,9 +4003,9 @@ integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== "@types/eslint@*": - version "7.28.2" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.28.2.tgz#0ff2947cdd305897c52d5372294e8c76f351db68" - integrity sha512-KubbADPkfoU75KgKeKLsFHXnU4ipH7wYg0TRT33NK3N3yiu7jlFAAoygIWBV+KbuHx/G+AvuGX6DllnK35gfJA== + version "8.4.2" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.2.tgz#48f2ac58ab9c631cb68845c3d956b28f79fad575" + integrity sha512-Z1nseZON+GEnFjJc04sv4NSALGjhFwy6K0HXt7qsn5ArfAKtb63dXNJHf+1YW6IpOIYRBGUbu3GwJdj8DGnCjA== dependencies: "@types/estree" "*" "@types/json-schema" "*" @@ -3874,7 +4047,7 @@ "@types/minimatch" "*" "@types/node" "*" -"@types/graceful-fs@^4.1.2": +"@types/graceful-fs@^4.1.2", "@types/graceful-fs@^4.1.3": version "4.1.5" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== @@ -3888,20 +4061,20 @@ dependencies: "@types/unist" "*" -"@types/history@*", "@types/history@^4.7.11": +"@types/history@^4.7.11": version "4.7.11" resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64" integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA== "@types/html-minifier-terser@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.0.0.tgz#563c1c6c132cd204e71512f9c0b394ff90d3fae7" - integrity sha512-NZwaaynfs1oIoLAV1vg18e7QMVDvw+6SQrdJc8w3BwUaoroVSf6EBj/Sk4PBWGxsq0dzhA2drbsuMC1/6C6KgQ== + version "6.1.0" + resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" + integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== -"@types/http-proxy@^1.17.5": - version "1.17.7" - resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.7.tgz#30ea85cc2c868368352a37f0d0d3581e24834c6f" - integrity sha512-9hdj6iXH64tHSLTY+Vt2eYOGzSogC+JQ2H7bdPWkuh7KXP5qLllWx++t+K9Wk556c3dkDdPws/SpMRi0sdCT1w== +"@types/http-proxy@^1.17.8": + version "1.17.9" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.9.tgz#7f0e7931343761efde1e2bf48c40f02f3f75705a" + integrity sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw== dependencies: "@types/node" "*" @@ -3911,9 +4084,9 @@ integrity sha512-4j5G9Y5jljDSICQ1R2f/Rcyoj6DZmYGneny+p/cDkjep0rkqNg0W73Ty0bVjMUTZgLXHf8oiMjg1XC3CDwCz+g== "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" - integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== "@types/istanbul-lib-report@*": version "3.0.0" @@ -3937,9 +4110,9 @@ "@types/jest" "*" "@types/jest@*", "@types/jest@^27.0.2": - version "27.5.0" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.5.0.tgz#e04ed1824ca6b1dd0438997ba60f99a7405d4c7b" - integrity sha512-9RBFx7r4k+msyj/arpfaa0WOOEcaAZNmN+j80KFbFCoSqCJGHTz7YMAMGQW9Xmqm5w6l5c25vbSjMwlikJi5+g== + version "27.5.1" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.5.1.tgz#2c8b6dc6ff85c33bcd07d0b62cb3d19ddfdb3ab9" + integrity sha512-fUy7YRpT+rHXto1YlL+J9rs0uLGyiqVt3ZOTQR+4ROc47yNl8WLdVLgUloBRhOxP1PZvguHl44T3H0wAWxahYQ== dependencies: jest-matcher-utils "^27.0.0" pretty-format "^27.0.0" @@ -3952,14 +4125,19 @@ "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" - integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== "@types/lodash@*", "@types/lodash@^4.14.176": version "4.14.182" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.182.tgz#05301a4d5e62963227eaafe0ce04dd77c54ea5c2" integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q== -"@types/marked@*", "@types/marked@^3.0.2": +"@types/marked@*": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/marked/-/marked-4.0.3.tgz#2098f4a77adaba9ce881c9e0b6baf29116e5acc4" + integrity sha512-HnMWQkLJEf/PnxZIfbm0yGJRRZYYMhb++O9M36UCTA9z53uPvVoSlAwJr3XOpDEryb7Hwl1qAx/MV6YIW1RXxg== + +"@types/marked@^3.0.2": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/marked/-/marked-3.0.3.tgz#37878f405d5f0cff0e6128cea330bd0aa8df8cb3" integrity sha512-ZgAr847Wl68W+B0sWH7F4fDPxTzerLnRuUXjUpp1n4NjGSs8hgPAjAp7NQIXblG34MXTrf5wWkAK8PVJ2LIlVg== @@ -3999,9 +4177,9 @@ "@types/node" "*" "@types/node@*", "@types/node@12.20.24", "@types/node@>=12", "@types/node@^14.14.31", "@types/node@^16.11.4": - version "16.11.4" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.4.tgz#90771124822d6663814f7c1c9b45a6654d8fd964" - integrity sha512-TMgXmy0v2xWyuCSCJM6NCna2snndD8yvQF67J29ipdzMcsPa9u+o0tjF5+EQNdhcuZplYuouYqpc4zcd5I6amQ== + version "16.11.38" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.38.tgz#be0edd097b23eace6c471c525a74b3f98803017f" + integrity sha512-hjO/0K140An3GWDw2HJfq7gko3wWeznbjXgg+rzPdVzhe198hp4x2i1dgveAOEiFKd8sOilAxzoSJiVv5P/CUg== "@types/normalize-package-data@^2.4.0": version "2.4.1" @@ -4019,14 +4197,14 @@ integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== "@types/prettier@*", "@types/prettier@^2.1.5", "@types/prettier@^2.4.2": - version "2.6.0" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.6.0.tgz#efcbd41937f9ae7434c714ab698604822d890759" - integrity sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw== + version "2.6.3" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.6.3.tgz#68ada76827b0010d0db071f739314fa429943d0a" + integrity sha512-ymZk3LEC/fsut+/Q5qejp6R9O1rMxz3XaRHDV6kX8MrGAhOSPqVARbDi+EZvInBpw+BnCX3TD240byVkOfQsHg== "@types/prop-types@*": - version "15.7.4" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" - integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ== + version "15.7.5" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" + integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== "@types/qs@*": version "6.9.7" @@ -4046,11 +4224,11 @@ "@types/react" "*" "@types/react-router-config@*": - version "5.0.3" - resolved "https://registry.yarnpkg.com/@types/react-router-config/-/react-router-config-5.0.3.tgz#72a53561bcb5e13b82c576527b818fa2579591c7" - integrity sha512-38vpjXic0+E2sIBEKUe+RrCmbc8RqcQhNV8OmU3KUcwgy/yzTeo67MhllP+0zjZWNr7Lhw+RnUkL0hzkf63nUQ== + version "5.0.6" + resolved "https://registry.yarnpkg.com/@types/react-router-config/-/react-router-config-5.0.6.tgz#87c5c57e72d241db900d9734512c50ccec062451" + integrity sha512-db1mx37a1EJDf1XeX8jJN7R3PZABmJQXR8r28yUjVMFSjkmnQo6X6pOEEmNl+Tp2gYQOGPdYbFIipBtdElZ3Yg== dependencies: - "@types/history" "*" + "@types/history" "^4.7.11" "@types/react" "*" "@types/react-router" "*" @@ -4064,17 +4242,17 @@ "@types/react-router" "*" "@types/react-router@*": - version "5.1.17" - resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.17.tgz#087091006213b11042f39570e5cd414863693968" - integrity sha512-RNSXOyb3VyRs/EOGmjBhhGKTbnN6fHWvy5FNLzWfOWOGjgVUKqJZXfpKzLmgoU8h6Hj8mpALj/mbXQASOb92wQ== + version "5.1.18" + resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.18.tgz#c8851884b60bc23733500d86c1266e1cfbbd9ef3" + integrity sha512-YYknwy0D0iOwKQgz9v8nOzt2J6l4gouBmDnWqUUznltOTaon+r8US8ky8HvN0tXvc38U9m6z/t2RsVsnd1zM0g== dependencies: - "@types/history" "*" + "@types/history" "^4.7.11" "@types/react" "*" "@types/react@*", "@types/react@^18.0.9": - version "18.0.9" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.9.tgz#d6712a38bd6cd83469603e7359511126f122e878" - integrity sha512-9bjbg1hJHUm4De19L1cHiW0Jvx3geel6Qczhjd0qY5VKVE2X5+x77YxAepuCwVh4vrgZJdgEJw48zrhRIeF4Nw== + version "18.0.10" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.10.tgz#5692944d4a45e204fb7a981eb1388afe919cf4d0" + integrity sha512-dIugadZuIPrRzvIEevIu7A1smqOAjkSMv8qOfwPt9Ve6i6JT/FQcCHyk2qIAxwsQNKZt5/oGR0T4z9h2dXRAkg== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -4087,10 +4265,10 @@ dependencies: "@types/node" "*" -"@types/retry@^0.12.0": - version "0.12.1" - resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065" - integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g== +"@types/retry@0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" + integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== "@types/rimraf@^3.0.2": version "3.0.2" @@ -4157,17 +4335,17 @@ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== -"@types/ws@^8.2.2": - version "8.2.2" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.2.2.tgz#7c5be4decb19500ae6b3d563043cd407bf366c21" - integrity sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg== +"@types/ws@^8.5.1": + version "8.5.3" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d" + integrity sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w== dependencies: "@types/node" "*" "@types/yargs-parser@*": - version "20.2.1" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129" - integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw== + version "21.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" + integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== "@types/yargs@^16.0.0": version "16.0.4" @@ -4176,10 +4354,17 @@ dependencies: "@types/yargs-parser" "*" +"@types/yargs@^17.0.8": + version "17.0.10" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.10.tgz#591522fce85d8739bca7b8bb90d048e4478d186a" + integrity sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA== + dependencies: + "@types/yargs-parser" "*" + "@types/yauzl@^2.9.1": - version "2.9.2" - resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.9.2.tgz#c48e5d56aff1444409e39fa164b0b4d4552a7b7a" - integrity sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA== + version "2.10.0" + resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.0.tgz#b3248295276cf8c6f153ebe6a9aba0c988cb2599" + integrity sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw== dependencies: "@types/node" "*" @@ -4323,22 +4508,22 @@ JSONStream@^1.0.4: through ">=2.2.7 <3" abab@^2.0.3, abab@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" - integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== + version "2.0.6" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" + integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" + mime-types "~2.1.34" + negotiator "0.6.3" acorn-globals@^6.0.0: version "6.0.0" @@ -4353,7 +4538,7 @@ acorn-import-assertions@^1.7.6: resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== -acorn-jsx@^5.3.1: +acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== @@ -4373,20 +4558,20 @@ acorn@^7.1.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.0.4, acorn@^8.2.4, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.0: - version "8.7.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" - integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== +acorn@^8.0.4, acorn@^8.2.4, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.1: + version "8.7.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" + integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== add-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" - integrity sha1-anmQQ3ynNtXhKI25K9MmbV9csqo= + integrity sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ== address@^1.0.1, address@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" - integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA== + version "1.2.0" + resolved "https://registry.yarnpkg.com/address/-/address-1.2.0.tgz#d352a62c92fee90f89a693eccd2a8b2139ab02d9" + integrity sha512-tNEZYz5G/zYunxFm7sfhAxkXEuLj3K6BKwv6ZURlsF6yiUQ65z0Q2wZW9L5cPUl9ocofGvXOdFYbFHp0+6MOig== agent-base@6, agent-base@^6.0.2: version "6.0.2" @@ -4396,9 +4581,9 @@ agent-base@6, agent-base@^6.0.2: debug "4" agentkeepalive@^4.1.3: - version "4.1.4" - resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.1.4.tgz#d928028a4862cb11718e55227872e842a44c945b" - integrity sha512-+V/rGa3EuU74H6wR04plBb7Ks10FbtUQgRj/FQOG7uUIEuaINI+AiqJR1k6t3SVNs7o7ZjIdus6706qqzVq8jQ== + version "4.2.1" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.2.1.tgz#a7975cbb9f83b367f06c90cc51ff28fe7d499717" + integrity sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA== dependencies: debug "^4.1.0" depd "^1.1.2" @@ -4442,41 +4627,41 @@ ajv@^6.10.0, ajv@^6.12.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.12.6, aj uri-js "^4.2.2" ajv@^8.0.0, ajv@^8.8.0: - version "8.8.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.8.2.tgz#01b4fef2007a28bf75f0b7fc009f62679de4abbb" - integrity sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw== + version "8.11.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f" + integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" require-from-string "^2.0.2" uri-js "^4.2.2" -algoliasearch-helper@^3.7.4: - version "3.7.4" - resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.7.4.tgz#3812ea161da52463ec88da52612c9a363c1b181d" - integrity sha512-KmJrsHVm5TmxZ9Oj53XdXuM4CQeu7eVFnB15tpSFt+7is1d1yVCv3hxCLMqYSw/rH42ccv013miQpRr268P8vw== +algoliasearch-helper@^3.8.2: + version "3.8.2" + resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.8.2.tgz#35726dc6d211f49dbab0bf6d37b4658165539523" + integrity sha512-AXxiF0zT9oYwl8ZBgU/eRXvfYhz7cBA5YrLPlw9inZHdaYF0QEya/f1Zp1mPYMXc1v6VkHwBq4pk6/vayBLICg== dependencies: "@algolia/events" "^4.0.1" -algoliasearch@^4.0.0, algoliasearch@^4.13.0: - version "4.13.0" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.13.0.tgz#e36611fda82b1fc548c156ae7929a7f486e4b663" - integrity sha512-oHv4faI1Vl2s+YC0YquwkK/TsaJs79g2JFg5FDm2rKN12VItPTAeQ7hyJMHarOPPYuCnNC5kixbtcqvb21wchw== - dependencies: - "@algolia/cache-browser-local-storage" "4.13.0" - "@algolia/cache-common" "4.13.0" - "@algolia/cache-in-memory" "4.13.0" - "@algolia/client-account" "4.13.0" - "@algolia/client-analytics" "4.13.0" - "@algolia/client-common" "4.13.0" - "@algolia/client-personalization" "4.13.0" - "@algolia/client-search" "4.13.0" - "@algolia/logger-common" "4.13.0" - "@algolia/logger-console" "4.13.0" - "@algolia/requester-browser-xhr" "4.13.0" - "@algolia/requester-common" "4.13.0" - "@algolia/requester-node-http" "4.13.0" - "@algolia/transporter" "4.13.0" +algoliasearch@^4.0.0, algoliasearch@^4.13.1: + version "4.13.1" + resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.13.1.tgz#54195c41c9e4bd13ed64982248cf49d4576974fe" + integrity sha512-dtHUSE0caWTCE7liE1xaL+19AFf6kWEcyn76uhcitWpntqvicFHXKFoZe5JJcv9whQOTRM6+B8qJz6sFj+rDJA== + dependencies: + "@algolia/cache-browser-local-storage" "4.13.1" + "@algolia/cache-common" "4.13.1" + "@algolia/cache-in-memory" "4.13.1" + "@algolia/client-account" "4.13.1" + "@algolia/client-analytics" "4.13.1" + "@algolia/client-common" "4.13.1" + "@algolia/client-personalization" "4.13.1" + "@algolia/client-search" "4.13.1" + "@algolia/logger-common" "4.13.1" + "@algolia/logger-console" "4.13.1" + "@algolia/requester-browser-xhr" "4.13.1" + "@algolia/requester-common" "4.13.1" + "@algolia/requester-node-http" "4.13.1" + "@algolia/transporter" "4.13.1" all-contributors-cli@^6.20.0: version "6.20.0" @@ -4502,9 +4687,9 @@ ansi-align@^3.0.0, ansi-align@^3.0.1: string-width "^4.1.0" ansi-colors@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== ansi-escapes@^3.2.0: version "3.2.0" @@ -4526,17 +4711,17 @@ ansi-html-community@^0.0.8: ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" + integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" + integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== ansi-regex@^5.0.1: version "5.0.1" @@ -4636,9 +4821,9 @@ array-differ@^3.0.0: array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== -array-flatten@^2.1.0: +array-flatten@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== @@ -4646,16 +4831,16 @@ array-flatten@^2.1.0: array-ify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" - integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4= + integrity sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng== -array-includes@^3.1.3, array-includes@^3.1.4: - version "3.1.4" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.4.tgz#f5b493162c760f3539631f005ba2bb46acb45ba9" - integrity sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw== +array-includes@^3.1.4, array-includes@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.5.tgz#2c320010db8d31031fd2a5f6b3bbd4b1aad31bdb" + integrity sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" + define-properties "^1.1.4" + es-abstract "^1.19.5" get-intrinsic "^1.1.1" is-string "^1.0.7" @@ -4669,33 +4854,41 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array-union@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-3.0.1.tgz#da52630d327f8b88cfbfb57728e2af5cd9b6b975" - integrity sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw== - array.prototype.flat@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz#07e0975d84bbc7c48cd1879d609e682598d33e13" - integrity sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg== + version "1.3.0" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz#0b0c1567bf57b38b56b4c97b8aa72ab45e4adc7b" + integrity sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw== dependencies: call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.19.0" + es-abstract "^1.19.2" + es-shim-unscopables "^1.0.0" -array.prototype.flatmap@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz#908dc82d8a406930fdf38598d51e7411d18d4446" - integrity sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA== +array.prototype.flatmap@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz#a7e8ed4225f4788a70cd910abcf0791e76a5534f" + integrity sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg== dependencies: - call-bind "^1.0.0" + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.19.0" + es-abstract "^1.19.2" + es-shim-unscopables "^1.0.0" + +array.prototype.reduce@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.4.tgz#8167e80089f78bff70a99e20bd4201d4663b0a6f" + integrity sha512-WnM+AjG/DvLRLo4DDl+r+SvCzYtD2Jd9oeBYMcEaI7t3fFrHY9M53/wdLcTvmZNQ70IU6Htj0emFkZ5TS+lrdw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.2" + es-array-method-boxes-properly "^1.0.0" + is-string "^1.0.7" arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== arrify@^2.0.1: version "2.0.1" @@ -4705,37 +4898,30 @@ arrify@^2.0.1: asap@^2.0.0, asap@~2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= + integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== dependencies: safer-buffer "~2.1.0" assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== ast-types-flow@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" - integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= + integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag== astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== -async@^2.6.2: - version "2.6.4" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" - integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== - dependencies: - lodash "^4.17.14" - async@^3.0.1, async@^3.2.0, async@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/async/-/async-3.2.3.tgz#ac53dafd3f4720ee9e8a160628f18ea91df196c9" @@ -4744,20 +4930,20 @@ async@^3.0.1, async@^3.2.0, async@^3.2.3: asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== at-least-node@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== -autoprefixer@^10.3.7, autoprefixer@^10.4.4: - version "10.4.4" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.4.tgz#3e85a245b32da876a893d3ac2ea19f01e7ea5a1e" - integrity sha512-Tm8JxsB286VweiZ5F0anmbyGiNI3v3wGv3mz9W+cxEDYB/6jbnj6GM9H9mK3wIL8ftgl+C07Lcwb8PG5PCCPzA== +autoprefixer@^10.3.7, autoprefixer@^10.4.7: + version "10.4.7" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.7.tgz#1db8d195f41a52ca5069b7593be167618edbbedf" + integrity sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA== dependencies: - browserslist "^4.20.2" - caniuse-lite "^1.0.30001317" + browserslist "^4.20.3" + caniuse-lite "^1.0.30001335" fraction.js "^4.2.0" normalize-range "^0.1.2" picocolors "^1.0.0" @@ -4766,7 +4952,7 @@ autoprefixer@^10.3.7, autoprefixer@^10.4.4: aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== aws4@^1.8.0: version "1.11.0" @@ -4774,9 +4960,9 @@ aws4@^1.8.0: integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== axe-core@^4.3.5: - version "4.3.5" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.3.5.tgz#78d6911ba317a8262bfee292aeafcc1e04b49cc5" - integrity sha512-WKTW1+xAzhMS5dJsxWkliixlO/PqC4VhmO9T4juNYcaTg9jzWiJsou6m5pxWYGfigWbwzJWeFY6z47a+4neRXA== + version "4.4.2" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.2.tgz#dcf7fb6dea866166c3eab33d68208afe4d5f670c" + integrity sha512-LVAaGp/wkkgYJcjmHsoKx4juT1aQvJyPcW09MLCjVTh3V2cc6PnyempiLMNH5iMdfIX/zdbjUx2KDjMLCTdPeA== axios@^0.21.1: version "0.21.4" @@ -4811,10 +4997,10 @@ babel-jest@^27.2.2, babel-jest@^27.5.1: graceful-fs "^4.2.9" slash "^3.0.0" -babel-loader@^8.2.4: - version "8.2.4" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.4.tgz#95f5023c791b2e9e2ca6f67b0984f39c82ff384b" - integrity sha512-8dytA3gcvPPPv4Grjhnt8b5IIiTcq/zeXOPk4iTYI0SVXcsmuGg7JtBRDp8S9X+gJfhQ8ektjXZlDu1Bb33U8A== +babel-loader@^8.2.5: + version "8.2.5" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.5.tgz#d45f585e654d5a5d90f5350a779d7647c5ed512e" + integrity sha512-OSiFfH89LrEMiWd4pLNqGz4CwJDtbs2ZVc+iGu2HrkRfPxId9F2anQj38IxWpmRfsUY0aBZYi1EFcd3mhtRMLQ== dependencies: find-cache-dir "^3.3.1" loader-utils "^2.0.0" @@ -4826,15 +5012,8 @@ babel-plugin-apply-mdx-type-prop@1.6.22: resolved "https://registry.yarnpkg.com/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz#d216e8fd0de91de3f1478ef3231e05446bc8705b" integrity sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ== dependencies: - "@babel/helper-plugin-utils" "7.10.4" - "@mdx-js/util" "1.6.22" - -babel-plugin-dynamic-import-node@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" - integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== - dependencies: - object.assign "^4.1.0" + "@babel/helper-plugin-utils" "7.10.4" + "@mdx-js/util" "1.6.22" babel-plugin-dynamic-import-node@^2.3.3: version "2.3.3" @@ -4872,12 +5051,12 @@ babel-plugin-jest-hoist@^27.5.1: "@types/babel__traverse" "^7.0.6" babel-plugin-polyfill-corejs2@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.0.tgz#407082d0d355ba565af24126fb6cb8e9115251fd" - integrity sha512-wMDoBJ6uG4u4PNFh72Ty6t3EgfA91puCuAwKIazbQlci+ENb/UU9A3xG5lutjUIiXCIn1CY5L15r9LimiJyrSA== + version "0.3.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz#440f1b70ccfaabc6b676d196239b138f8a2cfba5" + integrity sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w== dependencies: "@babel/compat-data" "^7.13.11" - "@babel/helper-define-polyfill-provider" "^0.3.0" + "@babel/helper-define-polyfill-provider" "^0.3.1" semver "^6.1.1" babel-plugin-polyfill-corejs3@^0.5.0: @@ -4889,11 +5068,11 @@ babel-plugin-polyfill-corejs3@^0.5.0: core-js-compat "^3.21.0" babel-plugin-polyfill-regenerator@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.0.tgz#9ebbcd7186e1a33e21c5e20cae4e7983949533be" - integrity sha512-dhAPTDLGoMW5/84wkgwiLRwMnio2i1fUe53EuvtKMv0pn2p3S8OCoV1xAzfJPl0KOX7IB89s2ib85vbYiea3jg== + version "0.3.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz#2c0678ea47c75c8cc2fbb1852278d8fb68233990" + integrity sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A== dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.0" + "@babel/helper-define-polyfill-provider" "^0.3.1" babel-preset-current-node-syntax@^1.0.0: version "1.0.1" @@ -4934,17 +5113,17 @@ balanced-match@^1.0.0: base16@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/base16/-/base16-1.0.0.tgz#e297f60d7ec1014a7a971a39ebc8a98c0b681e70" - integrity sha1-4pf2DX7BAUp6lxo568ipjAtoHnA= + integrity sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ== batch@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" - integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= + integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== dependencies: tweetnacl "^0.14.3" @@ -4973,38 +5152,38 @@ bluebird@^3.7.1, bluebird@^3.7.2: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== -body-parser@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== +body-parser@1.20.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5" + integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg== dependencies: - bytes "3.1.0" + bytes "3.1.2" content-type "~1.0.4" debug "2.6.9" - depd "~1.1.2" - http-errors "1.7.2" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" + on-finished "2.4.1" + qs "6.10.3" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" -bonjour@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" - integrity sha1-jokKGD2O6aI5OzhExpGkK897yfU= +bonjour-service@^1.0.11: + version "1.0.12" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.0.12.tgz#28fbd4683f5f2e36feedb833e24ba661cac960c3" + integrity sha512-pMmguXYCu63Ug37DluMKEHdxc+aaIf/ay4YbF8Gxtba+9d3u+rmEWy61VK3Z3hp8Rskok3BunHYnG0dUHAsblw== dependencies: - array-flatten "^2.1.0" - deep-equal "^1.0.1" + array-flatten "^2.1.2" dns-equal "^1.0.0" - dns-txt "^2.0.2" - multicast-dns "^6.0.1" - multicast-dns-service-types "^1.1.0" + fast-deep-equal "^3.1.3" + multicast-dns "^7.2.4" boolbase@^1.0.0, boolbase@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== boxen@^5.0.0: version "5.1.2" @@ -5061,15 +5240,15 @@ browser-process-hrtime@^1.0.0: resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== -browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.18.1, browserslist@^4.19.1, browserslist@^4.20.2: - version "4.20.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.2.tgz#567b41508757ecd904dab4d1c646c612cd3d4f88" - integrity sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA== +browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.18.1, browserslist@^4.20.2, browserslist@^4.20.3: + version "4.20.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.3.tgz#eb7572f49ec430e054f56d52ff0ebe9be915f8bf" + integrity sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg== dependencies: - caniuse-lite "^1.0.30001317" - electron-to-chromium "^1.4.84" + caniuse-lite "^1.0.30001332" + electron-to-chromium "^1.4.118" escalade "^3.1.1" - node-releases "^2.0.2" + node-releases "^2.0.3" picocolors "^1.0.0" bser@2.1.1: @@ -5082,37 +5261,32 @@ bser@2.1.1: buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= + integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -buffer-indexof@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" - integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== - builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= + integrity sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ== builtin-modules@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887" - integrity sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA== + version "3.3.0" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" + integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== builtins@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" - integrity sha1-y5T662HIaWRR2zZTThQi+U8K7og= + integrity sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ== byline@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" - integrity sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE= + integrity sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q== byte-size@^7.0.0: version "7.0.1" @@ -5122,12 +5296,12 @@ byte-size@^7.0.0: bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== cacache@^15.0.5, cacache@^15.2.0: version "15.3.0" @@ -5217,9 +5391,9 @@ camelcase@^5.0.0, camelcase@^5.3.1: integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== camelcase@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" - integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-api@^3.0.0: version "3.0.0" @@ -5231,29 +5405,21 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001317: - version "1.0.30001332" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001332.tgz" - integrity sha512-10T30NYOEQtN6C11YGg411yebhvpnC6Z102+B95eAsN0oB6KUs01ivE8u+G6FMIRtIrVlYXhL+LUwQ3/hXwDWw== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001332, caniuse-lite@^1.0.30001335: + version "1.0.30001344" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001344.tgz#8a1e7fdc4db9c2ec79a05e9fd68eb93a761888bb" + integrity sha512-0ZFjnlCaXNOAYcV7i+TtdKBp0L/3XEU2MF/x6Du1lrh+SRX4IfzIVL4HNJg5pB2PmFb8rszIGyOvsZnqqRoc2g== caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== ccount@^1.0.0, ccount@^1.0.3: version "1.1.0" resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== -chalk@4, chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - chalk@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" @@ -5271,6 +5437,14 @@ chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + char-regex@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" @@ -5299,23 +5473,24 @@ chardet@^0.7.0: check-more-types@^2.24.0: version "2.24.0" resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" - integrity sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA= + integrity sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA== -cheerio-select@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-1.5.0.tgz#faf3daeb31b17c5e1a9dabcee288aaf8aafa5823" - integrity sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg== +cheerio-select@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4" + integrity sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g== dependencies: - css-select "^4.1.3" - css-what "^5.0.1" - domelementtype "^2.2.0" - domhandler "^4.2.0" - domutils "^2.7.0" + boolbase "^1.0.0" + css-select "^5.1.0" + css-what "^6.1.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.0.1" cheerio@^0.22.0: version "0.22.0" resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" - integrity sha1-qbqoYKP5tZWmuBsahocxIe06Jp4= + integrity sha512-8/MzidM6G/TgRelkzDG13y3Y9LxBjCb+8yOEZ9+wwq5gVF2w2pV0wmHvjfT0RvuxGyR7UEuK36r+yYMbT4uKgA== dependencies: css-select "~1.2.0" dom-serializer "~0.1.0" @@ -5334,18 +5509,19 @@ cheerio@^0.22.0: lodash.reject "^4.4.0" lodash.some "^4.4.0" -cheerio@^1.0.0-rc.10: - version "1.0.0-rc.10" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.10.tgz#2ba3dcdfcc26e7956fc1f440e61d51c643379f3e" - integrity sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw== +cheerio@^1.0.0-rc.11: + version "1.0.0-rc.11" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.11.tgz#1be84be1a126958366bcc57a11648cd9b30a60c2" + integrity sha512-bQwNaDIBKID5ts/DsdhxrjqFXYfLw4ste+wMKqWA8DyKcS4qwsPP4Bk8ZNaTJjvpiX/qW3BT4sU7d6Bh5i+dag== dependencies: - cheerio-select "^1.5.0" - dom-serializer "^1.3.2" - domhandler "^4.2.0" - htmlparser2 "^6.1.0" - parse5 "^6.0.1" - parse5-htmlparser2-tree-adapter "^6.0.1" - tslib "^2.2.0" + cheerio-select "^2.1.0" + dom-serializer "^2.0.0" + domhandler "^5.0.3" + domutils "^3.0.1" + htmlparser2 "^8.0.1" + parse5 "^7.0.0" + parse5-htmlparser2-tree-adapter "^7.0.0" + tslib "^2.4.0" chokidar@^3.4.2, chokidar@^3.5.1, chokidar@^3.5.3: version "3.5.3" @@ -5382,20 +5558,20 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== -ci-info@^3.1.1, ci-info@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.2.0.tgz#2876cb948a498797b5236f0095bc057d0dca38b6" - integrity sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A== +ci-info@^3.2.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.1.tgz#58331f6f472a25fe3a50a351ae3052936c2c7f32" + integrity sha512-SXgeMX9VwDe7iFFaEWkA5AstuER9YKqy4EhHqr4DVqkwmD9rpVimkMKWHdjn30Ja45txyjhSn63lVX69eVCckg== cjs-module-lexer@^1.0.0: version "1.2.2" resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== -clean-css@^5.2.2, clean-css@^5.2.4: - version "5.2.4" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.2.4.tgz#982b058f8581adb2ae062520808fb2429bd487a4" - integrity sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg== +clean-css@^5.2.2, clean-css@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.0.tgz#ad3d8238d5f3549e83d5f87205189494bc7cbb59" + integrity sha512-YYuuxv4H/iNb1Z/5IbMRoxgrzjWGhOEFfd+groZ5dMCVkpENiMZmwspdrzBo9286JjM1gZJPAyL7ZIdzuvu2AQ== dependencies: source-map "~0.6.0" @@ -5404,10 +5580,10 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== -clear-module@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/clear-module/-/clear-module-4.1.1.tgz#bf8ba3b62eb70ee1e0adec90589741425cf32db8" - integrity sha512-ng0E7LeODcT3QkazOckzZqbca+JByQy/Q2Z6qO24YsTp+pLxCfohGz2gJYJqZS0CWTX3LEUiHOqe5KlYeUbEMw== +clear-module@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/clear-module/-/clear-module-4.1.2.tgz#5a58a5c9f8dccf363545ad7284cad3c887352a80" + integrity sha512-LWAxzHqdHsAZlPlEyJ2Poz6AIs384mPeqLVCru2p0BrP9G/kVGuhNyZYClLO6cXlnuJjzC8xtsJIuMjKqLXoAw== dependencies: parent-module "^2.0.0" resolve-from "^5.0.0" @@ -5432,7 +5608,7 @@ cli-cursor@3.1.0, cli-cursor@^3.1.0: cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= + integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw== dependencies: restore-cursor "^2.0.0" @@ -5441,14 +5617,14 @@ cli-spinners@2.6.1: resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d" integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== -cli-table3@^0.6.1, cli-table3@~0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.1.tgz#36ce9b7af4847f288d3cdd081fbd09bf7bd237b8" - integrity sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA== +cli-table3@^0.6.2, cli-table3@~0.6.0: + version "0.6.2" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.2.tgz#aaf5df9d8b5bf12634dc8b3040806a0c07120d2a" + integrity sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw== dependencies: string-width "^4.2.0" optionalDependencies: - colors "1.4.0" + "@colors/colors" "1.5.0" cli-truncate@^2.1.0: version "2.1.0" @@ -5506,14 +5682,14 @@ clone-deep@^4.0.1: clone-response@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + integrity sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q== dependencies: mimic-response "^1.0.0" clone@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== clsx@^1.1.1: version "1.1.1" @@ -5530,12 +5706,12 @@ cmd-shim@^4.1.0: co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== collapse-white-space@^1.0.2: version "1.0.6" @@ -5564,7 +5740,7 @@ color-convert@^2.0.1: color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== color-name@~1.1.4: version "1.1.4" @@ -5572,31 +5748,26 @@ color-name@~1.1.4: integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== colord@^2.9.1: - version "2.9.1" - resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.1.tgz#c961ea0efeb57c9f0f4834458f26cb9cc4a3f90e" - integrity sha512-4LBMSt09vR0uLnPVkOUBnmxgoaeN4ewRbx801wY/bXcltXfpR/G46OdWn96XpYmCWuYvO46aBZP4NgX8HpNAcw== + version "2.9.2" + resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.2.tgz#25e2bacbbaa65991422c07ea209e2089428effb1" + integrity sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ== colorette@^2.0.10, colorette@^2.0.16: version "2.0.16" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== -colors@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" - integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== - colors@~1.2.1: version "1.2.5" resolved "https://registry.yarnpkg.com/colors/-/colors-1.2.5.tgz#89c7ad9a374bc030df8013241f68136ed8835afc" integrity sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg== columnify@^1.5.4: - version "1.5.4" - resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb" - integrity sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs= + version "1.6.0" + resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.6.0.tgz#6989531713c9008bb29735e61e37acf5bd553cf3" + integrity sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q== dependencies: - strip-ansi "^3.0.0" + strip-ansi "^6.0.1" wcwidth "^1.0.0" combine-promises@^1.1.0: @@ -5616,7 +5787,7 @@ comma-separated-tokens@^1.0.0: resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== -commander@^2.12.1, commander@^2.20.0, commander@^2.7.1: +commander@^2.12.1, commander@^2.20.0, commander@^2.20.3: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -5631,23 +5802,28 @@ commander@^7.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== -commander@^8.2.0, commander@^8.3.0: +commander@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== +commander@^9.2.0, commander@^9.3.0: + version "9.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.3.0.tgz#f619114a5a2d2054e0d9ff1b31d5ccf89255e26b" + integrity sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw== + commander@~8.2.0: version "8.2.0" resolved "https://registry.yarnpkg.com/commander/-/commander-8.2.0.tgz#37fe2bde301d87d47a53adeff8b5915db1381ca8" integrity sha512-LLKxDvHeL91/8MIyTAD5BFMNtoIwztGPMiM/7Bl8rIPmHCZXRxmSWr91h57dpOpnQ6jIUqEWdXE/uBYMfiVZDA== -comment-json@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/comment-json/-/comment-json-4.1.1.tgz#49df4948704bebb1cc0ffa6910e25669b668b7c5" - integrity sha512-v8gmtPvxhBlhdRBLwdHSjGy9BgA23t9H1FctdQKyUrErPjSrJcdDMqBq9B4Irtm7w3TNYLQJNH6ARKnpyag1sA== +comment-json@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/comment-json/-/comment-json-4.2.2.tgz#5fae70a94e0c8f84a077bd31df5aa5269252f293" + integrity sha512-H8T+kl3nZesZu41zO2oNXIJWojNeK3mHxCLrsBNu6feksBXsgb+PtYz5daP5P86A0F3sz3840KVYehr04enISQ== dependencies: array-timsort "^1.0.3" - core-util-is "^1.0.2" + core-util-is "^1.0.3" esprima "^4.0.1" has-own-prop "^2.0.0" repeat-string "^1.6.1" @@ -5680,7 +5856,7 @@ common-tags@^1.8.0: commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== compare-func@^2.0.0: version "2.0.0" @@ -5713,7 +5889,7 @@ compression@^1.7.4: concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== concat-stream@^2.0.0: version "2.0.0" @@ -5758,19 +5934,19 @@ consola@^2.15.3: console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== content-disposition@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= + integrity sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA== -content-disposition@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== dependencies: - safe-buffer "5.1.2" + safe-buffer "5.2.1" content-type@~1.0.4: version "1.0.4" @@ -5786,9 +5962,9 @@ conventional-changelog-angular@^5.0.11, conventional-changelog-angular@^5.0.12: q "^1.5.1" conventional-changelog-conventionalcommits@^4.3.1: - version "4.6.1" - resolved "https://registry.yarnpkg.com/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.1.tgz#f4c0921937050674e578dc7875f908351ccf4014" - integrity sha512-lzWJpPZhbM1R0PIzkwzGBCnAkH5RKJzJfFQZcl/D+2lsJxAwGnDKBqn/F4C1RD31GJNn8NuKWQzAZDAVXPp2Mw== + version "4.6.3" + resolved "https://registry.yarnpkg.com/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.3.tgz#0765490f56424b46f6cb4db9135902d6e5a36dc2" + integrity sha512-LTTQV4fwOM4oLPad317V/QNQ1FY4Hju5qeBIM1uTHbrnCE+Eg4CdRZ3gO2pUeR+tzWdp80M2j3qFFEDWVqOV4g== dependencies: compare-func "^2.0.0" lodash "^4.17.15" @@ -5820,13 +5996,13 @@ conventional-changelog-preset-loader@^2.3.4: integrity sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g== conventional-changelog-writer@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-5.0.0.tgz#c4042f3f1542f2f41d7d2e0d6cad23aba8df8eec" - integrity sha512-HnDh9QHLNWfL6E1uHz6krZEQOgm8hN7z/m7tT16xwd802fwgMN0Wqd7AQYVkhpsjDUx/99oo+nGgvKF657XP5g== + version "5.0.1" + resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz#e0757072f045fe03d91da6343c843029e702f359" + integrity sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ== dependencies: conventional-commits-filter "^2.0.7" dateformat "^3.0.0" - handlebars "^4.7.6" + handlebars "^4.7.7" json-stringify-safe "^5.0.1" lodash "^4.17.15" meow "^8.0.0" @@ -5848,9 +6024,9 @@ conventional-commits-filter@^2.0.7: modify-values "^1.0.0" conventional-commits-parser@^3.2.0, conventional-commits-parser@^3.2.2: - version "3.2.3" - resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.2.3.tgz#fc43704698239451e3ef35fd1d8ed644f46bd86e" - integrity sha512-YyRDR7On9H07ICFpRm/igcdjIqebXbvf4Cff+Pf0BrBys1i1EOzx9iFXNlAbdrLAR8jf7bkUYkDAr8pEy0q4Pw== + version "3.2.4" + resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz#a7d3b77758a202a9b2293d2112a8d8052c740972" + integrity sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q== dependencies: JSONStream "^1.0.4" is-text-path "^1.0.1" @@ -5883,26 +6059,26 @@ convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== copy-text-to-clipboard@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz#8cbf8f90e0a47f12e4a24743736265d157bce69c" integrity sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q== -copy-webpack-plugin@^10.2.4: - version "10.2.4" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz#6c854be3fdaae22025da34b9112ccf81c63308fe" - integrity sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg== +copy-webpack-plugin@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz#96d4dbdb5f73d02dd72d0528d1958721ab72e04a" + integrity sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ== dependencies: - fast-glob "^3.2.7" + fast-glob "^3.2.11" glob-parent "^6.0.1" - globby "^12.0.2" + globby "^13.1.1" normalize-path "^3.0.0" schema-utils "^4.0.0" serialize-javascript "^6.0.0" @@ -5919,41 +6095,41 @@ copy-webpack-plugin@^9.1.0: schema-utils "^3.1.1" serialize-javascript "^6.0.0" -core-js-compat@^3.20.2, core-js-compat@^3.21.0: - version "3.21.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.21.1.tgz#cac369f67c8d134ff8f9bd1623e3bc2c42068c82" - integrity sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g== +core-js-compat@^3.21.0, core-js-compat@^3.22.1: + version "3.22.7" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.22.7.tgz#8359eb66ecbf726dd0cfced8e48d5e73f3224239" + integrity sha512-uI9DAQKKiiE/mclIC5g4AjRpio27g+VMRhe6rQoz+q4Wm4L6A/fJhiLtBw+sfOpDG9wZ3O0pxIw7GbfOlBgjOA== dependencies: - browserslist "^4.19.1" + browserslist "^4.20.3" semver "7.0.0" core-js-pure@^3.20.2: - version "3.21.1" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.21.1.tgz#8c4d1e78839f5f46208de7230cebfb72bc3bdb51" - integrity sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ== + version "3.22.7" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.22.7.tgz#f58489d9b309fa7b26486a0f70d4ec19a418084e" + integrity sha512-wTriFxiZI+C8msGeh7fJcbC/a0V8fdInN1oS2eK79DMBGs8iIJiXhtFJCiT3rBa8w6zroHWW3p8ArlujZ/Mz+w== -core-js@^3.21.1: - version "3.21.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.21.1.tgz#f2e0ddc1fc43da6f904706e8e955bc19d06a0d94" - integrity sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig== +core-js@^3.22.7: + version "3.22.7" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.22.7.tgz#8d6c37f630f6139b8732d10f2c114c3f1d00024f" + integrity sha512-Jt8SReuDKVNZnZEzyEQT5eK6T2RRCXkfTq7Lo09kpm+fHjgGewSbNjV+Wt4yZMhPDdzz2x1ulI5z/w4nxpBseg== core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== -core-util-is@^1.0.2, core-util-is@~1.0.0: +core-util-is@^1.0.3, core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -cosmiconfig-typescript-loader@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-1.0.3.tgz#528f2bb3e6b6705020dc42df659f24837e75b611" - integrity sha512-ARo21VjxdacJUcHxgVMEYNIoVPYiuKOEwWBIYej4M22+pEbe3LzKgmht2UPM+0u7/T/KnZf2r/5IzHv2Nwz+/w== +cosmiconfig-typescript-loader@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-2.0.1.tgz#5622bb1eb87d293570bcc3a57f406940e0960113" + integrity sha512-B9s6sX/omXq7I6gC6+YgLmrBFMJhPWew7ty/X5Tuwtd2zOSgWaUdXjkuVwbe3qqcdETo60+1nSVMekq//LIXVA== dependencies: cosmiconfig "^7" - ts-node "^10.4.0" + ts-node "^10.8.0" cosmiconfig@^6.0.0: version "6.0.0" @@ -5989,7 +6165,7 @@ cross-env@^7.0.3: dependencies: cross-spawn "^7.0.1" -cross-fetch@^3.0.4, cross-fetch@^3.1.4: +cross-fetch@^3.1.4, cross-fetch@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== @@ -6010,82 +6186,85 @@ crypto-random-string@^2.0.0: resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== -cspell-gitignore@^5.12.3: - version "5.12.3" - resolved "https://registry.yarnpkg.com/cspell-gitignore/-/cspell-gitignore-5.12.3.tgz#cd0425064f048cc6f40ba791684f068ee0cc130d" - integrity sha512-oPqY6oCVNwFRqcE0FiWNPsyv0EjWiK2N66en6HDZR+pXLZ1CBh8PHcUbRAGt+XHckm27zxbl/sDCKd2m+5yyIA== +cspell-gitignore@^5.21.2: + version "5.21.2" + resolved "https://registry.yarnpkg.com/cspell-gitignore/-/cspell-gitignore-5.21.2.tgz#f2e93addbc459098ea2d23cd29d9e645478d6907" + integrity sha512-MdNmRRbglmCi20LU7ORZM1gyPSe1gL+4A8Pn+Jm+W5ropSbotzCqiO8BcyhRMNb3lAdMGGrj7gmYtiQ5C/fXIQ== dependencies: - cspell-glob "^5.12.3" + cspell-glob "^5.21.2" find-up "^5.0.0" -cspell-glob@^5.12.3: - version "5.12.3" - resolved "https://registry.yarnpkg.com/cspell-glob/-/cspell-glob-5.12.3.tgz#31d1b3799f2ced60814730ef1c9332260df44755" - integrity sha512-2ZgzHr01Blch1I1C3jkzb3IIEE7peoFDDAM+MONQdf8JugWrexZsQ3A6nNUuUgtHZYbJC01ZKzB1JunmE84caA== +cspell-glob@^5.21.2: + version "5.21.2" + resolved "https://registry.yarnpkg.com/cspell-glob/-/cspell-glob-5.21.2.tgz#ef56578b561ab67efd3c2c84c2fbd85a7072ba61" + integrity sha512-AabqzG31UWy4CSz1xJIK4qzXcarxuRFP9OD2EX8iDtEo0tQJLGoTHE+UpNDBPWTHearE0BZPhpMDF/radtZAgw== dependencies: - micromatch "^4.0.4" - -cspell-io@^5.12.3: - version "5.12.3" - resolved "https://registry.yarnpkg.com/cspell-io/-/cspell-io-5.12.3.tgz#19bf52443ac964042b0a2e9103a8c12f3312d494" - integrity sha512-YqIsDPWj4OKyRYDZyZ9InvYBSGJAYbq/OMzCtJ1vCpgzGdm+7pWQkonGZMThPDW33EsSE8GPaT/XTGZbqZuDoA== + micromatch "^4.0.5" -cspell-lib@^5.12.3: - version "5.12.3" - resolved "https://registry.yarnpkg.com/cspell-lib/-/cspell-lib-5.12.3.tgz#47b2ebffe535a82eeed27f539125fef2fcedbb01" - integrity sha512-wiS3X3inzkwr2d6UojVLjzGFxwhnE+HoQYg7cDyC2qqK1Q++36c5bHJGE8564lsVedeAMVbHh81bP7hibg/yUw== - dependencies: - "@cspell/cspell-bundled-dicts" "^5.12.3" - "@cspell/cspell-types" "^5.12.3" - clear-module "^4.1.1" - comment-json "^4.1.1" +cspell-io@^5.21.2: + version "5.21.2" + resolved "https://registry.yarnpkg.com/cspell-io/-/cspell-io-5.21.2.tgz#d9087163b1c8ad11c6f94cb7dddf8c57eb97fabe" + integrity sha512-3J4cLuN59R7ARiRZ8ke5QwlC5uPfzHLVELOtEAmsTIjuUMvr7BpbrdCuTsUvLkAqYE9NA5eqolqQm3GLXnECNw== + +cspell-lib@^5.21.2: + version "5.21.2" + resolved "https://registry.yarnpkg.com/cspell-lib/-/cspell-lib-5.21.2.tgz#77e81b4f134441e11c0434dee7532c00ea116268" + integrity sha512-emAFXtDfs84FoMlhOxZYxYVvbCoCN0LxN0obIRvCsvFCLUPj9y7vHv/Tu/01ZyAPeo2r6gkqhanJpQyoIDA1yg== + dependencies: + "@cspell/cspell-bundled-dicts" "^5.21.2" + "@cspell/cspell-pipe" "^5.21.2" + "@cspell/cspell-types" "^5.21.2" + clear-module "^4.1.2" + comment-json "^4.2.2" configstore "^5.0.1" cosmiconfig "^7.0.1" - cspell-glob "^5.12.3" - cspell-io "^5.12.3" - cspell-trie-lib "^5.12.3" + cspell-glob "^5.21.2" + cspell-io "^5.21.2" + cspell-trie-lib "^5.21.2" + fast-equals "^3.0.2" find-up "^5.0.0" - fs-extra "^10.0.0" + fs-extra "^10.1.0" gensequence "^3.1.1" import-fresh "^3.3.0" resolve-from "^5.0.0" resolve-global "^1.0.0" - vscode-uri "^3.0.2" + vscode-languageserver-textdocument "^1.0.4" + vscode-uri "^3.0.3" -cspell-trie-lib@^5.12.3: - version "5.12.3" - resolved "https://registry.yarnpkg.com/cspell-trie-lib/-/cspell-trie-lib-5.12.3.tgz#31a6fe7ed3016d77768fc4b1dfcfab1a9dd46a93" - integrity sha512-kck/fUcsBeskuHPFSW4tn4yseDWCDTSaXwxTB+G129anzk0w7mz4LliBBfoD8AHo+D102N7nWmcKXxwPUxAXUQ== +cspell-trie-lib@^5.21.2: + version "5.21.2" + resolved "https://registry.yarnpkg.com/cspell-trie-lib/-/cspell-trie-lib-5.21.2.tgz#5d00667754c02695a00fc98f2c6bd467f7945951" + integrity sha512-iux2F+85jDlBEJZgikfPT5SUZMwuFjNqEJiO1SO+xfQG+2MFV9CaHTsoRJIGNy3udMm1mw0GMY5UIVAodwlnhg== dependencies: - fs-extra "^10.0.0" + "@cspell/cspell-pipe" "^5.21.2" + fs-extra "^10.1.0" gensequence "^3.1.1" cspell@^5.12.3: - version "5.12.3" - resolved "https://registry.yarnpkg.com/cspell/-/cspell-5.12.3.tgz#1966eb6687f7cdf86e5f96a8c39a140ffac42d55" - integrity sha512-lPyWZHfdQh+xjUZDAQC0gnpjglMu2AEfxBWlziTm3XuYuPGTvNJQSUrkMcH180tA3fkj8q2XFwfxHkXXAxm68w== + version "5.21.2" + resolved "https://registry.yarnpkg.com/cspell/-/cspell-5.21.2.tgz#3b147ba49ecdbaa8818d638b71ef142e15ccf303" + integrity sha512-yG14BUumeIcsuSEcM//+9XpbUR6a6FlAxfaVI4e5t6ZZE5tPgDE0PNIVr/jAiLPVm9qUfnq+oNdZE8wmVUbMzw== dependencies: + "@cspell/cspell-pipe" "^5.21.2" chalk "^4.1.2" - commander "^8.2.0" - comment-json "^4.1.1" - cspell-gitignore "^5.12.3" - cspell-glob "^5.12.3" - cspell-lib "^5.12.3" + commander "^9.2.0" + cspell-gitignore "^5.21.2" + cspell-glob "^5.21.2" + cspell-lib "^5.21.2" fast-json-stable-stringify "^2.1.0" file-entry-cache "^6.0.1" - fs-extra "^10.0.0" + fs-extra "^10.1.0" get-stdin "^8.0.0" - glob "^7.2.0" + glob "^8.0.3" imurmurhash "^0.1.4" + semver "^7.3.7" strip-ansi "^6.0.1" - vscode-uri "^3.0.2" + vscode-uri "^3.0.3" -css-declaration-sorter@^6.0.3: - version "6.1.3" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.1.3.tgz#e9852e4cf940ba79f509d9425b137d1f94438dc2" - integrity sha512-SvjQjNRZgh4ULK1LDJ2AduPKUKxIqmtU7ZAyi47BTV+M90Qvxr9AB6lKlLbDUfXqI9IQeYA8LbAsCZPpJEV3aA== - dependencies: - timsort "^0.3.0" +css-declaration-sorter@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.2.2.tgz#bfd2f6f50002d6a3ae779a87d3a0c5d5b10e0f02" + integrity sha512-Ufadglr88ZLsrvS11gjeu/40Lw74D9Am/Jpr3LlYm5Q4ZP5KdlUhG+6u2EjyXeZcxmZ2h1ebCKngDjolpeLHpg== css-loader@^6.7.1: version "6.7.1" @@ -6101,33 +6280,44 @@ css-loader@^6.7.1: postcss-value-parser "^4.2.0" semver "^7.3.5" -css-minimizer-webpack-plugin@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz#ab78f781ced9181992fe7b6e4f3422e76429878f" - integrity sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q== +css-minimizer-webpack-plugin@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-4.0.0.tgz#e11800388c19c2b7442c39cc78ac8ae3675c9605" + integrity sha512-7ZXXRzRHvofv3Uac5Y+RkWRNo0ZMlcg8e9/OtrqUYmwDWJo+qs67GvdeFrXLsFb7czKNwjQhPkM0avlIYl+1nA== dependencies: - cssnano "^5.0.6" - jest-worker "^27.0.2" - postcss "^8.3.5" + cssnano "^5.1.8" + jest-worker "^27.5.1" + postcss "^8.4.13" schema-utils "^4.0.0" serialize-javascript "^6.0.0" source-map "^0.6.1" css-select@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.1.3.tgz#a70440f70317f2669118ad74ff105e65849c7067" - integrity sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA== + version "4.3.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" + integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ== dependencies: boolbase "^1.0.0" - css-what "^5.0.0" - domhandler "^4.2.0" - domutils "^2.6.0" - nth-check "^2.0.0" + css-what "^6.0.1" + domhandler "^4.3.1" + domutils "^2.8.0" + nth-check "^2.0.1" + +css-select@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" + integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== + dependencies: + boolbase "^1.0.0" + css-what "^6.1.0" + domhandler "^5.0.2" + domutils "^3.0.1" + nth-check "^2.0.1" css-select@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" - integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= + integrity sha512-dUQOBoqdR7QwV90WysXPLXG5LO7nhYBgiWVfxF80DKPF8zx1t/pUd2FYy73emg3zrjtM6dzmYgbHKfV2rxiHQA== dependencies: boolbase "~1.0.0" css-what "2.1" @@ -6147,48 +6337,48 @@ css-what@2.1: resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== -css-what@^5.0.0, css-what@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" - integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== +css-what@^6.0.1, css-what@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== -cssnano-preset-advanced@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.1.tgz#f4fa7006aab67e354289b3efd512c93a272b3874" - integrity sha512-kfCknalY5VX/JKJ3Iri5/5rhZmQIqkbqgXsA6oaTnfA4flY/tt+w0hMxbExr0/fVuJL8w56j211op+pkQoNzoQ== +cssnano-preset-advanced@^5.3.5: + version "5.3.6" + resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.6.tgz#6c995a86cecc9e6472bf6d120e5517231ed527dc" + integrity sha512-OZHsytu16eStRVrIY3wmPQqhJMaI0+O3raU4JHoKV3uuQYEeQek/FJVUIvYXD55hWR6OjCMyKYNRDw+k3/xgUw== dependencies: autoprefixer "^10.3.7" - cssnano-preset-default "^5.2.5" + cssnano-preset-default "^5.2.10" postcss-discard-unused "^5.1.0" postcss-merge-idents "^5.1.1" postcss-reduce-idents "^5.2.0" postcss-zindex "^5.1.0" -cssnano-preset-default@^5.2.5: - version "5.2.5" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.5.tgz#267ded811a3e1664d78707f5355fcd89feeb38ac" - integrity sha512-WopL7PzN7sos3X8B54/QGl+CZUh1f0qN4ds+y2d5EPwRSSc3jsitVw81O+Uyop0pXyOfPfZxnc+LmA8w/Ki/WQ== +cssnano-preset-default@^5.2.10: + version "5.2.10" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.10.tgz#6dfffe6cc3b13f3bb356a42c49a334a98700ef45" + integrity sha512-H8TJRhTjBKVOPltp9vr9El9I+IfYsOMhmXdK0LwdvwJcxYX9oWkY7ctacWusgPWAgQq1vt/WO8v+uqpfLnM7QA== dependencies: - css-declaration-sorter "^6.0.3" + css-declaration-sorter "^6.2.2" cssnano-utils "^3.1.0" postcss-calc "^8.2.3" postcss-colormin "^5.3.0" - postcss-convert-values "^5.1.0" - postcss-discard-comments "^5.1.1" + postcss-convert-values "^5.1.2" + postcss-discard-comments "^5.1.2" postcss-discard-duplicates "^5.1.0" postcss-discard-empty "^5.1.1" postcss-discard-overridden "^5.1.0" - postcss-merge-longhand "^5.1.3" - postcss-merge-rules "^5.1.1" + postcss-merge-longhand "^5.1.5" + postcss-merge-rules "^5.1.2" postcss-minify-font-values "^5.1.0" postcss-minify-gradients "^5.1.1" - postcss-minify-params "^5.1.2" - postcss-minify-selectors "^5.2.0" + postcss-minify-params "^5.1.3" + postcss-minify-selectors "^5.2.1" postcss-normalize-charset "^5.1.0" postcss-normalize-display-values "^5.1.0" postcss-normalize-positions "^5.1.0" @@ -6209,12 +6399,12 @@ cssnano-utils@^3.1.0: resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.1.0.tgz#95684d08c91511edfc70d2636338ca37ef3a6861" integrity sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA== -cssnano@^5.0.6, cssnano@^5.1.5: - version "5.1.5" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.5.tgz#5f3f519538c7f1c182c527096892243db3e17397" - integrity sha512-VZO1e+bRRVixMeia1zKagrv0lLN1B/r/u12STGNNUFxnp97LIFgZHQa0JxqlwEkvzUyA9Oz/WnCTAFkdEbONmg== +cssnano@^5.1.8, cssnano@^5.1.9: + version "5.1.10" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.10.tgz#fc6ddd9a4d7d238f320634326ed814cf0abf6e1c" + integrity sha512-ACpnRgDg4m6CZD/+8SgnLcGCgy6DDGdkMbOawwdvVxNietTNLe/MtWcenp6qT0PRt5wzhGl6/cjMWCdhKXC9QA== dependencies: - cssnano-preset-default "^5.2.5" + cssnano-preset-default "^5.2.10" lilconfig "^2.0.3" yaml "^1.10.2" @@ -6243,9 +6433,9 @@ cssstyle@^2.3.0: cssom "~0.3.6" csstype@^3.0.2: - version "3.0.9" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.9.tgz#6410af31b26bd0520933d02cbc64fce9ce3fbf0b" - integrity sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw== + version "3.1.0" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.0.tgz#4ddcac3718d787cf9df0d1b7d15033925c8f29f2" + integrity sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA== cypress-axe@^0.14.0: version "0.14.0" @@ -6328,9 +6518,9 @@ cz-conventional-changelog@^3.3.0: "@commitlint/load" ">6.1.1" damerau-levenshtein@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz#64368003512a1a6992593741a09a9d31a836f55d" - integrity sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw== + version "1.0.8" + resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" + integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== dargs@^7.0.0: version "7.0.0" @@ -6340,7 +6530,7 @@ dargs@^7.0.0: dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== dependencies: assert-plus "^1.0.0" @@ -6359,9 +6549,9 @@ dateformat@^3.0.0: integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== dayjs@^1.10.4: - version "1.10.7" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.7.tgz#2cf5f91add28116748440866a0a1d26f3a6ce468" - integrity sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig== + version "1.11.2" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.2.tgz#fa0f5223ef0d6724b3d8327134890cfe3d72fbe5" + integrity sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw== debug@2.6.9, debug@^2.6.0, debug@^2.6.9: version "2.6.9" @@ -6370,14 +6560,14 @@ debug@2.6.9, debug@^2.6.0, debug@^2.6.9: dependencies: ms "2.0.0" -debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -debug@^3.1.0, debug@^3.1.1, debug@^3.2.7: +debug@^3.1.0, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -6387,12 +6577,12 @@ debug@^3.1.0, debug@^3.1.1, debug@^3.2.7: debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" - integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= + integrity sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw== decamelize-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" - integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= + integrity sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg== dependencies: decamelize "^1.1.0" map-obj "^1.0.0" @@ -6400,7 +6590,7 @@ decamelize-keys@^1.1.0: decamelize@^1.1.0, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== decimal.js@^10.2.1: version "10.3.1" @@ -6410,31 +6600,19 @@ decimal.js@^10.2.1: decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + integrity sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og== decompress-response@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA== dependencies: mimic-response "^1.0.0" dedent@0.7.0, dedent@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" - integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= - -deep-equal@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" - integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== - dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" - object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" + integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== deep-extend@^0.6.0, deep-extend@~0.6.0: version "0.6.0" @@ -6461,7 +6639,7 @@ default-gateway@^6.0.3: defaults@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" - integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + integrity sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA== dependencies: clone "^1.0.2" @@ -6475,17 +6653,18 @@ define-lazy-prop@^2.0.0: resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== -define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== +define-properties@^1.1.3, define-properties@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" + integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== dependencies: - object-keys "^1.0.12" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" -del@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/del/-/del-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952" - integrity sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ== +del@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/del/-/del-6.1.1.tgz#3b70314f1ec0aa325c6b14eb36b95786671edb7a" + integrity sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg== dependencies: globby "^11.0.1" graceful-fs "^4.2.4" @@ -6499,27 +6678,32 @@ del@^6.0.0: delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== depd@^1.1.2, depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== deprecation@^2.0.0, deprecation@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== detab@2.0.4: version "2.0.4" @@ -6531,7 +6715,7 @@ detab@2.0.4: detect-file@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" - integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= + integrity sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q== detect-indent@6.0.0: version "6.0.0" @@ -6541,7 +6725,7 @@ detect-indent@6.0.0: detect-indent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" - integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50= + integrity sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g== detect-indent@^6.0.0: version "6.1.0" @@ -6575,9 +6759,9 @@ detect-port@^1.3.0: debug "^2.6.0" dezalgo@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" - integrity sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY= + version "1.0.4" + resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81" + integrity sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig== dependencies: asap "^2.0.0" wrappy "1" @@ -6592,6 +6776,11 @@ diff-sequences@^27.5.1: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== +diff-sequences@^28.0.2: + version "28.0.2" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-28.0.2.tgz#40f8d4ffa081acbd8902ba35c798458d0ff1af41" + integrity sha512-YtEoNynLDFCRznv/XDalsKGSZDoj0U5kLnXvY0JSq3nBboRrZXjD81+eSiwi+nzcZDwedMmcowcxNwwgFW23mQ== + diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -6607,22 +6796,14 @@ dir-glob@^3.0.1: dns-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" - integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= - -dns-packet@^1.3.1: - version "1.3.4" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f" - integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA== - dependencies: - ip "^1.1.0" - safe-buffer "^5.0.1" + integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== -dns-txt@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" - integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY= +dns-packet@^5.2.2: + version "5.3.1" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.3.1.tgz#eb94413789daec0f0ebe2fcc230bdc9d7c91b43d" + integrity sha512-spBwIj0TK0Ey3666GwIdWVfUpLyubpU53BTCu8iPn4r4oXd9O14Hjg3EHw3ts2oed77/SeckunUYCyRlSngqHw== dependencies: - buffer-indexof "^1.0.0" + "@leichtgewicht/ip-codec" "^2.0.1" doctrine@^2.1.0: version "2.1.0" @@ -6653,15 +6834,24 @@ dom-serializer@0: domelementtype "^2.0.1" entities "^2.0.0" -dom-serializer@^1.0.1, dom-serializer@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" - integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== +dom-serializer@^1.0.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" + integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== dependencies: domelementtype "^2.0.1" domhandler "^4.2.0" entities "^2.0.0" +dom-serializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" + integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + entities "^4.2.0" + dom-serializer@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" @@ -6675,10 +6865,10 @@ domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== -domelementtype@^2.0.1, domelementtype@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" - integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== +domelementtype@^2.0.1, domelementtype@^2.2.0, domelementtype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== domexception@^2.0.1: version "2.0.1" @@ -6694,17 +6884,24 @@ domhandler@^2.3.0: dependencies: domelementtype "1" -domhandler@^4.0.0, domhandler@^4.2.0: - version "4.2.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.2.tgz#e825d721d19a86b8c201a35264e226c678ee755f" - integrity sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w== +domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" + integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== dependencies: domelementtype "^2.2.0" +domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" + integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== + dependencies: + domelementtype "^2.3.0" + domutils@1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" - integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= + integrity sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw== dependencies: dom-serializer "0" domelementtype "1" @@ -6717,7 +6914,7 @@ domutils@^1.5.1: dom-serializer "0" domelementtype "1" -domutils@^2.5.2, domutils@^2.6.0, domutils@^2.7.0: +domutils@^2.5.2, domutils@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== @@ -6726,6 +6923,15 @@ domutils@^2.5.2, domutils@^2.6.0, domutils@^2.7.0: domelementtype "^2.2.0" domhandler "^4.2.0" +domutils@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.0.1.tgz#696b3875238338cb186b6c0612bd4901c89a4f1c" + integrity sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q== + dependencies: + dom-serializer "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.1" + dot-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" @@ -6765,7 +6971,7 @@ downlevel-dts@^0.9.0: duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + integrity sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA== duplexer@^0.1.1, duplexer@^0.1.2: version "0.1.2" @@ -6780,7 +6986,7 @@ eastasianwidth@^0.2.0: ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== dependencies: jsbn "~0.1.0" safer-buffer "^2.1.0" @@ -6788,19 +6994,19 @@ ecc-jsbn@~0.1.1: ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== ejs@^3.1.5: - version "3.1.7" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.7.tgz#c544d9c7f715783dd92f0bddcf73a59e6962d006" - integrity sha512-BIar7R6abbUxDA3bfXrO4DSgwo8I+fB5/1zgujl3HLLjwd6+9iOnrT+t3grn2qbk9vOgBubXOFwX2m9axoFaGw== + version "3.1.8" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.8.tgz#758d32910c78047585c7ef1f92f9ee041c1c190b" + integrity sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ== dependencies: jake "^10.8.5" -electron-to-chromium@^1.4.84: - version "1.4.103" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.103.tgz#abfe376a4d70fa1e1b4b353b95df5d6dfd05da3a" - integrity sha512-c/uKWR1Z/W30Wy/sx3dkZoj4BijbXX85QKWu9jJfjho3LBAXNEGAEW3oWiGb+dotA6C6BzCTxL2/aLes7jlUeg== +electron-to-chromium@^1.4.118: + version "1.4.143" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.143.tgz#10f1bb595ad6cd893c05097039c685dcf5c8e30c" + integrity sha512-2hIgvu0+pDfXIqmVmV5X6iwMjQ2KxDsWKwM+oI1fABEOy/Dqmll0QJRmIQ3rm+XaoUa/qKrmy5h7LSTFQ6Ldzg== emittery@^0.8.1: version "0.8.1" @@ -6835,7 +7041,7 @@ emoticon@^3.2.0: encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== encoding@^0.1.12: version "0.1.13" @@ -6851,7 +7057,7 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enhanced-resolve@^5.8.3, enhanced-resolve@^5.9.2: +enhanced-resolve@^5.8.3, enhanced-resolve@^5.9.3: version "5.9.3" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz#44a342c012cbc473254af5cc6ae20ebd0aae5d88" integrity sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow== @@ -6881,6 +7087,11 @@ entities@^3.0.1: resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4" integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q== +entities@^4.2.0, entities@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.3.0.tgz#62915f08d67353bb4eb67e3d62641a4059aec656" + integrity sha512-/iP1rZrSEJ0DTlPiX+jbzlA3eVkY/e8L8SozroF395fIqE3TYF/Nz7YOMAawta+vLmyJ/hkGNNPcSbMADCCXbg== + entities@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" @@ -6908,37 +7119,52 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.19.0, es-abstract@^1.19.1: - version "1.19.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" - integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== +es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5, es-abstract@^1.20.1: + version "1.20.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814" + integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA== dependencies: call-bind "^1.0.2" es-to-primitive "^1.2.1" function-bind "^1.1.1" + function.prototype.name "^1.1.5" get-intrinsic "^1.1.1" get-symbol-description "^1.0.0" has "^1.0.3" - has-symbols "^1.0.2" + has-property-descriptors "^1.0.0" + has-symbols "^1.0.3" internal-slot "^1.0.3" is-callable "^1.2.4" - is-negative-zero "^2.0.1" + is-negative-zero "^2.0.2" is-regex "^1.1.4" - is-shared-array-buffer "^1.0.1" + is-shared-array-buffer "^1.0.2" is-string "^1.0.7" - is-weakref "^1.0.1" - object-inspect "^1.11.0" + is-weakref "^1.0.2" + object-inspect "^1.12.0" object-keys "^1.1.1" object.assign "^4.1.2" - string.prototype.trimend "^1.0.4" - string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.1" + regexp.prototype.flags "^1.4.3" + string.prototype.trimend "^1.0.5" + string.prototype.trimstart "^1.0.5" + unbox-primitive "^1.0.2" + +es-array-method-boxes-properly@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" + integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== es-module-lexer@^0.9.0: version "0.9.3" resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== +es-shim-unscopables@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" + integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + dependencies: + has "^1.0.3" + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -6961,12 +7187,12 @@ escape-goat@^2.0.0: escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== escape-string-regexp@^2.0.0: version "2.0.0" @@ -7015,9 +7241,9 @@ eslint-plugin-eslint-comments@^3.2.0: ignore "^5.0.5" eslint-plugin-eslint-plugin@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-eslint-plugin/-/eslint-plugin-eslint-plugin-4.1.0.tgz#40ae944d79e845dc9d4a85328eea3c5bf4ae0f7d" - integrity sha512-QJVw+WYXJuG2469gx5G929bz7crfxySDlK1i569FkuT6dpeHDeP7MmDrKaswCx17snG25LRFD6wmVX+AO5x7Qg== + version "4.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-eslint-plugin/-/eslint-plugin-eslint-plugin-4.2.0.tgz#64c5ba82f9b1073c89a79a1c8f451f278be6603a" + integrity sha512-ZDyUUlZJw85hmc9pGciNFiQwojXKxV7KAAVnQtojk1W/I8YYHxYV9JBuzhfAYfVemiQzDPNwj1zwAqQwGN1ROw== dependencies: eslint-utils "^3.0.0" estraverse "^5.2.0" @@ -7042,9 +7268,9 @@ eslint-plugin-import@^2.25.2: tsconfig-paths "^3.14.1" eslint-plugin-jest@^26.0.0: - version "26.1.5" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-26.1.5.tgz#6cfca264818d6d6aa120b019dab4d62b6aa8e775" - integrity sha512-su89aDuljL9bTjEufTXmKUMSFe2kZUL9bi7+woq+C2ukHZordhtfPm4Vg+tdioHBaKf8v3/FXW9uV0ksqhYGFw== + version "26.4.6" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-26.4.6.tgz#9d8184c1ecf077722a20cc236c7e14f4e263606f" + integrity sha512-R3mq1IepnhtsukHQsWxdyKra3OVwYB+N4k8i45ndqSfr8p9KZV6G+EIUt1Z7hzAh4KlsbXG+nCTlNeGFLFLNvA== dependencies: "@typescript-eslint/utils" "^5.10.0" @@ -7072,24 +7298,24 @@ eslint-plugin-react-hooks@^4.3.0: integrity sha512-8k1gRt7D7h03kd+SAAlzXkQwWK22BnK6GKZG+FJA6BAGy22CFvl8kCIXKpVux0cCxMWDQUPqSok0LKaZ0aOcCw== eslint-plugin-react@^7.27.1: - version "7.29.4" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.29.4.tgz#4717de5227f55f3801a5fd51a16a4fa22b5914d2" - integrity sha512-CVCXajliVh509PcZYRFyu/BoUEz452+jtQJq2b3Bae4v3xBUWPLCmtmBM+ZinG4MzwmxJgJ2M5rMqhqLVn7MtQ== + version "7.30.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.30.0.tgz#8e7b1b2934b8426ac067a0febade1b13bd7064e3" + integrity sha512-RgwH7hjW48BleKsYyHK5vUAvxtE9SMPDKmcPRQgtRCYaZA0XQPt5FSkrU3nhz5ifzMZcA8opwmRJ2cmOO8tr5A== dependencies: - array-includes "^3.1.4" - array.prototype.flatmap "^1.2.5" + array-includes "^3.1.5" + array.prototype.flatmap "^1.3.0" doctrine "^2.1.0" estraverse "^5.3.0" jsx-ast-utils "^2.4.1 || ^3.0.0" minimatch "^3.1.2" object.entries "^1.1.5" object.fromentries "^2.0.5" - object.hasown "^1.1.0" + object.hasown "^1.1.1" object.values "^1.1.5" prop-types "^15.8.1" resolve "^2.0.0-next.3" semver "^6.3.0" - string.prototype.matchall "^4.0.6" + string.prototype.matchall "^4.0.7" eslint-plugin-simple-import-sort@^7.0.0: version "7.0.0" @@ -7104,10 +7330,10 @@ eslint-scope@5.1.1, eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-scope@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.0.tgz#c1f6ea30ac583031f203d65c73e723b01298f153" - integrity sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg== +eslint-scope@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" + integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" @@ -7124,17 +7350,17 @@ eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== -eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.1.0, eslint-visitor-keys@^3.2.0: +eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== eslint@*, eslint@^8.7.0: - version "8.7.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.7.0.tgz#22e036842ee5b7cf87b03fe237731675b4d3633c" - integrity sha512-ifHYzkBGrzS2iDU7KjhCAVMGCvF6M3Xfs8X8b37cgrUlDt6bWRTpRh6T/gtSXv1HJ/BUGgmjvNvOEGu85Iif7w== + version "8.16.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.16.0.tgz#6d936e2d524599f2a86c708483b4c372c5d3bbae" + integrity sha512-MBndsoXY/PeVTDJeWsYj7kLZ5hQpJOfMYLsF6LicLHQWbRDG19lK5jOix4DPl8yY4SUFcE3txy86OzFLWT+yoA== dependencies: - "@eslint/eslintrc" "^1.0.5" + "@eslint/eslintrc" "^1.3.0" "@humanwhocodes/config-array" "^0.9.2" ajv "^6.10.0" chalk "^4.0.0" @@ -7142,17 +7368,17 @@ eslint@*, eslint@^8.7.0: debug "^4.3.2" doctrine "^3.0.0" escape-string-regexp "^4.0.0" - eslint-scope "^7.1.0" + eslint-scope "^7.1.1" eslint-utils "^3.0.0" - eslint-visitor-keys "^3.2.0" - espree "^9.3.0" + eslint-visitor-keys "^3.3.0" + espree "^9.3.2" esquery "^1.4.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" file-entry-cache "^6.0.1" functional-red-black-tree "^1.0.1" glob-parent "^6.0.1" - globals "^13.6.0" + globals "^13.15.0" ignore "^5.2.0" import-fresh "^3.0.0" imurmurhash "^0.1.4" @@ -7161,7 +7387,7 @@ eslint@*, eslint@^8.7.0: json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" lodash.merge "^4.6.2" - minimatch "^3.0.4" + minimatch "^3.1.2" natural-compare "^1.4.0" optionator "^0.9.1" regexpp "^3.2.0" @@ -7170,14 +7396,14 @@ eslint@*, eslint@^8.7.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^9.2.0, espree@^9.3.0: - version "9.3.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.0.tgz#c1240d79183b72aaee6ccfa5a90bc9111df085a8" - integrity sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ== +espree@^9.3.2: + version "9.3.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.2.tgz#f58f77bd334731182801ced3380a8cc859091596" + integrity sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA== dependencies: - acorn "^8.7.0" - acorn-jsx "^5.3.1" - eslint-visitor-keys "^3.1.0" + acorn "^8.7.1" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.3.0" esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" @@ -7231,7 +7457,7 @@ eta@^1.12.3: etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== eval@^0.1.8: version "0.1.8" @@ -7296,12 +7522,12 @@ executable@^4.1.1: exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== expand-tilde@^2.0.0, expand-tilde@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" - integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= + integrity sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw== dependencies: homedir-polyfill "^1.0.1" @@ -7315,38 +7541,50 @@ expect@^27.5.1: jest-matcher-utils "^27.5.1" jest-message-util "^27.5.1" -express@^4.17.1: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== +expect@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-28.1.0.tgz#10e8da64c0850eb8c39a480199f14537f46e8360" + integrity sha512-qFXKl8Pmxk8TBGfaFKRtcQjfXEnKAs+dmlxdwvukJZorwrAabT7M3h8oLOG01I2utEhkmUTi17CHaPBovZsKdw== + dependencies: + "@jest/expect-utils" "^28.1.0" + jest-get-type "^28.0.2" + jest-matcher-utils "^28.1.0" + jest-message-util "^28.1.0" + jest-util "^28.1.0" + +express@^4.17.3: + version "4.18.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf" + integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q== dependencies: - accepts "~1.3.7" + accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" + body-parser "1.20.0" + content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.4.0" + cookie "0.5.0" cookie-signature "1.0.6" debug "2.6.9" - depd "~1.1.2" + depd "2.0.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "~1.1.2" + finalhandler "1.2.0" fresh "0.5.2" + http-errors "2.0.0" merge-descriptors "1.0.1" methods "~1.1.2" - on-finished "~2.3.0" + on-finished "2.4.1" parseurl "~1.3.3" path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" + proxy-addr "~2.0.7" + qs "6.10.3" range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" type-is "~1.6.18" utils-merge "1.0.1" vary "~1.1.2" @@ -7354,7 +7592,7 @@ express@^4.17.1: extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== dependencies: is-extendable "^0.1.0" @@ -7386,18 +7624,23 @@ extract-zip@2.0.1: extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-equals@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-3.0.3.tgz#8e6cb4e51ca1018d87dd41982ef92758b3e4197f" + integrity sha512-NCe8qxnZFARSHGztGMZOO/PC1qa5MIFB5Hp66WdzbCRAz8U8US3bx1UTgLS49efBQPcUtO9gf5oVEY8o7y/7Kg== + fast-glob@3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" @@ -7409,10 +7652,10 @@ fast-glob@3.2.7: merge2 "^1.3.0" micromatch "^4.0.4" -fast-glob@^3.2.7, fast-glob@^3.2.9: - version "3.2.10" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.10.tgz#2734f83baa7f43b7fd41e13bc34438f4ffe284ee" - integrity sha512-s9nFhFnvR63wls6/kM88kQqDhMu0AfdjqouE2l5GVQPbqLgyFjjU5ry/r2yKsJxpb9Py1EYNqieFrmMaX4v++A== +fast-glob@^3.2.11, fast-glob@^3.2.7, fast-glob@^3.2.9: + version "3.2.11" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" + integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -7428,12 +7671,12 @@ fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fast-url-parser@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" - integrity sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0= + integrity sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ== dependencies: punycode "^1.3.2" @@ -7470,12 +7713,12 @@ fbjs-css-vars@^1.0.0: resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8" integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== -fbjs@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.1.tgz#70a053d34a96c2b513b559eaea124daed49ace64" - integrity sha512-8+vkGyT4lNDRKHQNPp0yh/6E7FfkLg89XqQbOYnvntRh+8RiSD43yrh9E5ejp1muCizTL4nDVG+y8W4e+LROHg== +fbjs@^3.0.0, fbjs@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.4.tgz#e1871c6bd3083bac71ff2da868ad5067d37716c6" + integrity sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ== dependencies: - cross-fetch "^3.0.4" + cross-fetch "^3.1.5" fbjs-css-vars "^1.0.0" loose-envify "^1.0.0" object-assign "^4.1.0" @@ -7486,7 +7729,7 @@ fbjs@^3.0.0: fd-slicer@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= + integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g== dependencies: pend "~1.2.0" @@ -7507,7 +7750,7 @@ figures@3.2.0, figures@^3.0.0, figures@^3.2.0: figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= + integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA== dependencies: escape-string-regexp "^1.0.5" @@ -7527,9 +7770,9 @@ file-loader@^6.2.0: schema-utils "^3.0.0" filelist@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.3.tgz#448607750376484932f67ef1b9ff07386b036c83" - integrity sha512-LwjCsruLWQULGYKy7TX0OPtrL9kLpojOFKc5VCTxdFTV7w5zbsgqVKfnkKG7Qgjtq50gKfO56hJv88OfcGb70Q== + version "1.0.4" + resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5" + integrity sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q== dependencies: minimatch "^5.0.1" @@ -7548,19 +7791,19 @@ fill-range@^7.0.1: filter-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" - integrity sha1-mzERErxsYSehbgFsbF1/GeCAXFs= + integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ== -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== dependencies: debug "2.6.9" encodeurl "~1.0.2" escape-html "~1.0.3" - on-finished "~2.3.0" + on-finished "2.4.1" parseurl "~1.3.3" - statuses "~1.5.0" + statuses "2.0.1" unpipe "~1.0.0" find-cache-dir@^3.3.1: @@ -7573,12 +7816,12 @@ find-cache-dir@^3.3.1: pkg-dir "^4.1.0" find-node-modules@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/find-node-modules/-/find-node-modules-2.1.2.tgz#57565a3455baf671b835bc6b2134a9b938b9c53c" - integrity sha512-x+3P4mbtRPlSiVE1Qco0Z4YLU8WFiFcuWTf3m75OV9Uzcfs2Bg+O9N+r/K0AnmINBW06KpfqKwYJbFlFq4qNug== + version "2.1.3" + resolved "https://registry.yarnpkg.com/find-node-modules/-/find-node-modules-2.1.3.tgz#3c976cff2ca29ee94b4f9eafc613987fc4c0ee44" + integrity sha512-UC2I2+nx1ZuOBclWVNdcnbDR5dlrOdVb7xNjmT/lHE+LsgztWks3dG7boJ37yTS/venXw84B/mAW9uHVoC5QRg== dependencies: findup-sync "^4.0.0" - merge "^2.1.0" + merge "^2.1.1" find-root@1.1.0: version "1.1.0" @@ -7588,7 +7831,7 @@ find-root@1.1.0: find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== dependencies: locate-path "^2.0.0" @@ -7639,32 +7882,32 @@ flat@^5.0.2: integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== flatted@^3.1.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.2.tgz#64bfed5cb68fe3ca78b3eb214ad97b63bedce561" - integrity sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA== + version "3.2.5" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" + integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== flux@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/flux/-/flux-4.0.2.tgz#d71dcaf6cb51ca059f303f3d964d6f325d444952" - integrity sha512-u/ucO5ezm3nBvdaSGkWpDlzCePoV+a9x3KHmy13TV/5MzOaCZDN8Mfd94jmf0nOi8ZZay+nOKbBUkOe2VNaupQ== + version "4.0.3" + resolved "https://registry.yarnpkg.com/flux/-/flux-4.0.3.tgz#573b504a24982c4768fdfb59d8d2ea5637d72ee7" + integrity sha512-yKAbrp7JhZhj6uiT1FTuVMlIAT1J4jqEyBpFApi1kxpGZCvacMVc/t1pMQyotqHhAgvoE3bNvAykhCo2CLjnYw== dependencies: fbemitter "^3.0.0" - fbjs "^3.0.0" + fbjs "^3.0.1" follow-redirects@^1.0.0, follow-redirects@^1.14.0, follow-redirects@^1.14.7: - version "1.14.9" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" - integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== + version "1.15.1" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" + integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== fork-ts-checker-webpack-plugin@^6.5.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz#0282b335fa495a97e167f69018f566ea7d2a2b5e" - integrity sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw== + version "6.5.2" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz#4f67183f2f9eb8ba7df7177ce3cf3e75cdafb340" + integrity sha512-m5cUmF30xkZ7h4tWUgTAcEaKmUW7tfyUyTqNNOz7OxWJ0v1VWKTcOvH8FWHUwSjlW/356Ijc9vi3XfcPstpQKA== dependencies: "@babel/code-frame" "^7.8.3" "@types/json-schema" "^7.0.5" @@ -7711,7 +7954,7 @@ fraction.js@^4.2.0: fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== fs-extra@8.1.0: version "8.1.0" @@ -7722,10 +7965,10 @@ fs-extra@8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^10.0.0, fs-extra@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.1.tgz#27de43b4320e833f6867cc044bfce29fdf0ef3b8" - integrity sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag== +fs-extra@^10.0.0, fs-extra@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== dependencies: graceful-fs "^4.2.0" jsonfile "^6.0.1" @@ -7772,7 +8015,7 @@ fs-monkey@1.0.3: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@^2.3.2, fsevents@~2.3.2: version "2.3.2" @@ -7784,15 +8027,30 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== + +functions-have-names@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + integrity sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg== dependencies: aproba "^1.0.3" console-control-strings "^1.0.0" @@ -7894,14 +8152,14 @@ getos@^3.2.1: getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== dependencies: assert-plus "^1.0.0" git-raw-commits@^2.0.0, git-raw-commits@^2.0.8: - version "2.0.10" - resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.10.tgz#e2255ed9563b1c9c3ea6bd05806410290297bbc1" - integrity sha512-sHhX5lsbG9SOO6yXdlwgEMQ/ljIn7qMpAbJZCGfXX2fq5T8M5SrDnpYk9/4HswTildcIqatsWa91vty6VhWSaQ== + version "2.0.11" + resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.11.tgz#bc3576638071d18655e1cc60d7f524920008d723" + integrity sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A== dependencies: dargs "^7.0.0" lodash "^4.17.15" @@ -7912,7 +8170,7 @@ git-raw-commits@^2.0.0, git-raw-commits@^2.0.8: git-remote-origin-url@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz#5282659dae2107145a11126112ad3216ec5fa65f" - integrity sha1-UoJlna4hBxRaERJhEq0yFuxfpl8= + integrity sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw== dependencies: gitconfiglocal "^1.0.0" pify "^2.3.0" @@ -7943,7 +8201,7 @@ git-url-parse@^11.4.4: gitconfiglocal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz#41d045f3851a5ea88f03f24ca1c6178114464b9b" - integrity sha1-QdBF84UaXqiPA/JMocYXgRRGS5s= + integrity sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ== dependencies: ini "^1.3.2" @@ -7971,17 +8229,16 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@*, glob@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-8.0.1.tgz#00308f5c035aa0b2a447cd37ead267ddff1577d3" - integrity sha512-cF7FYZZ47YzmCu7dDy50xSRRfO3ErRfrXuLZcNIuyiJEco0XSrGtuilG19L5xp3NcwTx7Gn+X6Tv3fmsUPTbow== +glob@*, glob@^8.0.1, glob@^8.0.3: + version "8.0.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.0.3.tgz#415c6eb2deed9e502c68fa44a272e6da6eeca42e" + integrity sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" minimatch "^5.0.1" once "^1.3.0" - path-is-absolute "^1.0.0" glob@7.1.4: version "7.1.4" @@ -7995,22 +8252,22 @@ glob@7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0, glob@~7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== +glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.2.0: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.4" + minimatch "^3.1.1" once "^1.3.0" path-is-absolute "^1.0.0" global-dirs@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" - integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU= + integrity sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg== dependencies: ini "^1.3.4" @@ -8040,7 +8297,7 @@ global-modules@^2.0.0: global-prefix@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" - integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= + integrity sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg== dependencies: expand-tilde "^2.0.2" homedir-polyfill "^1.0.1" @@ -8062,10 +8319,10 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^13.6.0, globals@^13.9.0: - version "13.11.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.11.0.tgz#40ef678da117fe7bd2e28f1fab24951bd0255be7" - integrity sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g== +globals@^13.15.0: + version "13.15.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.15.0.tgz#38113218c907d2f7e98658af246cef8b77e90bac" + integrity sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog== dependencies: type-fest "^0.20.2" @@ -8081,15 +8338,14 @@ globby@^11.0.1, globby@^11.0.2, globby@^11.0.3, globby@^11.0.4, globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -globby@^12.0.2: - version "12.2.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-12.2.0.tgz#2ab8046b4fba4ff6eede835b29f678f90e3d3c22" - integrity sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA== +globby@^13.1.1: + version "13.1.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-13.1.1.tgz#7c44a93869b0b7612e38f22ed532bfe37b25ea6f" + integrity sha512-XMzoDZbGZ37tufiv7g0N4F/zp3zkwdFtVbV3EHsVl1KQr4RPLfNoT068/97RPshz2J5xYNEjLKKBKaGHifBd3Q== dependencies: - array-union "^3.0.1" dir-glob "^3.0.1" - fast-glob "^3.2.7" - ignore "^5.1.9" + fast-glob "^3.2.11" + ignore "^5.2.0" merge2 "^1.4.1" slash "^4.0.0" @@ -8111,9 +8367,9 @@ got@^9.6.0: url-parse-lax "^3.0.0" graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.3, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: - version "4.2.9" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== gray-matter@^4.0.3: version "4.0.3" @@ -8137,7 +8393,7 @@ handle-thing@^2.0.0: resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== -handlebars@^4.7.6: +handlebars@^4.7.7: version "4.7.7" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== @@ -8152,7 +8408,7 @@ handlebars@^4.7.6: har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== har-validator@~5.1.3: version "5.1.5" @@ -8172,15 +8428,15 @@ harmony-reflect@^1.4.6: resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.6.2.tgz#31ecbd32e648a34d030d86adb67d4d47547fe710" integrity sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g== -has-bigints@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" - integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" @@ -8192,10 +8448,17 @@ has-own-prop@^2.0.0: resolved "https://registry.yarnpkg.com/has-own-prop/-/has-own-prop-2.0.0.tgz#f0f95d58f65804f5d218db32563bb85b8e0417af" integrity sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ== -has-symbols@^1.0.1, has-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" - integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== has-tostringtag@^1.0.0: version "1.0.0" @@ -8207,7 +8470,7 @@ has-tostringtag@^1.0.0: has-unicode@^2.0.0, has-unicode@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== has-yarn@^2.1.0: version "2.1.0" @@ -8347,16 +8610,16 @@ hosted-git-info@^2.1.4: integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== hosted-git-info@^4.0.0, hosted-git-info@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.0.2.tgz#5e425507eede4fea846b7262f0838456c4209961" - integrity sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg== + version "4.1.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" + integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== dependencies: lru-cache "^6.0.0" hpack.js@^2.1.6: version "2.1.6" resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" - integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI= + integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ== dependencies: inherits "^2.0.1" obuf "^1.0.0" @@ -8371,9 +8634,9 @@ html-encoding-sniffer@^2.0.1: whatwg-encoding "^1.0.5" html-entities@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.2.tgz#760b404685cb1d794e4f4b744332e3b00dcfe488" - integrity sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ== + version "2.3.3" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" + integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA== html-escaper@^2.0.0: version "2.0.2" @@ -8393,10 +8656,10 @@ html-minifier-terser@^6.0.2, html-minifier-terser@^6.1.0: relateurl "^0.2.7" terser "^5.10.0" -html-tags@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" - integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg== +html-tags@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.2.0.tgz#dbb3518d20b726524e4dd43de397eb0a95726961" + integrity sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg== html-void-elements@^1.0.0: version "1.0.5" @@ -8436,6 +8699,16 @@ htmlparser2@^6.1.0: domutils "^2.5.2" entities "^2.0.0" +htmlparser2@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.1.tgz#abaa985474fcefe269bc761a779b544d7196d010" + integrity sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + domutils "^3.0.1" + entities "^4.3.0" + http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" @@ -8444,44 +8717,33 @@ http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0: http-deceiver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" - integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= + integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" http-errors@~1.6.2: version "1.6.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= + integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== dependencies: depd "~1.1.2" inherits "2.0.3" setprototypeof "1.1.0" statuses ">= 1.4.0 < 2" -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - http-parser-js@>=0.5.1: - version "0.5.3" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9" - integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg== + version "0.5.6" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.6.tgz#2e02406ab2df8af8a7abfba62e0da01c62b95afd" + integrity sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA== http-proxy-agent@^4.0.1: version "4.0.1" @@ -8492,12 +8754,12 @@ http-proxy-agent@^4.0.1: agent-base "6" debug "4" -http-proxy-middleware@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.1.tgz#7ef3417a479fb7666a571e09966c66a39bd2c15f" - integrity sha512-cfaXRVoZxSed/BmkA7SwBVNI9Kj7HFltaE5rqYOub5kWzWZ+gofV2koVN1j2rMW7pEfSSlCHGJ31xmuyFyfLOg== +http-proxy-middleware@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" + integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== dependencies: - "@types/http-proxy" "^1.17.5" + "@types/http-proxy" "^1.17.8" http-proxy "^1.18.1" is-glob "^4.0.1" is-plain-obj "^3.0.0" @@ -8515,7 +8777,7 @@ http-proxy@^1.18.1: http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== dependencies: assert-plus "^1.0.0" jsprim "^1.2.2" @@ -8531,9 +8793,9 @@ http-signature@~1.3.6: sshpk "^1.14.1" https-proxy-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" - integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== dependencies: agent-base "6" debug "4" @@ -8551,7 +8813,7 @@ human-signals@^2.1.0: humanize-ms@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" - integrity sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0= + integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ== dependencies: ms "^2.0.0" @@ -8582,7 +8844,7 @@ icss-utils@^5.0.0, icss-utils@^5.1.0: identity-obj-proxy@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz#94d2bda96084453ef36fbc5aaec37e0f79f1fc14" - integrity sha1-lNK9qWCERT7zb7xarsN+D3nx/BQ= + integrity sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA== dependencies: harmony-reflect "^1.4.6" @@ -8593,12 +8855,7 @@ ignore-walk@^3.0.3: dependencies: minimatch "^3.0.4" -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - -ignore@^5.0.4, ignore@^5.0.5, ignore@^5.1.8, ignore@^5.1.9, ignore@^5.2.0: +ignore@^5.0.4, ignore@^5.0.5, ignore@^5.1.8, ignore@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== @@ -8616,9 +8873,9 @@ image-size@^1.0.1: queue "6.0.2" immer@^9.0.7: - version "9.0.12" - resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.12.tgz#2d33ddf3ee1d247deab9d707ca472c8c942a0f20" - integrity sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA== + version "9.0.14" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.14.tgz#e05b83b63999d26382bb71676c9d827831248a48" + integrity sha512-ubBeqQutOSLIFCUBN03jGeOS6a3DoYlSYwYJTa+gSKEZKU5redJIqkIdZ3JVv/4RZpfcXdAWH5zCNLWPRv2WDw== import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" @@ -8631,7 +8888,7 @@ import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.3 import-lazy@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" - integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= + integrity sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A== import-lazy@~4.0.0: version "4.0.0" @@ -8639,9 +8896,9 @@ import-lazy@~4.0.0: integrity sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw== import-local@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.3.tgz#4d51c2c495ca9393da259ec66b62e022920211e0" - integrity sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA== + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== dependencies: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" @@ -8649,7 +8906,7 @@ import-local@^3.0.2: imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== indent-string@^4.0.0: version "4.0.0" @@ -8661,15 +8918,15 @@ infer-owner@^1.0.4: resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== -infima@0.2.0-alpha.38: - version "0.2.0-alpha.38" - resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.38.tgz#e41d95c7cd82756549b17df12f613fed4af3d528" - integrity sha512-1WsmqSMI5IqzrUx3goq+miJznHBonbE3aoqZ1AR/i/oHhroxNeSV6Awv5VoVfXBhfTzLSnxkHaRI2qpAMYcCzw== +infima@0.2.0-alpha.39: + version "0.2.0-alpha.39" + resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.39.tgz#054b13ac44f3e9a42bc083988f1a1586add2f59c" + integrity sha512-UyYiwD3nwHakGhuOUfpe3baJ8gkiPpRVx4a4sE/Ag+932+Y6swtLsdPoRR8ezhwqGnduzxmFkjumV9roz6QoLw== inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" wrappy "1" @@ -8682,7 +8939,7 @@ inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, i inherits@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== ini@2.0.0, ini@~2.0.0: version "2.0.0" @@ -8771,10 +9028,10 @@ invariant@^2.2.4: dependencies: loose-envify "^1.0.0" -ip@^1.1.0, ip@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= +ip@^1.1.5: + version "1.1.8" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.8.tgz#ae05948f6b075435ed3307acce04629da8cdbf48" + integrity sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg== ipaddr.js@1.9.1: version "1.9.1" @@ -8799,18 +9056,10 @@ is-alphanumerical@^1.0.0: is-alphabetical "^1.0.0" is-decimal "^1.0.0" -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== is-bigint@^1.0.1: version "1.0.4" @@ -8859,16 +9108,16 @@ is-ci@^2.0.0: ci-info "^2.0.0" is-ci@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.0.tgz#c7e7be3c9d8eef7d0fa144390bd1e4b88dc4c994" - integrity sha512-kDXyttuLeslKAHYL/K28F2YkM3x5jvFPEw3yXbRptXydjD9rpLEz+C5K5iutY9ZiUu6AP41JdvRQwF4Iqs4ZCQ== + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867" + integrity sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ== dependencies: - ci-info "^3.1.1" + ci-info "^3.2.0" is-core-module@^2.1.0, is-core-module@^2.2.0, is-core-module@^2.5.0, is-core-module@^2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" - integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== + version "2.9.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" + integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== dependencies: has "^1.0.3" @@ -8892,24 +9141,24 @@ is-docker@^2.0.0, is-docker@^2.1.1: is-extendable@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== is-fullwidth-code-point@^3.0.0: version "3.0.0" @@ -8949,17 +9198,17 @@ is-installed-globally@^0.4.0, is-installed-globally@~0.4.0: is-lambda@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" - integrity sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU= + integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ== is-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" - integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE= + integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g== -is-negative-zero@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" - integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== is-npm@^5.0.0: version "5.0.0" @@ -8967,9 +9216,9 @@ is-npm@^5.0.0: integrity sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA== is-number-object@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" - integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== dependencies: has-tostringtag "^1.0.0" @@ -8981,7 +9230,7 @@ is-number@^7.0.0: is-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= + integrity sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg== is-obj@^2.0.0: version "2.0.0" @@ -9001,7 +9250,7 @@ is-path-inside@^3.0.2: is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= + integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== is-plain-obj@^2.0.0: version "2.1.0" @@ -9037,7 +9286,7 @@ is-reference@^1.2.1: dependencies: "@types/estree" "*" -is-regex@^1.0.4, is-regex@^1.1.4: +is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== @@ -9048,17 +9297,19 @@ is-regex@^1.0.4, is-regex@^1.1.4: is-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" - integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= + integrity sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA== is-root@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg== -is-shared-array-buffer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" - integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" is-ssh@^1.3.0: version "1.3.3" @@ -9089,14 +9340,14 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: is-text-path@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-1.0.1.tgz#4e1aa0fb51bfbcb3e92688001397202c1775b66e" - integrity sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4= + integrity sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w== dependencies: text-extensions "^1.0.0" is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== is-unicode-supported@^0.1.0: version "0.1.0" @@ -9106,14 +9357,14 @@ is-unicode-supported@^0.1.0: is-utf8@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= + integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q== -is-weakref@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.1.tgz#842dba4ec17fa9ac9850df2d6efbc1737274f2a2" - integrity sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ== +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== dependencies: - call-bind "^1.0.0" + call-bind "^1.0.2" is-whitespace-character@^1.0.0: version "1.0.4" @@ -9145,27 +9396,27 @@ is-yarn-global@^0.3.0: isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: version "3.2.0" @@ -9183,9 +9434,9 @@ istanbul-lib-instrument@^4.0.3: semver "^6.3.0" istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz#7b49198b657b27a730b8e9cb601f1e1bff24c59a" - integrity sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q== + version "5.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz#31d18bdd127f825dd02ea7bfdfd906f8ab840e9f" + integrity sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A== dependencies: "@babel/core" "^7.12.3" "@babel/parser" "^7.14.7" @@ -9212,9 +9463,9 @@ istanbul-lib-source-maps@^4.0.0: source-map "^0.6.1" istanbul-reports@^3.0.2, istanbul-reports@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.3.tgz#4bcae3103b94518117930d51283690960b50d3c2" - integrity sha512-x9LtDVtfm/t1GFiLl3NffC7hz+I1ragvgX1P/Lg1NlIagifZDKUkuuaAxH/qpwj2IuEfD8G2Bs/UKp+sZ/pKkg== + version "3.1.4" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.4.tgz#1b6f068ecbc6c331040aab5741991273e609e40c" + integrity sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw== dependencies: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" @@ -9338,7 +9589,17 @@ jest-config@^27.5.1: slash "^3.0.0" strip-json-comments "^3.1.1" -jest-diff@*, jest-diff@^27.3.1, jest-diff@^27.5.1: +jest-diff@*, jest-diff@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-28.1.0.tgz#77686fef899ec1873dbfbf9330e37dd429703269" + integrity sha512-8eFd3U3OkIKRtlasXfiAQfbovgFgRDb0Ngcs2E+FMeBZ4rUezqIaGjuyggJBp+llosQXNEWofk/Sz4Hr5gMUhA== + dependencies: + chalk "^4.0.0" + diff-sequences "^28.0.2" + jest-get-type "^28.0.2" + pretty-format "^28.1.0" + +jest-diff@^27.3.1, jest-diff@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== @@ -9396,6 +9657,11 @@ jest-get-type@^27.0.6, jest-get-type@^27.5.1: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== +jest-get-type@^28.0.2: + version "28.0.2" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-28.0.2.tgz#34622e628e4fdcd793d46db8a242227901fcf203" + integrity sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA== + jest-haste-map@^27.2.2, jest-haste-map@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.5.1.tgz#9fd8bd7e7b4fa502d9c6164c5640512b4e811e7f" @@ -9416,6 +9682,25 @@ jest-haste-map@^27.2.2, jest-haste-map@^27.5.1: optionalDependencies: fsevents "^2.3.2" +jest-haste-map@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-28.1.0.tgz#6c1ee2daf1c20a3e03dbd8e5b35c4d73d2349cf0" + integrity sha512-xyZ9sXV8PtKi6NCrJlmq53PyNVHzxmcfXNVvIRHpHmh1j/HChC4pwKgyjj7Z9us19JMw8PpQTJsFWOsIfT93Dw== + dependencies: + "@jest/types" "^28.1.0" + "@types/graceful-fs" "^4.1.3" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^28.0.2" + jest-util "^28.1.0" + jest-worker "^28.1.0" + micromatch "^4.0.4" + walker "^1.0.7" + optionalDependencies: + fsevents "^2.3.2" + jest-jasmine2@^27.2.2, jest-jasmine2@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz#a037b0034ef49a9f3d71c4375a796f3b230d1ac4" @@ -9457,6 +9742,16 @@ jest-matcher-utils@^27.0.0, jest-matcher-utils@^27.5.1: jest-get-type "^27.5.1" pretty-format "^27.5.1" +jest-matcher-utils@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-28.1.0.tgz#2ae398806668eeabd293c61712227cb94b250ccf" + integrity sha512-onnax0n2uTLRQFKAjC7TuaxibrPSvZgKTcSCnNUz/tOjJ9UhxNm7ZmPpoQavmTDUjXvUQ8KesWk2/VdrxIFzTQ== + dependencies: + chalk "^4.0.0" + jest-diff "^28.1.0" + jest-get-type "^28.0.2" + pretty-format "^28.1.0" + jest-message-util@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.5.1.tgz#bdda72806da10d9ed6425e12afff38cd1458b6cf" @@ -9472,6 +9767,21 @@ jest-message-util@^27.5.1: slash "^3.0.0" stack-utils "^2.0.3" +jest-message-util@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-28.1.0.tgz#7e8f0b9049e948e7b94c2a52731166774ba7d0af" + integrity sha512-RpA8mpaJ/B2HphDMiDlrAZdDytkmwFqgjDZovM21F35lHGeUeCvYmm6W+sbQ0ydaLpg5bFAUuWG1cjqOl8vqrw== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^28.1.0" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^28.1.0" + slash "^3.0.0" + stack-utils "^2.0.3" + jest-mock@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.5.1.tgz#19948336d49ef4d9c52021d34ac7b5f36ff967d6" @@ -9490,6 +9800,11 @@ jest-regex-util@^27.0.6, jest-regex-util@^27.5.1: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95" integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg== +jest-regex-util@^28.0.2: + version "28.0.2" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-28.0.2.tgz#afdc377a3b25fb6e80825adcf76c854e5bf47ead" + integrity sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw== + jest-resolve-dependencies@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz#d811ecc8305e731cc86dd79741ee98fed06f1da8" @@ -9594,7 +9909,36 @@ jest-serializer@^27.5.1: "@types/node" "*" graceful-fs "^4.2.9" -jest-snapshot@*, jest-snapshot@^27.0.2, jest-snapshot@^27.3.1, jest-snapshot@^27.5.1: +jest-snapshot@*: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-28.1.0.tgz#4b74fa8816707dd10fe9d551c2c258e5a67b53b6" + integrity sha512-ex49M2ZrZsUyQLpLGxQtDbahvgBjlLPgklkqGM0hq/F7W/f8DyqZxVHjdy19QKBm4O93eDp+H5S23EiTbbUmHw== + dependencies: + "@babel/core" "^7.11.6" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/traverse" "^7.7.2" + "@babel/types" "^7.3.3" + "@jest/expect-utils" "^28.1.0" + "@jest/transform" "^28.1.0" + "@jest/types" "^28.1.0" + "@types/babel__traverse" "^7.0.6" + "@types/prettier" "^2.1.5" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^28.1.0" + graceful-fs "^4.2.9" + jest-diff "^28.1.0" + jest-get-type "^28.0.2" + jest-haste-map "^28.1.0" + jest-matcher-utils "^28.1.0" + jest-message-util "^28.1.0" + jest-util "^28.1.0" + natural-compare "^1.4.0" + pretty-format "^28.1.0" + semver "^7.3.5" + +jest-snapshot@^27.0.2, jest-snapshot@^27.3.1, jest-snapshot@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.5.1.tgz#b668d50d23d38054a51b42c4039cab59ae6eb6a1" integrity sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA== @@ -9653,6 +9997,18 @@ jest-util@^27.2.0, jest-util@^27.5.1: graceful-fs "^4.2.9" picomatch "^2.2.3" +jest-util@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-28.1.0.tgz#d54eb83ad77e1dd441408738c5a5043642823be5" + integrity sha512-qYdCKD77k4Hwkose2YBEqQk7PzUf/NSE+rutzceduFveQREeH6b+89Dc9+wjX9dAwHcgdx4yedGA3FQlU/qCTA== + dependencies: + "@jest/types" "^28.1.0" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + jest-validate@^27.2.2, jest-validate@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.5.1.tgz#9197d54dc0bdb52260b8db40b46ae668e04df067" @@ -9678,7 +10034,7 @@ jest-watcher@^27.5.1: jest-util "^27.5.1" string-length "^4.0.1" -jest-worker@^27.0.2, jest-worker@^27.2.2, jest-worker@^27.4.5, jest-worker@^27.5.1: +jest-worker@^27.2.2, jest-worker@^27.4.5, jest-worker@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== @@ -9687,6 +10043,15 @@ jest-worker@^27.0.2, jest-worker@^27.2.2, jest-worker@^27.4.5, jest-worker@^27.5 merge-stream "^2.0.0" supports-color "^8.0.0" +jest-worker@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-28.1.0.tgz#ced54757a035e87591e1208253a6e3aac1a855e5" + integrity sha512-ZHwM6mNwaWBR52Snff8ZvsCTqQsvhCxP/bT1I6T6DAnb6ygkshsyLQIMxFwHpYxht0HOoqt23JlC01viI7T03A== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + jest@^27.3.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest/-/jest-27.5.1.tgz#dadf33ba70a779be7a6fc33015843b51494f63fc" @@ -9699,7 +10064,7 @@ jest@^27.3.1: jju@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" - integrity sha1-o6vicYryQaKykE+EpiWXDzia4yo= + integrity sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA== joi@^17.6.0: version "17.6.0" @@ -9735,7 +10100,7 @@ js-yaml@^4.1.0: jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== jsdom@^16.6.0: version "16.7.0" @@ -9778,28 +10143,28 @@ jsesc@^2.5.1: jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== json-buffer@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + integrity sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ== json-fixer@^1.5.1: - version "1.6.12" - resolved "https://registry.yarnpkg.com/json-fixer/-/json-fixer-1.6.12.tgz#352026c905c6366e214c9f10f77d6d7f93c48322" - integrity sha512-BGO9HExf0ZUVYvuWsps71Re513Ss0il1Wp7wYWkir2NthzincvNJEUu82KagEfAkGdjOMsypj3t2JB7drBKWnA== + version "1.6.13" + resolved "https://registry.yarnpkg.com/json-fixer/-/json-fixer-1.6.13.tgz#27d2f0e837aec54afbc9ec1cd8c1dd965bf534c9" + integrity sha512-DKQ71M+0uwAG3QsUkeVgh6XREw/OkpnTfHfM+sdmxRjHvYZ8PlcMVF4ibsHQ1ckR63NROs68qUr1I0u6yPVePQ== dependencies: "@babel/runtime" "^7.14.6" - chalk "^4.1.1" + chalk "^4.1.2" pegjs "^0.10.0" -json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: +json-parse-better-errors@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== -json-parse-even-better-errors@^2.3.0: +json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== @@ -9819,20 +10184,15 @@ json-schema@*, json-schema@0.4.0: resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== json5@^1.0.1: version "1.0.1" @@ -9854,7 +10214,7 @@ jsonc-parser@3.0.0, jsonc-parser@~3.0.0: jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== optionalDependencies: graceful-fs "^4.1.6" @@ -9870,16 +10230,16 @@ jsonfile@^6.0.1: jsonparse@^1.2.0, jsonparse@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" - integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= + integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== dependencies: assert-plus "1.0.0" extsprintf "1.3.0" - json-schema "0.2.3" + json-schema "0.4.0" verror "1.10.0" jsprim@^2.0.2: @@ -9893,11 +10253,11 @@ jsprim@^2.0.2: verror "1.10.0" "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz#720b97bfe7d901b927d87c3773637ae8ea48781b" - integrity sha512-uP5vu8xfy2F9A6LGC22KO7e2/vGTS1MhP+18f++ZNlf0Ohaxbc9nIEwHAsejlJKyzfZzU5UIhe5ItYkitcZnZA== + version "3.3.0" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.0.tgz#e624f259143b9062c92b6413ff92a164c80d3ccb" + integrity sha512-XzO9luP6L0xkxwhIJMTJQpZo/eeN60K08jHdexfD569AGxeNug6UketeHXEhROoM8aR7EcUoOQmIhcJQjcuq8Q== dependencies: - array-includes "^3.1.3" + array-includes "^3.1.4" object.assign "^4.1.2" keyv@^3.0.0: @@ -9943,7 +10303,7 @@ language-subtag-registry@~0.3.2: language-tags@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.5.tgz#d321dbc4da30ba8bf3024e040fa5c14661f9193a" - integrity sha1-0yHbxNowuovzAk4ED6XBRmH5GTo= + integrity sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ== dependencies: language-subtag-registry "~0.3.2" @@ -9957,7 +10317,7 @@ latest-version@^5.1.0: lazy-ass@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" - integrity sha1-eZllXoZGwX8In90YfRUNMyTVRRM= + integrity sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw== lerna@^4.0.0: version "4.0.0" @@ -9999,7 +10359,7 @@ levn@^0.4.1: levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" @@ -10025,15 +10385,15 @@ libnpmpublish@^4.0.0: semver "^7.1.3" ssri "^8.0.1" -lilconfig@2.0.4, lilconfig@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.4.tgz#f4507d043d7058b380b6a8f5cb7bcd4b34cee082" - integrity sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA== +lilconfig@2.0.5, lilconfig@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.5.tgz#19e57fd06ccc3848fd1891655b5a447092225b25" + integrity sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg== lines-and-columns@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" - integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== linkify-it@^3.0.1: version "3.0.3" @@ -10043,57 +10403,57 @@ linkify-it@^3.0.1: uc.micro "^1.0.1" lint-staged@^12.0.2: - version "12.4.1" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-12.4.1.tgz#63fa27bfc8a33515f6902f63f6670864f1fb233c" - integrity sha512-PTXgzpflrQ+pODQTG116QNB+Q6uUTDg5B5HqGvNhoQSGt8Qy+MA/6zSnR8n38+sxP5TapzeQGTvoKni0KRS8Vg== + version "12.5.0" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-12.5.0.tgz#d6925747480ae0e380d13988522f9dd8ef9126e3" + integrity sha512-BKLUjWDsKquV/JuIcoQW4MSAI3ggwEImF1+sB4zaKvyVx1wBk3FsG7UK9bpnmBTN1pm7EH2BBcMwINJzCRv12g== dependencies: cli-truncate "^3.1.0" colorette "^2.0.16" - commander "^8.3.0" - debug "^4.3.3" + commander "^9.3.0" + debug "^4.3.4" execa "^5.1.1" - lilconfig "2.0.4" - listr2 "^4.0.1" - micromatch "^4.0.4" + lilconfig "2.0.5" + listr2 "^4.0.5" + micromatch "^4.0.5" normalize-path "^3.0.0" - object-inspect "^1.12.0" + object-inspect "^1.12.2" pidtree "^0.5.0" string-argv "^0.3.1" - supports-color "^9.2.1" + supports-color "^9.2.2" yaml "^1.10.2" listr2@^3.8.3: - version "3.13.5" - resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.13.5.tgz#105a813f2eb2329c4aae27373a281d610ee4985f" - integrity sha512-3n8heFQDSk+NcwBn3CgxEibZGaRzx+pC64n3YjpMD1qguV4nWus3Al+Oo3KooqFKTQEJ1v7MmnbnyyNspgx3NA== + version "3.14.0" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.14.0.tgz#23101cc62e1375fd5836b248276d1d2b51fdbe9e" + integrity sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g== dependencies: cli-truncate "^2.1.0" colorette "^2.0.16" log-update "^4.0.0" p-map "^4.0.0" rfdc "^1.3.0" - rxjs "^7.4.0" + rxjs "^7.5.1" through "^2.3.8" wrap-ansi "^7.0.0" -listr2@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/listr2/-/listr2-4.0.1.tgz#e050c1fd390276e191f582603d6e3531cd6fd2b3" - integrity sha512-D65Nl+zyYHL2jQBGmxtH/pU8koPZo5C8iCNE8EoB04RwPgQG1wuaKwVbeZv9LJpiH4Nxs0FCp+nNcG8OqpniiA== +listr2@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-4.0.5.tgz#9dcc50221583e8b4c71c43f9c7dfd0ef546b75d5" + integrity sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA== dependencies: cli-truncate "^2.1.0" colorette "^2.0.16" log-update "^4.0.0" p-map "^4.0.0" rfdc "^1.3.0" - rxjs "^7.5.2" + rxjs "^7.5.5" through "^2.3.8" wrap-ansi "^7.0.0" load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= + integrity sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw== dependencies: graceful-fs "^4.1.2" parse-json "^4.0.0" @@ -10111,14 +10471,14 @@ load-json-file@^6.2.0: type-fest "^0.6.0" loader-runner@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" - integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== loader-utils@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.1.tgz#3b8d4386f42378d6434d32d7bc08e7a52d39575e" - integrity sha512-g4miPa9uUrZz4iElkaVJgDFwKJGh8aQGM7pUL4ejXl6cu7kSb30seQOVGNMP6sW8j7DW77X68hJZ+GM7UGhXeQ== + version "2.0.2" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129" + integrity sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A== dependencies: big.js "^5.2.2" emojis-list "^3.0.0" @@ -10132,7 +10492,7 @@ loader-utils@^3.2.0: locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== dependencies: p-locate "^2.0.0" path-exists "^3.0.0" @@ -10162,82 +10522,82 @@ locate-path@^6.0.0: lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= + integrity sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA== lodash.assignin@^4.0.9: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" - integrity sha1-uo31+4QesKPoBEIysOJjqNxqKKI= + integrity sha512-yX/rx6d/UTVh7sSVWVSIMjfnz95evAgDFdb1ZozC35I9mSFCkmzptOzevxjgbQUsc78NR44LVHWjsoMQXy9FDg== lodash.bind@^4.1.4: version "4.2.1" resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" - integrity sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU= + integrity sha512-lxdsn7xxlCymgLYo1gGvVrfHmkjDiyqVv62FAeF2i5ta72BipE1SLxw8hPEPLhD4/247Ijw07UQH7Hq/chT5LA== lodash.curry@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.curry/-/lodash.curry-4.1.1.tgz#248e36072ede906501d75966200a86dab8b23170" - integrity sha1-JI42By7ekGUB11lmIAqG2riyMXA= + integrity sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA== lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== lodash.defaults@^4.0.1: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" - integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= + integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== lodash.differencewith@~4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.differencewith/-/lodash.differencewith-4.5.0.tgz#bafafbc918b55154e179176a00bb0aefaac854b7" - integrity sha1-uvr7yRi1UVTheRdqALsK76rIVLc= + integrity sha512-/8JFjydAS+4bQuo3CpLMBv7WxGFyk7/etOAsrQUCu0a9QVDemxv0YQ0rFyeZvqlUD314SERfNlgnlqqHmaQ0Cg== lodash.filter@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace" - integrity sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4= + integrity sha512-pXYUy7PR8BCLwX5mgJ/aNtyOvuJTdZAo9EQFUvMIYugqmJxnrYaANvTbgndOzHSCSR0wnlBBfRXJL5SbWxo3FQ== lodash.flatten@^4.2.0, lodash.flatten@~4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" - integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= + integrity sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g== lodash.flow@^3.3.0: version "3.5.0" resolved "https://registry.yarnpkg.com/lodash.flow/-/lodash.flow-3.5.0.tgz#87bf40292b8cf83e4e8ce1a3ae4209e20071675a" - integrity sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o= + integrity sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw== lodash.foreach@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" - integrity sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM= + integrity sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ== lodash.get@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= + integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ== lodash.isequal@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== lodash.ismatch@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" - integrity sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc= + integrity sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g== lodash.map@^4.4.0, lodash.map@^4.5.1: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" - integrity sha1-dx7Hg540c9nEzeKLGTlMNWL09tM= + integrity sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q== lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== lodash.merge@^4.4.0, lodash.merge@^4.6.2: version "4.6.2" @@ -10247,27 +10607,27 @@ lodash.merge@^4.4.0, lodash.merge@^4.6.2: lodash.once@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" - integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= + integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== lodash.pick@^4.2.1: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" - integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM= + integrity sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q== lodash.reduce@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b" - integrity sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs= + integrity sha512-6raRe2vxCYBhpBu+B+TtNGUzah+hQjVdu3E17wfusjyrXBka2nBS8OH/gjVZ5PvHOhWmIZTYri09Z6n/QfnNMw== lodash.reject@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415" - integrity sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU= + integrity sha512-qkTuvgEzYdyhiJBx42YPzPo71R1aEr0z79kAv7Ixg8wPFEjgRgJdUsGMG3Hf3OYSF/kHI79XhNlt+5Ar6OzwxQ== lodash.some@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" - integrity sha1-G7nzFO9ri63tE7VJFpsqlF62jk0= + integrity sha512-j7MJE+TuT51q9ggt4fSgVqro163BEFjAt3u97IqU+JA2DkWl80nFTrowzLpZ/BnpN7rrl0JA/593NAdd8p/scQ== lodash.template@^4.5.0: version "4.5.0" @@ -10287,9 +10647,9 @@ lodash.templatesettings@^4.0.0: lodash.uniq@4.5.0, lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= + integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== -lodash@^4.11.2, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0, lodash@~4.17.15: +lodash@^4.11.2, lodash@^4.17.12, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0, lodash@~4.17.15: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -10315,7 +10675,7 @@ log-update@^4.0.0: longest@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-2.0.1.tgz#781e183296aa94f6d4d916dc335d0d17aefa23f8" - integrity sha1-eB4YMpaqlPbU2RbcM10NF676I/g= + integrity sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q== loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" @@ -10356,11 +10716,11 @@ lzstring.ts@^2.0.2: tslib "^1.10.0" magic-string@^0.25.7: - version "0.25.7" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" - integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== + version "0.25.9" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" + integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ== dependencies: - sourcemap-codec "^1.4.4" + sourcemap-codec "^1.4.8" make-dir@*, make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: version "3.1.0" @@ -10425,17 +10785,17 @@ make-fetch-happen@^9.0.1: socks-proxy-agent "^6.0.0" ssri "^8.0.0" -makeerror@1.0.x: - version "1.0.11" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" - integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw= +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== dependencies: - tmpl "1.0.x" + tmpl "1.0.5" map-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= + integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg== map-obj@^4.0.0: version "4.3.0" @@ -10536,17 +10896,17 @@ mdn-data@2.0.14: mdurl@^1.0.0, mdurl@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" - integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= + integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== -memfs@^3.1.2, memfs@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.1.tgz#b78092f466a0dce054d63d39275b24c71d3f1305" - integrity sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw== +memfs@^3.1.2, memfs@^3.4.3: + version "3.4.4" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.4.tgz#e8973cd8060548916adcca58a248e7805c715e89" + integrity sha512-W4gHNUE++1oSJVn8Y68jPXi+mkx3fXR5ITE/Ubz6EQ3xRpCN5k2CQ4AUR8094Z7211F876TyoBACGsIveqgiGA== dependencies: fs-monkey "1.0.3" @@ -10570,7 +10930,7 @@ meow@^8.0.0: merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== merge-stream@^2.0.0: version "2.0.0" @@ -10582,7 +10942,7 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -merge@^2.1.0: +merge@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/merge/-/merge-2.1.1.tgz#59ef4bf7e0b3e879186436e8481c06a6c162ca98" integrity sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w== @@ -10590,7 +10950,7 @@ merge@^2.1.0: methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: version "4.0.5" @@ -10600,10 +10960,10 @@ micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: braces "^3.0.2" picomatch "^2.3.1" -mime-db@1.50.0, "mime-db@>= 1.43.0 < 2": - version "1.50.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.50.0.tgz#abd4ac94e98d3c0e185016c67ab45d5fde40c11f" - integrity sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A== +mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== mime-db@~1.33.0: version "1.33.0" @@ -10617,23 +10977,18 @@ mime-types@2.1.18: dependencies: mime-db "~1.33.0" -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: - version "2.1.33" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.33.tgz#1fa12a904472fafd068e48d9e8401f74d3f70edb" - integrity sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g== +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: - mime-db "1.50.0" + mime-db "1.52.0" mime@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.3.1: - version "2.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" - integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== - mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" @@ -10674,14 +11029,14 @@ minimalistic-assert@^1.0.0: resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimatch@3.0.4, minimatch@~3.0.4: +minimatch@3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" -minimatch@^3.0.4, minimatch@^3.1.2: +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -10689,12 +11044,19 @@ minimatch@^3.0.4, minimatch@^3.1.2: brace-expansion "^1.1.7" minimatch@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" - integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== + version "5.1.0" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.0.tgz#1717b464f4971b144f6aabe8f2d0b8e4511e09c7" + integrity sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg== dependencies: brace-expansion "^2.0.1" +minimatch@~3.0.4: + version "3.0.8" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.8.tgz#5e6a59bd11e2ab0de1cfb843eb2d82e546c321c1" + integrity sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q== + dependencies: + brace-expansion "^1.1.7" + minimist-options@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" @@ -10770,9 +11132,9 @@ minipass@^2.6.0, minipass@^2.9.0: yallist "^3.0.0" minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3: - version "3.1.5" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.5.tgz#71f6251b0a33a49c01b3cf97ff77eda030dff732" - integrity sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw== + version "3.1.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee" + integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ== dependencies: yallist "^4.0.0" @@ -10801,11 +11163,11 @@ mkdirp-infer-owner@^2.0.0: mkdirp "^1.0.3" mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== dependencies: - minimist "^1.2.5" + minimist "^1.2.6" mkdirp@^1.0.3, mkdirp@^1.0.4: version "1.0.4" @@ -10822,37 +11184,32 @@ monaco-editor@^0.33.0: resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.33.0.tgz#842e244f3750a2482f8a29c676b5684e75ff34af" integrity sha512-VcRWPSLIUEgQJQIE0pVT8FcGBIgFoxz7jtqctE+IiCxWugD0DwgyQBcZBhdSrdMC84eumoqMZsGl2GTreOzwqw== +mrmime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.0.tgz#14d387f0585a5233d291baba339b063752a2398b" + integrity sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.0.0, ms@^2.1.1: +ms@2.1.3, ms@^2.0.0, ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -multicast-dns-service-types@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" - integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE= - -multicast-dns@^6.0.1: - version "6.2.3" - resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" - integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== +multicast-dns@^7.2.4: + version "7.2.5" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced" + integrity sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg== dependencies: - dns-packet "^1.3.1" + dns-packet "^5.2.2" thunky "^1.0.2" multimatch@^5.0.0: @@ -10869,32 +11226,32 @@ multimatch@^5.0.0: mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= + integrity sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ== mute-stream@0.0.8, mute-stream@~0.0.4: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nanoid@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" - integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== +nanoid@^3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" + integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== ncp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" - integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M= + integrity sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA== -negotiator@0.6.2, negotiator@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== +negotiator@0.6.3, negotiator@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== neo-async@^2.6.0, neo-async@^2.6.2: version "2.6.2" @@ -10921,22 +11278,22 @@ node-emoji@^1.10.0: dependencies: lodash "^4.17.21" -node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1: +node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" -node-forge@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.0.tgz#37a874ea723855f37db091e6c186e5b67a01d4b2" - integrity sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA== +node-forge@^1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== node-gyp-build@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" - integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q== + version "4.4.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.4.0.tgz#42e99687ce87ddeaf3a10b99dc06abc11021f3f4" + integrity sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ== node-gyp@^5.0.2: version "5.1.1" @@ -10974,17 +11331,17 @@ node-gyp@^7.1.0: node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== node-machine-id@^1.1.12: version "1.1.12" resolved "https://registry.yarnpkg.com/node-machine-id/-/node-machine-id-1.1.12.tgz#37904eee1e59b320bb9c5d6c0a59f3b469cb6267" integrity sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ== -node-releases@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01" - integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg== +node-releases@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.5.tgz#280ed5bc3eba0d96ce44897d8aee478bfb3d9666" + integrity sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q== nopt@^4.0.1: version "4.0.3" @@ -11029,7 +11386,7 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: normalize-range@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= + integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== normalize-url@^4.1.0: version "4.5.1" @@ -11156,10 +11513,10 @@ nprogress@^0.2.0: resolved "https://registry.yarnpkg.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1" integrity sha1-y480xTIT2JVyP8urkH6UIq28r7E= -nth-check@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2" - integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w== +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== dependencies: boolbase "^1.0.0" @@ -11197,20 +11554,12 @@ object-assign@^4.1.0, object-assign@^4.1.1: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= -object-inspect@^1.11.0, object-inspect@^1.12.0, object-inspect@^1.9.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" - integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== - -object-is@^1.0.1: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" +object-inspect@^1.12.0, object-inspect@^1.12.2, object-inspect@^1.9.0: + version "1.12.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" + integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== -object-keys@^1.0.12, object-keys@^1.1.1: +object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -11244,21 +11593,22 @@ object.fromentries@^2.0.5: es-abstract "^1.19.1" object.getownpropertydescriptors@^2.0.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz#b223cf38e17fefb97a63c10c91df72ccb386df9e" - integrity sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw== + version "2.1.4" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.4.tgz#7965e6437a57278b587383831a9b829455a4bc37" + integrity sha512-sccv3L/pMModT6dJAYF3fzGMVcb38ysQ0tEE6ixv2yXJDtEIPph268OlAdJj5/qZMZDq2g/jqvwppt36uS/uQQ== dependencies: + array.prototype.reduce "^1.0.4" call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" + define-properties "^1.1.4" + es-abstract "^1.20.1" -object.hasown@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.0.tgz#7232ed266f34d197d15cac5880232f7a4790afe5" - integrity sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg== +object.hasown@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.1.tgz#ad1eecc60d03f49460600430d97f23882cf592a3" + integrity sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A== dependencies: - define-properties "^1.1.3" - es-abstract "^1.19.1" + define-properties "^1.1.4" + es-abstract "^1.19.5" object.values@^1.1.5: version "1.1.5" @@ -11274,10 +11624,10 @@ obuf@^1.0.0, obuf@^1.1.2: resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== dependencies: ee-first "1.1.1" @@ -11458,11 +11808,11 @@ p-reduce@^2.0.0, p-reduce@^2.1.0: integrity sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw== p-retry@^4.5.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.1.tgz#8fcddd5cdf7a67a0911a9cf2ef0e5df7f602316c" - integrity sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA== + version "4.6.2" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" + integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== dependencies: - "@types/retry" "^0.12.0" + "@types/retry" "0.12.0" retry "^0.13.1" p-timeout@^3.2.0: @@ -11606,14 +11956,15 @@ parse-url@^6.0.0: parse-path "^4.0.0" protocols "^1.4.0" -parse5-htmlparser2-tree-adapter@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" - integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA== +parse5-htmlparser2-tree-adapter@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1" + integrity sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g== dependencies: - parse5 "^6.0.1" + domhandler "^5.0.2" + parse5 "^7.0.0" -parse5@6.0.1, parse5@^6.0.0, parse5@^6.0.1: +parse5@6.0.1, parse5@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== @@ -11623,6 +11974,13 @@ parse5@^5.0.0: resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== +parse5@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.0.0.tgz#51f74a5257f5fcc536389e8c2d0b3802e1bfa91a" + integrity sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g== + dependencies: + entities "^4.3.0" + parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -11745,7 +12103,7 @@ pify@^5.0.0: resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f" integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA== -pirates@^4.0.4: +pirates@^4.0.4, pirates@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== @@ -11764,15 +12122,6 @@ pkg-up@^3.1.0: dependencies: find-up "^3.0.0" -portfinder@^1.0.28: - version "1.0.28" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" - integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== - dependencies: - async "^2.6.2" - debug "^3.1.1" - mkdirp "^0.5.5" - postcss-calc@^8.2.3: version "8.2.4" resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5" @@ -11791,17 +12140,18 @@ postcss-colormin@^5.3.0: colord "^2.9.1" postcss-value-parser "^4.2.0" -postcss-convert-values@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.1.0.tgz#f8d3abe40b4ce4b1470702a0706343eac17e7c10" - integrity sha512-GkyPbZEYJiWtQB0KZ0X6qusqFHUepguBCNFi9t5JJc7I2OTXG7C0twbTLvCfaKOLl3rSXmpAwV7W5txd91V84g== +postcss-convert-values@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.1.2.tgz#31586df4e184c2e8890e8b34a0b9355313f503ab" + integrity sha512-c6Hzc4GAv95B7suy4udszX9Zy4ETyMCgFPUDtWjdFTKH1SE9eFY/jEpHSwTH1QPuwxHpWslhckUQWbNRM4ho5g== dependencies: + browserslist "^4.20.3" postcss-value-parser "^4.2.0" -postcss-discard-comments@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.1.1.tgz#e90019e1a0e5b99de05f63516ce640bd0df3d369" - integrity sha512-5JscyFmvkUxz/5/+TB3QTTT9Gi9jHkcn8dcmmuN68JQcv3aQg4y88yEHHhwFB52l/NkaJ43O0dbksGMAo49nfQ== +postcss-discard-comments@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz#8df5e81d2925af2780075840c1526f0660e53696" + integrity sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ== postcss-discard-duplicates@^5.1.0: version "5.1.0" @@ -11825,14 +12175,14 @@ postcss-discard-unused@^5.1.0: dependencies: postcss-selector-parser "^6.0.5" -postcss-loader@^6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-6.2.1.tgz#0895f7346b1702103d30fdc66e4d494a93c008ef" - integrity sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q== +postcss-loader@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-7.0.0.tgz#367d10eb1c5f1d93700e6b399683a6dc7c3af396" + integrity sha512-IDyttebFzTSY6DI24KuHUcBjbAev1i+RyICoPEWcAstZsj03r533uMXtDn506l6/wlsRYiS5XBdx7TpccCsyUg== dependencies: cosmiconfig "^7.0.0" klona "^2.0.5" - semver "^7.3.5" + semver "^7.3.7" postcss-merge-idents@^5.1.1: version "5.1.1" @@ -11842,18 +12192,18 @@ postcss-merge-idents@^5.1.1: cssnano-utils "^3.1.0" postcss-value-parser "^4.2.0" -postcss-merge-longhand@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.1.3.tgz#a49e2be6237316e3b55e329e0a8da15d1f9f47ab" - integrity sha512-lX8GPGvZ0iGP/IboM7HXH5JwkXvXod1Rr8H8ixwiA372hArk0zP4ZcCy4z4Prg/bfNlbbTf0KCOjCF9kKnpP/w== +postcss-merge-longhand@^5.1.5: + version "5.1.5" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.1.5.tgz#b0e03bee3b964336f5f33c4fc8eacae608e91c05" + integrity sha512-NOG1grw9wIO+60arKa2YYsrbgvP6tp+jqc7+ZD5/MalIw234ooH2C6KlR6FEn4yle7GqZoBxSK1mLBE9KPur6w== dependencies: postcss-value-parser "^4.2.0" stylehacks "^5.1.0" -postcss-merge-rules@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.1.tgz#d327b221cd07540bcc8d9ff84446d8b404d00162" - integrity sha512-8wv8q2cXjEuCcgpIB1Xx1pIy8/rhMPIQqYKNzEdyx37m6gpq83mQQdCxgIkFgliyEnKvdwJf/C61vN4tQDq4Ww== +postcss-merge-rules@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.2.tgz#7049a14d4211045412116d79b751def4484473a5" + integrity sha512-zKMUlnw+zYCWoPN6yhPjtcEdlJaMUZ0WyVcxTAmw3lkkN/NDMRkOkiuctQEoWAOvH7twaxUUdvBWl0d4+hifRQ== dependencies: browserslist "^4.16.6" caniuse-api "^3.0.0" @@ -11876,19 +12226,19 @@ postcss-minify-gradients@^5.1.1: cssnano-utils "^3.1.0" postcss-value-parser "^4.2.0" -postcss-minify-params@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.1.2.tgz#77e250780c64198289c954884ebe3ee4481c3b1c" - integrity sha512-aEP+p71S/urY48HWaRHasyx4WHQJyOYaKpQ6eXl8k0kxg66Wt/30VR6/woh8THgcpRbonJD5IeD+CzNhPi1L8g== +postcss-minify-params@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.1.3.tgz#ac41a6465be2db735099bbd1798d85079a6dc1f9" + integrity sha512-bkzpWcjykkqIujNL+EVEPOlLYi/eZ050oImVtHU7b4lFS82jPnsCb44gvC6pxaNt38Els3jWYDHTjHKf0koTgg== dependencies: browserslist "^4.16.6" cssnano-utils "^3.1.0" postcss-value-parser "^4.2.0" -postcss-minify-selectors@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.2.0.tgz#17c2be233e12b28ffa8a421a02fc8b839825536c" - integrity sha512-vYxvHkW+iULstA+ctVNx0VoRAR4THQQRkG77o0oa4/mBS0OzGvvzLIvHDv/nNEM0crzN2WIyFU5X7wZhaUK3RA== +postcss-minify-selectors@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz#d4e7e6b46147b8117ea9325a915a801d5fe656c6" + integrity sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg== dependencies: postcss-selector-parser "^6.0.5" @@ -12014,9 +12364,9 @@ postcss-reduce-transforms@^5.1.0: postcss-value-parser "^4.2.0" postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: - version "6.0.9" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f" - integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ== + version "6.0.10" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d" + integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" @@ -12053,12 +12403,12 @@ postcss-zindex@^5.1.0: resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-5.1.0.tgz#4a5c7e5ff1050bd4c01d95b1847dfdcc58a496ff" integrity sha512-fgFMf0OtVSBR1va1JNHYgMxYk73yhn/qb4uQDq1DLGYolz8gHCyr/sesEuGUaYs58E3ZJRcpoGuPVoB7Meiq9A== -postcss@^8.3.11, postcss@^8.3.5, postcss@^8.4.12, postcss@^8.4.7: - version "8.4.12" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.12.tgz#1e7de78733b28970fa4743f7da6f3763648b1905" - integrity sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg== +postcss@^8.3.11, postcss@^8.4.13, postcss@^8.4.14, postcss@^8.4.7: + version "8.4.14" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf" + integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig== dependencies: - nanoid "^3.3.1" + nanoid "^3.3.4" picocolors "^1.0.0" source-map-js "^1.0.2" @@ -12077,7 +12427,12 @@ prepend-http@^2.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= -prettier@*, prettier@2.5.1: +prettier@*: + version "2.6.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032" + integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== + +prettier@2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a" integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg== @@ -12095,7 +12450,17 @@ pretty-error@^4.0.0: lodash "^4.17.20" renderkid "^3.0.0" -pretty-format@*, pretty-format@^27.0.0, pretty-format@^27.2.2, pretty-format@^27.3.1, pretty-format@^27.5.1: +pretty-format@*, pretty-format@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-28.1.0.tgz#8f5836c6a0dfdb834730577ec18029052191af55" + integrity sha512-79Z4wWOYCdvQkEoEuSlBhHJqWeZ8D8YRPiPctJFCtvuaClGpiwiQYSCUOE6IEKUbbFukKOTFIUAXE8N4EQTo1Q== + dependencies: + "@jest/schemas" "^28.0.2" + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^18.0.0" + +pretty-format@^27.0.0, pretty-format@^27.2.2, pretty-format@^27.3.1, pretty-format@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== @@ -12109,15 +12474,15 @@ pretty-time@^1.1.0: resolved "https://registry.yarnpkg.com/pretty-time/-/pretty-time-1.1.0.tgz#ffb7429afabb8535c346a34e41873adf3d74dd0e" integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA== -prism-react-renderer@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.3.1.tgz#88fc9d0df6bed06ca2b9097421349f8c2f24e30d" - integrity sha512-xUeDMEz074d0zc5y6rxiMp/dlC7C+5IDDlaEUlcBOFE2wddz7hz5PNupb087mPwTt7T9BrFmewObfCBuf/LKwQ== +prism-react-renderer@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.3.3.tgz#9b5a4211a6756eee3c96fee9a05733abc0b0805c" + integrity sha512-Viur/7tBTCH2HmYzwCHmt2rEFn+rdIWNIINXyg0StiISbDiIhHKhrFuEK8eMkKgvsIYSjgGqy/hNyucHp6FpoQ== -prismjs@^1.27.0: - version "1.27.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057" - integrity sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA== +prismjs@^1.28.0: + version "1.28.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.28.0.tgz#0d8f561fa0f7cf6ebca901747828b149147044b6" + integrity sha512-8aaXdYvl1F7iC7Xm1spqSaY/OJBpYW3v+KJ+F17iYxvdc8sfjW194COK5wVhMZX45tGteiBQgdvD/nhxcRwylw== process-nextick-args@~2.0.0: version "2.0.1" @@ -12185,7 +12550,7 @@ protocols@^1.1.0, protocols@^1.4.0: resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.8.tgz#48eea2d8f58d9644a4a32caae5d5db290a075ce8" integrity sha512-IgjKyaUSjsROSO8/D49Ab7hP8mJgTYcqApOqdPhLoPxAplXmkp+zRvsrSQjFn5by0rhm4VH0GAUELIPpx7B1yg== -proxy-addr@~2.0.5: +proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== @@ -12238,22 +12603,17 @@ q@^1.5.1: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== - -qs@^6.9.4: - version "6.10.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.1.tgz#4931482fa8d647a5aab799c5271d2133b981fb6a" - integrity sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg== +qs@6.10.3, qs@^6.9.4: + version "6.10.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" + integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== dependencies: side-channel "^1.0.4" qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== query-string@^6.13.8: version "6.14.1" @@ -12288,9 +12648,9 @@ quick-lru@^4.0.1: integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== ramda@~0.27.1: - version "0.27.1" - resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.1.tgz#66fc2df3ef873874ffc2da6aa8984658abacf5c9" - integrity sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw== + version "0.27.2" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.2.tgz#84463226f7f36dc33592f6f4ed6374c48306c3f1" + integrity sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA== randombytes@^2.1.0: version "2.1.0" @@ -12309,13 +12669,13 @@ range-parser@^1.2.1, range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== +raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== dependencies: - bytes "3.1.0" - http-errors "1.7.2" + bytes "3.1.2" + http-errors "2.0.0" iconv-lite "0.4.24" unpipe "1.0.0" @@ -12339,10 +12699,10 @@ react-base16-styling@^0.6.0: lodash.flow "^3.3.0" pure-color "^1.2.0" -react-dev-utils@^12.0.0: - version "12.0.0" - resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.0.tgz#4eab12cdb95692a077616770b5988f0adf806526" - integrity sha512-xBQkitdxozPxt1YZ9O1097EJiVpwHr9FoAuEVURCKV0Av8NBERovJauzP7bo1ThvuhZ4shsQ1AJiu4vQpoT1AQ== +react-dev-utils@^12.0.1: + version "12.0.1" + resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.1.tgz#ba92edb4a1f379bd46ccd6bcd4e7bc398df33e73" + integrity sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ== dependencies: "@babel/code-frame" "^7.16.0" address "^1.1.2" @@ -12363,7 +12723,7 @@ react-dev-utils@^12.0.0: open "^8.4.0" pkg-up "^3.1.0" prompts "^2.4.2" - react-error-overlay "^6.0.10" + react-error-overlay "^6.0.11" recursive-readdir "^2.2.2" shell-quote "^1.7.3" strip-ansi "^6.0.1" @@ -12377,20 +12737,20 @@ react-dom@^18.1.0: loose-envify "^1.1.0" scheduler "^0.22.0" -react-error-overlay@^6.0.10: - version "6.0.10" - resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.10.tgz#0fe26db4fa85d9dbb8624729580e90e7159a59a6" - integrity sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA== +react-error-overlay@^6.0.11: + version "6.0.11" + resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb" + integrity sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg== react-fast-compare@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== -react-helmet-async@*, react-helmet-async@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-1.2.3.tgz#57326a69304ea3293036eafb49475e9ba454cb37" - integrity sha512-mCk2silF53Tq/YaYdkl2sB+/tDoPnaxN7dFS/6ZLJb/rhUY2EWGI5Xj2b4jHppScMqY45MbgPSwTxDchKpZ5Kw== +react-helmet-async@*, react-helmet-async@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-1.3.0.tgz#7bd5bf8c5c69ea9f02f6083f14ce33ef545c222e" + integrity sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg== dependencies: "@babel/runtime" "^7.12.5" invariant "^2.2.4" @@ -12408,6 +12768,11 @@ react-is@^17.0.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== +react-is@^18.0.0: + version "18.1.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.1.0.tgz#61aaed3096d30eacf2a2127118b5b41387d32a67" + integrity sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg== + react-json-view@^1.21.3: version "1.21.3" resolved "https://registry.yarnpkg.com/react-json-view/-/react-json-view-1.21.3.tgz#f184209ee8f1bf374fb0c41b0813cff54549c475" @@ -12437,23 +12802,23 @@ react-router-config@^5.1.1: dependencies: "@babel/runtime" "^7.1.2" -react-router-dom@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.0.tgz#da1bfb535a0e89a712a93b97dd76f47ad1f32363" - integrity sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ== +react-router-dom@^5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.3.tgz#8779fc28e6691d07afcaf98406d3812fe6f11199" + integrity sha512-Ov0tGPMBgqmbu5CDmN++tv2HQ9HlWDuWIIqn4b88gjlAN5IHI+4ZUZRcpz9Hl0azFIwihbLDYw1OiHGRo7ZIng== dependencies: "@babel/runtime" "^7.12.13" history "^4.9.0" loose-envify "^1.3.1" prop-types "^15.6.2" - react-router "5.2.1" + react-router "5.3.3" tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-router@5.2.1, react-router@^5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.1.tgz#4d2e4e9d5ae9425091845b8dbc6d9d276239774d" - integrity sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ== +react-router@5.3.3, react-router@^5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.3.3.tgz#8e3841f4089e728cf82a429d92cdcaa5e4a3a288" + integrity sha512-mzQGUvS3bM84TnbtMYR8ZjKnuPJ71IjSzR+DE6UkUqvN4czWIqEs17yLL8xkAycv4ev0AiN+IGrWu88vJs/p2w== dependencies: "@babel/runtime" "^7.12.13" history "^4.9.0" @@ -12467,13 +12832,13 @@ react-router@5.2.1, react-router@^5.2.0: tiny-warning "^1.0.0" react-textarea-autosize@^8.3.2: - version "8.3.3" - resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz#f70913945369da453fd554c168f6baacd1fa04d8" - integrity sha512-2XlHXK2TDxS6vbQaoPbMOfQ8GK7+irc2fVK6QFIcC8GOnH3zI/v481n+j1L0WaPVvKxwesnY93fEfH++sus2rQ== + version "8.3.4" + resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.4.tgz#270a343de7ad350534141b02c9cb78903e553524" + integrity sha512-CdtmP8Dc19xL8/R6sWvtknD/eCXkQr30dtvC4VmGInhRsfF8X/ihXCq6+9l9qbxmKRiq407/7z5fxE7cVWQNgQ== dependencies: "@babel/runtime" "^7.10.2" - use-composed-ref "^1.0.0" - use-latest "^1.0.0" + use-composed-ref "^1.3.0" + use-latest "^1.2.1" react@^18.0.0: version "18.1.0" @@ -12516,9 +12881,9 @@ read-package-json@^3.0.0: npm-normalize-package-bin "^1.0.0" read-package-json@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-4.1.1.tgz#153be72fce801578c1c86b8ef2b21188df1b9eea" - integrity sha512-P82sbZJ3ldDrWCOSKxJT0r/CXMWR0OR3KRh55SgKo3p91GSIEEC32v3lSHAvO/UcH3/IoL7uqhOFBduAnwdldw== + version "4.1.2" + resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-4.1.2.tgz#b444d047de7c75d4a160cb056d00c0693c1df703" + integrity sha512-Dqer4pqzamDE2O4M55xp1qZMuLPqi4ldk2ya648FOMHRjwMzFhuxVrG04wd0c38IsvkVdr3vgHI6z+QTPdAjrQ== dependencies: glob "^7.1.1" json-parse-even-better-errors "^2.3.0" @@ -12660,20 +13025,21 @@ regenerator-runtime@^0.13.4: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== -regenerator-transform@^0.14.2: - version "0.14.5" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" - integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== +regenerator-transform@^0.15.0: + version "0.15.0" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.0.tgz#cbd9ead5d77fae1a48d957cf889ad0586adb6537" + integrity sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg== dependencies: "@babel/runtime" "^7.8.4" -regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26" - integrity sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA== +regexp.prototype.flags@^1.4.1, regexp.prototype.flags@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" + integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== dependencies: call-bind "^1.0.2" define-properties "^1.1.3" + functions-have-names "^1.2.2" regexpp@^3.2.0: version "3.2.0" @@ -12749,7 +13115,7 @@ remark-docusaurus-tabs@^0.2.0: mdast-util-to-string "^2.0.0" unist-util-visit "^2.0.3" -remark-emoji@^2.1.0: +remark-emoji@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/remark-emoji/-/remark-emoji-2.2.0.tgz#1c702090a1525da5b80e15a8f963ef2c8236cac7" integrity sha512-P3cj9s5ggsUvWw5fS2uzCHJMGuXYRb0NnZqYlNecewXt8QBU9n5vW3DUUKOhepS8F9CwdMx9B8a3i7pqFWAI5w== @@ -13012,9 +13378,9 @@ rimraf@^2.6.3: glob "^7.1.3" rollup@^2.59.0: - version "2.72.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.72.1.tgz#861c94790537b10008f0ca0fbc60e631aabdd045" - integrity sha512-NTc5UGy/NWFGpSqF1lFY8z9Adri6uhyMLI6LvPAXdBKoPRFhIIiBUpt+Qg2awixqO3xvzSijjhnb4+QEZwJmxA== + version "2.75.4" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.75.4.tgz#c3518c326c98e508b628a93015a03a276c331f22" + integrity sha512-JgZiJMJkKImMZJ8ZY1zU80Z2bA/TvrL/7D9qcBCrfl2bP+HUaIw0QHUroB4E3gBpFl6CRFM1YxGbuYGtdAswbQ== optionalDependencies: fsevents "~2.3.2" @@ -13074,7 +13440,7 @@ rxjs@^6.4.0, rxjs@^6.5.4, rxjs@^6.6.0: dependencies: tslib "^1.9.0" -rxjs@^7.4.0, rxjs@^7.5.2, rxjs@^7.5.4: +rxjs@^7.5.1, rxjs@^7.5.4, rxjs@^7.5.5: version "7.5.5" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.5.tgz#2ebad89af0f560f460ad5cc4213219e1f7dd4e9f" integrity sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw== @@ -13086,7 +13452,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@^5.2.1, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -13165,12 +13531,12 @@ select-hose@^2.0.0: resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= -selfsigned@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.0.0.tgz#e927cd5377cbb0a1075302cff8df1042cc2bce5b" - integrity sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ== +selfsigned@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.0.1.tgz#8b2df7fa56bf014d19b6007655fff209c0ef0a56" + integrity sha512-LmME957M1zOsUhG+67rAjKfiWFox3SBxE/yymatMZsAx+oMrJ0YQ8AToOnyCm7xbeg2ep37IHLxdu0o2MavQOQ== dependencies: - node-forge "^1.2.0" + node-forge "^1" semver-diff@^3.1.1: version "3.1.1" @@ -13196,7 +13562,7 @@ semver@7.3.4: dependencies: lru-cache "^6.0.0" -semver@7.3.7, semver@^7.1.1, semver@^7.1.3, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@~7.3.0: +semver@7.3.7, semver@^7.1.1, semver@^7.1.3, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@~7.3.0: version "7.3.7" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== @@ -13208,24 +13574,24 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== dependencies: debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" + depd "2.0.0" + destroy "1.2.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" fresh "0.5.2" - http-errors "~1.7.2" + http-errors "2.0.0" mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" + ms "2.1.3" + on-finished "2.4.1" range-parser "~1.2.1" - statuses "~1.5.0" + statuses "2.0.1" serialize-javascript@^6.0.0: version "6.0.0" @@ -13261,15 +13627,15 @@ serve-index@^1.9.1: mime-types "~2.1.17" parseurl "~1.3.2" -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" parseurl "~1.3.3" - send "0.17.1" + send "0.18.0" set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" @@ -13286,10 +13652,10 @@ setprototypeof@1.1.0: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== shallow-clone@^3.0.0: version "3.0.1" @@ -13338,18 +13704,18 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" -signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: - version "3.0.5" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.5.tgz#9e3e8cc0c75a99472b44321033a7702e7738252f" - integrity sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ== +signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== sirv@^1.0.7: - version "1.0.18" - resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.18.tgz#105fab52fb656ce8a2bebbf36b11052005952899" - integrity sha512-f2AOPogZmXgJ9Ma2M22ZEhc1dNtRIzcEkiflMFeVTRq+OViOZMvH1IPMVOwrKaxpSaHioBJiDR0SluRqGa7atA== + version "1.0.19" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49" + integrity sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ== dependencies: "@polka/url" "^1.0.0-next.20" - mime "^2.3.1" + mrmime "^1.0.0" totalist "^1.0.0" sisteransi@^1.0.5: @@ -13398,18 +13764,18 @@ slide@^1.1.6: resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" integrity sha1-VusCfWW00tzmyy4tMsTUr8nh1wc= -smart-buffer@^4.1.0: +smart-buffer@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== -sockjs@^0.3.21: - version "0.3.21" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.21.tgz#b34ffb98e796930b60a0cfa11904d6a339a7d417" - integrity sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw== +sockjs@^0.3.24: + version "0.3.24" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" + integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== dependencies: faye-websocket "^0.11.3" - uuid "^3.4.0" + uuid "^8.3.2" websocket-driver "^0.7.4" socks-proxy-agent@^5.0.0: @@ -13422,21 +13788,21 @@ socks-proxy-agent@^5.0.0: socks "^2.3.3" socks-proxy-agent@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.1.0.tgz#869cf2d7bd10fea96c7ad3111e81726855e285c3" - integrity sha512-57e7lwCN4Tzt3mXz25VxOErJKXlPfXmkMLnk310v/jwW20jWRVcgsOit+xNkN3eIEdB47GwnfAEBLacZ/wVIKg== + version "6.2.1" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz#2687a31f9d7185e38d530bef1944fe1f1496d6ce" + integrity sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ== dependencies: agent-base "^6.0.2" - debug "^4.3.1" - socks "^2.6.1" + debug "^4.3.3" + socks "^2.6.2" -socks@^2.3.3, socks@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.1.tgz#989e6534a07cf337deb1b1c94aaa44296520d30e" - integrity sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA== +socks@^2.3.3, socks@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.2.tgz#ec042d7960073d40d94268ff3bb727dc685f111a" + integrity sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA== dependencies: ip "^1.1.5" - smart-buffer "^4.1.0" + smart-buffer "^4.2.0" sort-css-media-queries@2.0.4: version "2.0.4" @@ -13485,12 +13851,12 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@^0.7.3, source-map@~0.7.2: +source-map@^0.7.3: version "0.7.3" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== -sourcemap-codec@^1.4.4: +sourcemap-codec@^1.4.8: version "1.4.8" resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== @@ -13522,9 +13888,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.10" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz#0d9becccde7003d6c658d487dd48a32f0bf3014b" - integrity sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA== + version "3.0.11" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95" + integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== spdy-transport@^3.0.0: version "3.0.0" @@ -13574,9 +13940,9 @@ sprintf-js@~1.0.2: integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sshpk@^1.14.1, sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -13612,15 +13978,20 @@ state-toggle@^1.0.0: resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe" integrity sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ== -"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +"statuses@>= 1.4.0 < 2": version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= std-env@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.0.1.tgz#bc4cbc0e438610197e34c2d79c3df30b491f5182" - integrity sha512-mC1Ps9l77/97qeOZc+HrOL7TIaOboHqMZ24dGVQrlxFcpPpfCHpH+qfUT7Dz+6mlG8+JPA1KfBQo19iC/+Ngcw== + version "3.1.1" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.1.1.tgz#1f19c4d3f6278c52efd08a94574a2a8d32b7d092" + integrity sha512-/c645XdExBypL01TpFKiG/3RAa/Qmu+zRi0MwAmrdEkwHNuN0ebo8ccAXBBDa5Z0QOJgBskUIbuCK91x0sCVEw== strict-uri-encode@^2.0.0: version "2.0.0" @@ -13649,15 +14020,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2: +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -13666,6 +14029,14 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2 is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string-width@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + string-width@^5.0.0, string-width@^5.0.1: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -13675,35 +14046,37 @@ string-width@^5.0.0, string-width@^5.0.1: emoji-regex "^9.2.2" strip-ansi "^7.0.1" -string.prototype.matchall@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz#5abb5dabc94c7b0ea2380f65ba610b3a544b15fa" - integrity sha512-6WgDX8HmQqvEd7J+G6VtAahhsQIssiZ8zl7zKh1VDMFyL3hRTJP4FTNA3RbIp2TOQ9AYNDcc7e3fH0Qbup+DBg== +string.prototype.matchall@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz#8e6ecb0d8a1fb1fda470d81acecb2dba057a481d" + integrity sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg== dependencies: call-bind "^1.0.2" define-properties "^1.1.3" es-abstract "^1.19.1" get-intrinsic "^1.1.1" - has-symbols "^1.0.2" + has-symbols "^1.0.3" internal-slot "^1.0.3" - regexp.prototype.flags "^1.3.1" + regexp.prototype.flags "^1.4.1" side-channel "^1.0.4" -string.prototype.trimend@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" - integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== +string.prototype.trimend@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" + integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" + define-properties "^1.1.4" + es-abstract "^1.19.5" -string.prototype.trimstart@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" - integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== +string.prototype.trimstart@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" + integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" + define-properties "^1.1.4" + es-abstract "^1.19.5" string_decoder@^1.1.1: version "1.3.0" @@ -13756,7 +14129,7 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-ansi@^7.0.0, strip-ansi@^7.0.1: +strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== @@ -13850,10 +14223,10 @@ supports-color@^8.0.0, supports-color@^8.1.1: dependencies: has-flag "^4.0.0" -supports-color@^9.2.1: - version "9.2.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.2.1.tgz#599dc9d45acf74c6176e0d880bab1d7d718fe891" - integrity sha512-Obv7ycoCTG51N7y175StI9BlAXrmgZrFhZOb0/PyjHBher/NmsdBgbbQ1Inhq+gIhz6+7Gb+jWF2Vqi7Mf1xnQ== +supports-color@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.2.2.tgz#502acaf82f2b7ee78eb7c83dcac0f89694e5a7bb" + integrity sha512-XC6g/Kgux+rJXmwokjm9ECpD6k/smUoS5LKlUCcsYr4IY3rW0XyAympon2RmxGrlnZURMpg5T18gWDP9CsHXFA== supports-hyperlinks@^2.0.0: version "2.2.0" @@ -13962,13 +14335,13 @@ terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.3.1: terser "^5.7.2" terser@^5.10.0, terser@^5.7.2: - version "5.12.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.12.1.tgz#4cf2ebed1f5bceef5c83b9f60104ac4a78b49e9c" - integrity sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ== + version "5.14.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.14.0.tgz#eefeec9af5153f55798180ee2617f390bdd285e2" + integrity sha512-JC6qfIEkPBd9j1SMO3Pfn+A6w2kQV54tv+ABQLgZr7dA3k/DL/OBoYSWxzVpZev3J+bUHXfr55L8Mox7AaNo6g== dependencies: + "@jridgewell/source-map" "^0.3.2" acorn "^8.5.0" commander "^2.20.0" - source-map "~0.7.2" source-map-support "~0.5.20" test-exclude@^6.0.0: @@ -14025,7 +14398,7 @@ thunky@^1.0.2: resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== -timsort@^0.3.0, timsort@~0.3.0: +timsort@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= @@ -14061,7 +14434,7 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" -tmpl@1.0.x: +tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== @@ -14083,10 +14456,10 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== totalist@^1.0.0: version "1.1.0" @@ -14142,17 +14515,12 @@ trough@^1.0.0: resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== -ts-essentials@^2.0.3: - version "2.0.12" - resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-2.0.12.tgz#c9303f3d74f75fa7528c3d49b80e089ab09d8745" - integrity sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w== - -ts-node@^10.4.0: - version "10.7.0" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.7.0.tgz#35d503d0fab3e2baa672a0e94f4b40653c2463f5" - integrity sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A== +ts-node@^10.4.0, ts-node@^10.8.0: + version "10.8.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.8.0.tgz#3ceb5ac3e67ae8025c1950626aafbdecb55d82ce" + integrity sha512-/fNd5Qh+zTt8Vt1KbYZjRHCE9sI5i7nqfD/dzBBRDeVXZXS6kToW6R7tTU6Nd4XavFs0mAVCg29Q//ML7WsZYA== dependencies: - "@cspotcode/source-map-support" "0.7.0" + "@cspotcode/source-map-support" "^0.8.0" "@tsconfig/node10" "^1.0.7" "@tsconfig/node12" "^1.0.7" "@tsconfig/node14" "^1.0.0" @@ -14163,7 +14531,7 @@ ts-node@^10.4.0: create-require "^1.1.0" diff "^4.0.1" make-error "^1.1.1" - v8-compile-cache-lib "^3.0.0" + v8-compile-cache-lib "^3.0.1" yn "3.1.1" tsconfig-paths@^3.14.1, tsconfig-paths@^3.9.0: @@ -14181,10 +14549,10 @@ tslib@^1.10.0, tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.0, tslib@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== +tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== tslint@^6.1.3: version "6.1.3" @@ -14281,11 +14649,11 @@ type-fest@^0.8.1: integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== type-fest@^2.5.0: - version "2.12.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.12.1.tgz#d2be8f50bf5f8f0a5fd916d29bf3e98c17e960be" - integrity sha512-AiknQSEqKVGDDjtZqeKrUoTlcj7FKhupmnVUgz6KoOKtvMwRGE6hUNJ/nVear+h7fnUPO1q/htSkYKb1pyntkQ== + version "2.13.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.13.0.tgz#d1ecee38af29eb2e863b22299a3d68ef30d2abfb" + integrity sha512-lPfAm42MxE4/456+QyIaaVBAwgpJb6xZ8PRu09utnhPdWwcyj9vgy6Sq0Z5yNbJ21EdxB5dRU/Qg8bsyAMtlcw== -type-is@~1.6.17, type-is@~1.6.18: +type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== @@ -14305,7 +14673,7 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@*, typescript@4.6.2, "typescript@>=3.3.1 <4.7.0", typescript@^4.4.3, typescript@^4.5.3, typescript@^4.5.5, typescript@~4.6.3: +typescript@*, typescript@4.6.2, "typescript@>=3.3.1 <4.7.0", typescript@^4.4.3, typescript@^4.5.5, typescript@^4.6.4, typescript@~4.6.3: version "4.6.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4" integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg== @@ -14321,9 +14689,9 @@ uc.micro@^1.0.1, uc.micro@^1.0.5: integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== uglify-js@^3.1.4: - version "3.14.2" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.14.2.tgz#d7dd6a46ca57214f54a2d0a43cad0f35db82ac99" - integrity sha512-rtPMlmcO4agTUfz10CbgJ1k6UAoXM2gWb3GoMPPZB/+/Ackf8lNWk11K4rYi2D0apgoFRLtQOZhb+/iGNJq26A== + version "3.15.5" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.15.5.tgz#2b10f9e0bfb3f5c15a8e8404393b6361eaeb33b3" + integrity sha512-hNM5q5GbBRB5xB+PMqVRcgYe4c8jbyZ1pzZhS6jbq54/4F2gFK869ZheiE5A8/t+W5jtTNpWef/5Q9zk639FNQ== uid-number@0.0.6: version "0.0.6" @@ -14335,14 +14703,14 @@ umask@^1.1.0: resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d" integrity sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0= -unbox-primitive@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" - integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== dependencies: - function-bind "^1.1.1" - has-bigints "^1.0.1" - has-symbols "^1.0.2" + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" unherit@^1.0.4: @@ -14469,7 +14837,7 @@ unist-util-visit-parents@^3.0.0: "@types/unist" "^2.0.0" unist-util-is "^4.0.0" -unist-util-visit@2.0.3, unist-util-visit@^2.0.0, unist-util-visit@^2.0.1, unist-util-visit@^2.0.2, unist-util-visit@^2.0.3: +unist-util-visit@2.0.3, unist-util-visit@^2.0.0, unist-util-visit@^2.0.1, unist-util-visit@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" integrity sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q== @@ -14559,24 +14927,22 @@ url@^0.11.0: punycode "1.3.2" querystring "0.2.0" -use-composed-ref@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/use-composed-ref/-/use-composed-ref-1.1.0.tgz#9220e4e94a97b7b02d7d27eaeab0b37034438bbc" - integrity sha512-my1lNHGWsSDAhhVAT4MKs6IjBUtG6ZG11uUqexPH9PptiIZDQOzaF4f5tEbJ2+7qvNbtXNBbU3SfmN+fXlWDhg== - dependencies: - ts-essentials "^2.0.3" +use-composed-ref@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/use-composed-ref/-/use-composed-ref-1.3.0.tgz#3d8104db34b7b264030a9d916c5e94fbe280dbda" + integrity sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ== -use-isomorphic-layout-effect@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz#7bb6589170cd2987a152042f9084f9effb75c225" - integrity sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ== +use-isomorphic-layout-effect@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb" + integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA== -use-latest@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/use-latest/-/use-latest-1.2.0.tgz#a44f6572b8288e0972ec411bdd0840ada366f232" - integrity sha512-d2TEuG6nSLKQLAfW3By8mKr8HurOlTkul0sOpxbClIv4SQ4iOd7BYr7VIzdbktUCnv7dua/60xzd8igMU6jmyw== +use-latest@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/use-latest/-/use-latest-1.2.1.tgz#d13dfb4b08c28e3e33991546a2cee53e14038cf2" + integrity sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw== dependencies: - use-isomorphic-layout-effect "^1.0.0" + use-isomorphic-layout-effect "^1.1.1" util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" @@ -14605,7 +14971,7 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= -uuid@^3.3.2, uuid@^3.4.0: +uuid@^3.3.2: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== @@ -14615,10 +14981,10 @@ uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== -v8-compile-cache-lib@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz#0582bcb1c74f3a2ee46487ceecf372e46bce53e8" - integrity sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA== +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== v8-compile-cache@2.3.0, v8-compile-cache@^2.0.3: version "2.3.0" @@ -14626,9 +14992,9 @@ v8-compile-cache@2.3.0, v8-compile-cache@^2.0.3: integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== v8-to-istanbul@^8.0.0, v8-to-istanbul@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.0.tgz#0aeb763894f1a0a1676adf8a8b7612a38902446c" - integrity sha512-/PRhfd8aTNp9Ggr62HPzXg2XasNFGy5PBt0Rp04du7/8GNNSgxFL6WBTkgMKSL9bFjH+8kKEG3f37FmxiTqUUA== + version "8.1.1" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed" + integrity sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w== dependencies: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" @@ -14696,10 +15062,15 @@ vfile@^4.0.0: unist-util-stringify-position "^2.0.0" vfile-message "^2.0.0" -vscode-uri@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.2.tgz#ecfd1d066cb8ef4c3a208decdbab9a8c23d055d0" - integrity sha512-jkjy6pjU1fxUvI51P+gCsxg1u2n8LSt0W6KrCNQceaziKzff74GoWmjVG46KieVzybO1sttPQmYfrwSHey7GUA== +vscode-languageserver-textdocument@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.5.tgz#838769940ece626176ec5d5a2aa2d0aa69f5095c" + integrity sha512-1ah7zyQjKBudnMiHbZmxz5bYNM9KKZYz+5VQLj+yr8l+9w3g+WAhCkUkWbhMEdC5u0ub4Ndiye/fDyS8ghIKQg== + +vscode-uri@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.3.tgz#a95c1ce2e6f41b7549f86279d19f47951e4f4d84" + integrity sha512-EcswR2S8bpR7fD0YPeS7r2xXExrScVMxg4MedACaWHEtx9ftCF/qHG1xGkolzTPcEmjTavCQgbVzHUIdTMzFGA== w3c-hr-time@^1.0.2: version "1.0.2" @@ -14727,11 +15098,11 @@ wait-on@^6.0.1: rxjs "^7.5.4" walker@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" - integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== dependencies: - makeerror "1.0.x" + makeerror "1.0.12" watchpack@^2.3.1: version "2.3.1" @@ -14791,49 +15162,47 @@ webpack-bundle-analyzer@^4.5.0: ws "^7.3.1" webpack-dev-middleware@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz#aa079a8dedd7e58bfeab358a9af7dab304cee57f" - integrity sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg== + version "5.3.3" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz#efae67c2793908e7311f1d9b06f2a08dcc97e51f" + integrity sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA== dependencies: colorette "^2.0.10" - memfs "^3.4.1" + memfs "^3.4.3" mime-types "^2.1.31" range-parser "^1.2.1" schema-utils "^4.0.0" -webpack-dev-server@^4.7.4: - version "4.7.4" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz#d0ef7da78224578384e795ac228d8efb63d5f945" - integrity sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A== +webpack-dev-server@^4.9.0: + version "4.9.1" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.9.1.tgz#184607b0287c791aeaa45e58e8fe75fcb4d7e2a8" + integrity sha512-CTMfu2UMdR/4OOZVHRpdy84pNopOuigVIsRbGX3LVDMWNP8EUgC5mUBMErbwBlHTEX99ejZJpVqrir6EXAEajA== dependencies: "@types/bonjour" "^3.5.9" "@types/connect-history-api-fallback" "^1.3.5" "@types/express" "^4.17.13" "@types/serve-index" "^1.9.1" "@types/sockjs" "^0.3.33" - "@types/ws" "^8.2.2" + "@types/ws" "^8.5.1" ansi-html-community "^0.0.8" - bonjour "^3.5.0" + bonjour-service "^1.0.11" chokidar "^3.5.3" colorette "^2.0.10" compression "^1.7.4" connect-history-api-fallback "^1.6.0" default-gateway "^6.0.3" - del "^6.0.0" - express "^4.17.1" + express "^4.17.3" graceful-fs "^4.2.6" html-entities "^2.3.2" - http-proxy-middleware "^2.0.0" + http-proxy-middleware "^2.0.3" ipaddr.js "^2.0.1" open "^8.0.9" p-retry "^4.5.0" - portfinder "^1.0.28" + rimraf "^3.0.2" schema-utils "^4.0.0" - selfsigned "^2.0.0" + selfsigned "^2.0.1" serve-index "^1.9.1" - sockjs "^0.3.21" + sockjs "^0.3.24" spdy "^4.0.2" - strip-ansi "^7.0.0" webpack-dev-middleware "^5.3.1" ws "^8.4.2" @@ -14858,10 +15227,10 @@ webpack-sources@^3.2.3: resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@^5.70.0, webpack@^5.71.0: - version "5.71.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.71.0.tgz#b01fcf379570b8c5ee06ca06c829ca168c951884" - integrity sha512-g4dFT7CFG8LY0iU5G8nBL6VlkT21Z7dcYDpJAEJV5Q1WLb9UwnFbrem1k7K52ILqEmomN7pnzWFxxE6SlDY56A== +webpack@^5.71.0, webpack@^5.72.1: + version "5.72.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.72.1.tgz#3500fc834b4e9ba573b9f430b2c0a61e1bb57d13" + integrity sha512-dXG5zXCLspQR4krZVR6QgajnZOjW2K/djHvdcRaDQvsjV9z9vaW6+ja5dZOYbqBBjF6kGXka/2ZyxNdc+8Jung== dependencies: "@types/eslint-scope" "^3.7.3" "@types/estree" "^0.0.51" @@ -14872,13 +15241,13 @@ webpack@^5.70.0, webpack@^5.71.0: acorn-import-assertions "^1.7.6" browserslist "^4.14.5" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.9.2" + enhanced-resolve "^5.9.3" es-module-lexer "^0.9.0" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" graceful-fs "^4.2.9" - json-parse-better-errors "^1.0.2" + json-parse-even-better-errors "^2.3.1" loader-runner "^4.2.0" mime-types "^2.1.27" neo-async "^2.6.2" @@ -14972,11 +15341,11 @@ which@^2.0.1, which@^2.0.2: isexe "^2.0.0" wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== dependencies: - string-width "^1.0.2 || 2" + string-width "^1.0.2 || 2 || 3 || 4" widest-line@^3.1.0: version "3.1.0" @@ -15058,6 +15427,14 @@ write-file-atomic@^3.0.0, write-file-atomic@^3.0.3: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" +write-file-atomic@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.1.tgz#9faa33a964c1c85ff6f849b80b42a88c2c537c8f" + integrity sha512-nSKUxgAbyioruk6hU87QzVbY279oYT6uiwgDoujth2ju4mJ+TZau7SQBhtbTmUyuNYTuXnSyRn66FV0+eCgcrQ== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^3.0.7" + write-json-file@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-3.2.0.tgz#65bbdc9ecd8a1458e15952770ccbadfcff5fe62a" @@ -15092,14 +15469,14 @@ write-pkg@^4.0.0: write-json-file "^3.2.0" ws@^7.3.1, ws@^7.4.6: - version "7.5.5" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881" - integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w== + version "7.5.8" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.8.tgz#ac2729881ab9e7cbaf8787fe3469a48c5c7f636a" + integrity sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw== ws@^8.4.2: - version "8.5.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" - integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== + version "8.7.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.7.0.tgz#eaf9d874b433aa00c0e0d8752532444875db3957" + integrity sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg== xdg-basedir@^4.0.0: version "4.0.0" @@ -15176,6 +15553,11 @@ yargs-parser@^20.2.2, yargs-parser@^20.2.3: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== +yargs-parser@^21.0.0: + version "21.0.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.1.tgz#0267f286c877a4f0f728fceb6f8a3e4cb95c6e35" + integrity sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg== + yargs@15.4.1, yargs@^15.0.1: version "15.4.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" @@ -15207,17 +15589,17 @@ yargs@^16.2.0: yargs-parser "^20.2.2" yargs@^17.0.0: - version "17.2.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.2.1.tgz#e2c95b9796a0e1f7f3bf4427863b42e0418191ea" - integrity sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q== + version "17.5.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.5.1.tgz#e109900cab6fcb7fd44b1d8249166feb0b36e58e" + integrity sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA== dependencies: cliui "^7.0.2" escalade "^3.1.1" get-caller-file "^2.0.5" require-directory "^2.1.1" - string-width "^4.2.0" + string-width "^4.2.3" y18n "^5.0.5" - yargs-parser "^20.2.2" + yargs-parser "^21.0.0" yauzl@^2.10.0: version "2.10.0" @@ -15238,15 +15620,15 @@ yocto-queue@^0.1.0: integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== z-schema@~5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/z-schema/-/z-schema-5.0.2.tgz#f410394b2c9fcb9edaf6a7511491c0bb4e89a504" - integrity sha512-40TH47ukMHq5HrzkeVE40Ad7eIDKaRV2b+Qpi2prLc9X9eFJFzV7tMe5aH12e6avaSS/u5l653EQOv+J9PirPw== + version "5.0.3" + resolved "https://registry.yarnpkg.com/z-schema/-/z-schema-5.0.3.tgz#68fafb9b735fc7f3c89eabb3e5a6353b4d7b4935" + integrity sha512-sGvEcBOTNum68x9jCpCVGPFJ6mWnkD0YxOcddDlJHRx3tKdB2q8pCHExMVZo/AV/6geuVJXG7hljDaWG8+5GDw== dependencies: lodash.get "^4.4.2" lodash.isequal "^4.5.0" validator "^13.7.0" optionalDependencies: - commander "^2.7.1" + commander "^2.20.3" zwitch@^1.0.0: version "1.0.5" From 871e9cad34f3b690122cadff364f8b6b5cf1d667 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 31 May 2022 21:40:14 -0400 Subject: [PATCH 66/88] Update strict-enums.ts --- packages/eslint-plugin/src/rules/strict-enums.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 3878f285554e..d466ab3dbc17 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -728,8 +728,8 @@ export default util.createRule({ } }, - /** When a function is invoked, or class is instantiated. */ - 'CallExpression, NewExpression'( + /** When a function is invoked or a class is instantiated. */ + 'CallExpression, NewExpression': function callExpressionOrNewExpression( node: TSESTree.CallExpression | TSESTree.NewExpression, ): void { checkCallExpression(node); From cbe9e902051e2fb052d11bdf46d3298d220d1288 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Fri, 25 Nov 2022 03:50:05 -0500 Subject: [PATCH 67/88] Continued fixing merge conflicts --- .../eslint-plugin/src/rules/no-redeclare.ts | 1 + .../sort-type-union-intersection-members.ts | 1 + .../eslint-plugin/src/rules/strict-enums.ts | 9 +- .../src/util/collectUnusedVariables.ts | 5 +- packages/scope-manager/src/ScopeManager.ts | 1 + packages/type-utils/src/isTypeReadonly.ts | 31 +- packages/type-utils/src/typeFlagUtils.ts | 1 + yarn.lock | 677 +++++++++--------- 8 files changed, 354 insertions(+), 372 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-redeclare.ts b/packages/eslint-plugin/src/rules/no-redeclare.ts index c39c5beb97aa..1eb2baa6de8d 100644 --- a/packages/eslint-plugin/src/rules/no-redeclare.ts +++ b/packages/eslint-plugin/src/rules/no-redeclare.ts @@ -1,3 +1,4 @@ +import { ScopeType } from '@typescript-eslint/scope-manager'; import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; diff --git a/packages/eslint-plugin/src/rules/sort-type-union-intersection-members.ts b/packages/eslint-plugin/src/rules/sort-type-union-intersection-members.ts index c18b39537086..1fbf91b9ae89 100644 --- a/packages/eslint-plugin/src/rules/sort-type-union-intersection-members.ts +++ b/packages/eslint-plugin/src/rules/sort-type-union-intersection-members.ts @@ -2,6 +2,7 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as util from '../util'; +import { getEnumNames } from '../util'; enum Group { conditional = 'conditional', diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index d466ab3dbc17..c61f8d4a3a4e 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -1,7 +1,8 @@ -import * as util from '../util'; +import type { TSESTree } from '@typescript-eslint/utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; -import { TSESTree } from '@typescript-eslint/utils'; + +import * as util from '../util'; /** * TypeScript only allows number enums, string enums, or mixed enums with both @@ -48,7 +49,7 @@ export default util.createRule({ meta: { type: 'suggestion', docs: { - description: 'Disallows the usage of unsafe enum patterns', + description: 'Disallow the usage of unsafe enum code patterns', recommended: false, requiresTypeChecking: true, }, @@ -781,7 +782,7 @@ export default util.createRule({ /** * We have to use `leftTSNode.name` instead of `leftTSNode` to avoid * runtime errors because the `typeChecker.getTypeAtLocation` method - * expects a `ts.BindingName` instead of a`ts.VariableDeclaration`. + * expects a `ts.BindingName` instead of a `ts.VariableDeclaration`. * https://github.com/microsoft/TypeScript/issues/48878 */ const leftType = getTypeFromTSNode(leftTSNode.name); diff --git a/packages/eslint-plugin/src/util/collectUnusedVariables.ts b/packages/eslint-plugin/src/util/collectUnusedVariables.ts index abf59a3e260a..5ffe503eb1a1 100644 --- a/packages/eslint-plugin/src/util/collectUnusedVariables.ts +++ b/packages/eslint-plugin/src/util/collectUnusedVariables.ts @@ -1,4 +1,7 @@ -import { ImplicitLibVariable } from '@typescript-eslint/scope-manager'; +import { + ImplicitLibVariable, + ScopeType, +} from '@typescript-eslint/scope-manager'; import { Visitor } from '@typescript-eslint/scope-manager/dist/referencer/Visitor'; import type { TSESTree } from '@typescript-eslint/utils'; import { diff --git a/packages/scope-manager/src/ScopeManager.ts b/packages/scope-manager/src/ScopeManager.ts index 2475783456ec..586db1123f45 100644 --- a/packages/scope-manager/src/ScopeManager.ts +++ b/packages/scope-manager/src/ScopeManager.ts @@ -14,6 +14,7 @@ import { GlobalScope, MappedTypeScope, ModuleScope, + ScopeType, SwitchScope, TSEnumScope, TSModuleScope, diff --git a/packages/type-utils/src/isTypeReadonly.ts b/packages/type-utils/src/isTypeReadonly.ts index aa616e26260b..a4e43d5997c3 100644 --- a/packages/type-utils/src/isTypeReadonly.ts +++ b/packages/type-utils/src/isTypeReadonly.ts @@ -4,7 +4,6 @@ import { isIntersectionType, isObjectType, isPropertyReadonlyInType, - isSymbolFlagSet, isUnionType, unionTypeParts, } from 'tsutils'; @@ -159,13 +158,7 @@ function isTypeReadonlyObject( } } - if ( - tsutils.isPropertyReadonlyInType( - type, - property.getEscapedName(), - checker, - ) - ) { + if (isPropertyReadonlyInType(type, property.getEscapedName(), checker)) { continue; } @@ -229,21 +222,19 @@ function isTypeReadonlyRecurser( ): Readonlyness.Readonly | Readonlyness.Mutable { seenTypes.add(type); - if (tsutils.isUnionType(type)) { + if (isUnionType(type)) { // all types in the union must be readonly - const result = tsutils - .unionTypeParts(type) - .every( - t => - seenTypes.has(t) || - isTypeReadonlyRecurser(checker, t, options, seenTypes) === - Readonlyness.Readonly, - ); + const result = unionTypeParts(type).every( + t => + seenTypes.has(t) || + isTypeReadonlyRecurser(checker, t, options, seenTypes) === + Readonlyness.Readonly, + ); const readonlyness = result ? Readonlyness.Readonly : Readonlyness.Mutable; return readonlyness; } - if (tsutils.isIntersectionType(type)) { + if (isIntersectionType(type)) { // Special case for handling arrays/tuples (as readonly arrays/tuples always have mutable methods). if ( type.types.some(t => checker.isArrayType(t) || checker.isTupleType(t)) @@ -269,7 +260,7 @@ function isTypeReadonlyRecurser( } } - if (tsutils.isConditionalType(type)) { + if (isConditionalType(type)) { const result = [type.root.node.trueType, type.root.node.falseType] .map(checker.getTypeFromTypeNode) .every( @@ -285,7 +276,7 @@ function isTypeReadonlyRecurser( // all non-object, non-intersection types are readonly. // this should only be primitive types - if (!tsutils.isObjectType(type)) { + if (!isObjectType(type)) { return Readonlyness.Readonly; } diff --git a/packages/type-utils/src/typeFlagUtils.ts b/packages/type-utils/src/typeFlagUtils.ts index 2a69d2625211..eee2b2712527 100644 --- a/packages/type-utils/src/typeFlagUtils.ts +++ b/packages/type-utils/src/typeFlagUtils.ts @@ -1,5 +1,6 @@ import { unionTypeParts } from 'tsutils'; import * as ts from 'typescript'; + import { getEnumValues } from './getEnum'; const ANY_OR_UNKNOWN = ts.TypeFlags.Any | ts.TypeFlags.Unknown; diff --git a/yarn.lock b/yarn.lock index 9bc721e08e1c..2598bd29b00e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -131,12 +131,11 @@ "@algolia/requester-common" "4.13.1" "@ampproject/remapping@^2.1.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" - integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== + version "2.1.2" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" + integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== dependencies: - "@jridgewell/gen-mapping" "^0.1.0" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/trace-mapping" "^0.3.0" "@apideck/better-ajv-errors@^0.3.1": version "0.3.6" @@ -1510,12 +1509,17 @@ resolved "https://registry.yarnpkg.com/@cspell/dict-vue/-/dict-vue-2.0.2.tgz#8618b9f4825b3d80e1788082c19ac9c15832463e" integrity sha512-/MB0RS0Gn01s4pgmjy0FvsLfr3RRMrRphEuvTRserNcM8XVtoIVAtrjig/Gg0DPwDrN8Clm0L1j7iQay6S8D0g== -"@cspotcode/source-map-support@^0.8.0": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" - integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== +"@cspotcode/source-map-consumer@0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" + integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== + +"@cspotcode/source-map-support@0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5" + integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== dependencies: - "@jridgewell/trace-mapping" "0.3.9" + "@cspotcode/source-map-consumer" "0.8.0" "@docsearch/css@3.1.1": version "3.1.1" @@ -1983,9 +1987,9 @@ integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== "@hapi/hoek@^9.0.0": - version "9.3.0" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" - integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== + version "9.2.1" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.2.1.tgz#9551142a1980503752536b5050fd99f4a7f13b17" + integrity sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw== "@hapi/topo@^5.0.0": version "5.1.0" @@ -1995,9 +1999,9 @@ "@hapi/hoek" "^9.0.0" "@humanwhocodes/config-array@^0.9.2": - version "0.9.5" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7" - integrity sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw== + version "0.9.2" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.2.tgz#68be55c737023009dfc5fe245d51181bb6476914" + integrity sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA== dependencies: "@humanwhocodes/object-schema" "^1.2.1" debug "^4.1.1" @@ -2234,24 +2238,7 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" -"@jridgewell/gen-mapping@^0.1.0": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" - integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== - dependencies: - "@jridgewell/set-array" "^1.0.0" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@jridgewell/gen-mapping@^0.3.0": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz#cf92a983c83466b8c0ce9124fadeaf09f7c66ea9" - integrity sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg== - dependencies: - "@jridgewell/set-array" "^1.0.0" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/gen-mapping@^0.3.2": +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": version "0.3.2" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== @@ -2265,7 +2252,7 @@ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== -"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": +"@jridgewell/set-array@^1.0.1": version "1.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== @@ -2283,15 +2270,7 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.15", "@jridgewell/trace-mapping@^0.3.7", "@jridgewell/trace-mapping@^0.3.9": +"@jridgewell/trace-mapping@^0.3.0", "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.15", "@jridgewell/trace-mapping@^0.3.7", "@jridgewell/trace-mapping@^0.3.9": version "0.3.15" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774" integrity sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g== @@ -3887,9 +3866,9 @@ "@types/babel__traverse" "*" "@types/babel__generator@*": - version "7.6.4" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7" - integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== + version "7.6.3" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.3.tgz#f456b4b2ce79137f768aa130d2423d2f0ccfaba5" + integrity sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA== dependencies: "@babel/types" "^7.0.0" @@ -3959,9 +3938,9 @@ integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== "@types/eslint@*": - version "8.4.2" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.2.tgz#48f2ac58ab9c631cb68845c3d956b28f79fad575" - integrity sha512-Z1nseZON+GEnFjJc04sv4NSALGjhFwy6K0HXt7qsn5ArfAKtb63dXNJHf+1YW6IpOIYRBGUbu3GwJdj8DGnCjA== + version "7.28.2" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.28.2.tgz#0ff2947cdd305897c52d5372294e8c76f351db68" + integrity sha512-KubbADPkfoU75KgKeKLsFHXnU4ipH7wYg0TRT33NK3N3yiu7jlFAAoygIWBV+KbuHx/G+AvuGX6DllnK35gfJA== dependencies: "@types/estree" "*" "@types/json-schema" "*" @@ -4030,15 +4009,15 @@ dependencies: "@types/unist" "*" -"@types/history@^4.7.11": +"@types/history@*", "@types/history@^4.7.11": version "4.7.11" resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64" integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA== "@types/html-minifier-terser@^6.0.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" - integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== + version "6.0.0" + resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.0.0.tgz#563c1c6c132cd204e71512f9c0b394ff90d3fae7" + integrity sha512-NZwaaynfs1oIoLAV1vg18e7QMVDvw+6SQrdJc8w3BwUaoroVSf6EBj/Sk4PBWGxsq0dzhA2drbsuMC1/6C6KgQ== "@types/http-proxy@^1.17.8": version "1.17.9" @@ -4053,9 +4032,9 @@ integrity sha512-4j5G9Y5jljDSICQ1R2f/Rcyoj6DZmYGneny+p/cDkjep0rkqNg0W73Ty0bVjMUTZgLXHf8oiMjg1XC3CDwCz+g== "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" - integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" + integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== "@types/istanbul-lib-report@*": version "3.0.0" @@ -4094,7 +4073,7 @@ "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" - integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== + integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= "@types/lodash@*", "@types/lodash@^4.14.182": version "4.14.186" @@ -4171,9 +4150,9 @@ integrity sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow== "@types/prop-types@*": - version "15.7.5" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" - integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== + version "15.7.4" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" + integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ== "@types/qs@*": version "6.9.7" @@ -4211,11 +4190,11 @@ "@types/react-router" "*" "@types/react-router@*": - version "5.1.18" - resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.18.tgz#c8851884b60bc23733500d86c1266e1cfbbd9ef3" - integrity sha512-YYknwy0D0iOwKQgz9v8nOzt2J6l4gouBmDnWqUUznltOTaon+r8US8ky8HvN0tXvc38U9m6z/t2RsVsnd1zM0g== + version "5.1.17" + resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.17.tgz#087091006213b11042f39570e5cd414863693968" + integrity sha512-RNSXOyb3VyRs/EOGmjBhhGKTbnN6fHWvy5FNLzWfOWOGjgVUKqJZXfpKzLmgoU8h6Hj8mpALj/mbXQASOb92wQ== dependencies: - "@types/history" "^4.7.11" + "@types/history" "*" "@types/react" "*" "@types/react@*", "@types/react@^18.0.9": @@ -4239,10 +4218,10 @@ resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.2.tgz#97d26e00cd4a0423b4af620abecf3e6f442b7975" integrity sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q== -"@types/retry@0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" - integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== +"@types/retry@^0.12.0": + version "0.12.1" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065" + integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g== "@types/rimraf@^3.0.2": version "3.0.2" @@ -4319,9 +4298,9 @@ "@types/node" "*" "@types/yargs-parser@*": - version "21.0.0" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" - integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + version "20.2.1" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129" + integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw== "@types/yargs@^17.0.8": version "17.0.10" @@ -4525,12 +4504,12 @@ acorn@^8.0.4, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.1: add-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" - integrity sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ== + integrity sha1-anmQQ3ynNtXhKI25K9MmbV9csqo= address@^1.0.1, address@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/address/-/address-1.2.0.tgz#d352a62c92fee90f89a693eccd2a8b2139ab02d9" - integrity sha512-tNEZYz5G/zYunxFm7sfhAxkXEuLj3K6BKwv6ZURlsF6yiUQ65z0Q2wZW9L5cPUl9ocofGvXOdFYbFHp0+6MOig== + version "1.1.2" + resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" + integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA== agent-base@6, agent-base@^6.0.2: version "6.0.2" @@ -4630,9 +4609,9 @@ ansi-align@^3.0.0, ansi-align@^3.0.1: string-width "^4.1.0" ansi-colors@^4.1.1: - version "4.1.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" - integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: version "4.3.2" @@ -4744,7 +4723,7 @@ array-differ@^3.0.0: array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= array-flatten@^2.1.2: version "2.1.2" @@ -4754,7 +4733,7 @@ array-flatten@^2.1.2: array-ify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" - integrity sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng== + integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4= array-includes@^3.1.4, array-includes@^3.1.5: version "3.1.5" @@ -4778,14 +4757,13 @@ array-union@^2.1.0: integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== array.prototype.flat@^1.2.5: - version "1.3.0" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz#0b0c1567bf57b38b56b4c97b8aa72ab45e4adc7b" - integrity sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw== + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz#07e0975d84bbc7c48cd1879d609e682598d33e13" + integrity sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg== dependencies: call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.19.2" - es-shim-unscopables "^1.0.0" + es-abstract "^1.19.0" array.prototype.flatmap@^1.3.0: version "1.3.0" @@ -4800,7 +4778,7 @@ array.prototype.flatmap@^1.3.0: arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= arrify@^2.0.1: version "2.0.1" @@ -4810,12 +4788,12 @@ arrify@^2.0.1: asap@^2.0.0, asap@~2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== + integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= ast-types-flow@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" - integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag== + integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= astral-regex@^2.0.0: version "2.0.0" @@ -5026,7 +5004,7 @@ balanced-match@^1.0.0: base16@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/base16/-/base16-1.0.0.tgz#e297f60d7ec1014a7a971a39ebc8a98c0b681e70" - integrity sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ== + integrity sha1-4pf2DX7BAUp6lxo568ipjAtoHnA= base64-js@^1.3.1: version "1.5.1" @@ -5036,7 +5014,7 @@ base64-js@^1.3.1: batch@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" - integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== + integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= before-after-hook@^2.2.0: version "2.2.2" @@ -5105,7 +5083,7 @@ bonjour-service@^1.0.11: boolbase@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= boxen@^5.0.0: version "5.1.2" @@ -5190,7 +5168,7 @@ buffer@^5.5.0: builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - integrity sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ== + integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= builtin-modules@^3.1.0, builtin-modules@^3.3.0: version "3.3.0" @@ -5200,7 +5178,7 @@ builtin-modules@^3.1.0, builtin-modules@^3.3.0: builtins@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" - integrity sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ== + integrity sha1-y5T662HIaWRR2zZTThQi+U8K7og= builtins@^5.0.0: version "5.0.1" @@ -5217,7 +5195,7 @@ byte-size@^7.0.0: bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== + integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= bytes@3.1.2: version "3.1.2" @@ -5307,9 +5285,9 @@ camelcase@^5.3.1: integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== camelcase@^6.2.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + version "6.2.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" + integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== caniuse-api@^3.0.0: version "3.0.0" @@ -5560,14 +5538,14 @@ clone-deep@^4.0.1: clone-response@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q== + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= dependencies: mimic-response "^1.0.0" clone@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= clsx@^1.1.1, clsx@^1.2.1: version "1.2.1" @@ -5584,7 +5562,7 @@ cmd-shim@^5.0.0: co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= collapse-white-space@^1.0.2: version "1.0.6" @@ -5613,7 +5591,7 @@ color-convert@^2.0.1: color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= color-name@~1.1.4: version "1.1.4" @@ -5626,9 +5604,9 @@ color-support@^1.1.3: integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== colord@^2.9.1: - version "2.9.2" - resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.2.tgz#25e2bacbbaa65991422c07ea209e2089428effb1" - integrity sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ== + version "2.9.1" + resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.1.tgz#c961ea0efeb57c9f0f4834458f26cb9cc4a3f90e" + integrity sha512-4LBMSt09vR0uLnPVkOUBnmxgoaeN4ewRbx801wY/bXcltXfpR/G46OdWn96XpYmCWuYvO46aBZP4NgX8HpNAcw== colorette@^2.0.10, colorette@^2.0.16, colorette@^2.0.17: version "2.0.17" @@ -5665,7 +5643,7 @@ comma-separated-tokens@^1.0.0: resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== -commander@^2.12.1, commander@^2.20.0, commander@^2.20.3: +commander@^2.12.1, commander@^2.20.0, commander@^2.7.1: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -5714,7 +5692,7 @@ common-tags@^1.8.0: commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== + integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= compare-func@^2.0.0: version "2.0.0" @@ -5747,7 +5725,7 @@ compression@^1.7.4: concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= concat-stream@^2.0.0: version "2.0.0" @@ -5792,7 +5770,7 @@ consola@^2.15.3: console-control-strings@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= console-fail-test@^0.1.7: version "0.1.7" @@ -5802,7 +5780,7 @@ console-fail-test@^0.1.7: content-disposition@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - integrity sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA== + integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= content-disposition@0.5.4: version "0.5.4" @@ -5850,13 +5828,13 @@ conventional-changelog-preset-loader@^2.3.4: integrity sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g== conventional-changelog-writer@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz#e0757072f045fe03d91da6343c843029e702f359" - integrity sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ== + version "5.0.0" + resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-5.0.0.tgz#c4042f3f1542f2f41d7d2e0d6cad23aba8df8eec" + integrity sha512-HnDh9QHLNWfL6E1uHz6krZEQOgm8hN7z/m7tT16xwd802fwgMN0Wqd7AQYVkhpsjDUx/99oo+nGgvKF657XP5g== dependencies: conventional-commits-filter "^2.0.7" dateformat "^3.0.0" - handlebars "^4.7.7" + handlebars "^4.7.6" json-stringify-safe "^5.0.1" lodash "^4.17.15" meow "^8.0.0" @@ -5908,7 +5886,7 @@ convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= cookie@0.5.0: version "0.5.0" @@ -5940,9 +5918,9 @@ core-js-compat@^3.21.0, core-js-compat@^3.25.1: browserslist "^4.21.4" core-js-pure@^3.20.2: - version "3.22.7" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.22.7.tgz#f58489d9b309fa7b26486a0f70d4ec19a418084e" - integrity sha512-wTriFxiZI+C8msGeh7fJcbC/a0V8fdInN1oS2eK79DMBGs8iIJiXhtFJCiT3rBa8w6zroHWW3p8ArlujZ/Mz+w== + version "3.21.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.21.1.tgz#8c4d1e78839f5f46208de7230cebfb72bc3bdb51" + integrity sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ== core-js@^3.23.3: version "3.24.0" @@ -5988,7 +5966,7 @@ cross-env@^7.0.3: dependencies: cross-spawn "^7.0.1" -cross-fetch@^3.1.5: +cross-fetch@^3.0.4, cross-fetch@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== @@ -6152,15 +6130,15 @@ css-minimizer-webpack-plugin@^4.0.0: source-map "^0.6.1" css-select@^4.1.3: - version "4.3.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" - integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ== + version "4.1.3" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.1.3.tgz#a70440f70317f2669118ad74ff105e65849c7067" + integrity sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA== dependencies: boolbase "^1.0.0" - css-what "^6.0.1" - domhandler "^4.3.1" - domutils "^2.8.0" - nth-check "^2.0.1" + css-what "^5.0.0" + domhandler "^4.2.0" + domutils "^2.6.0" + nth-check "^2.0.0" css-select@^5.1.0: version "5.1.0" @@ -6181,7 +6159,12 @@ css-tree@^1.1.2, css-tree@^1.1.3: mdn-data "2.0.14" source-map "^0.6.1" -css-what@^6.0.1, css-what@^6.1.0: +css-what@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" + integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== + +css-what@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== @@ -6260,9 +6243,9 @@ csso@^4.2.0: css-tree "^1.1.2" csstype@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.0.tgz#4ddcac3718d787cf9df0d1b7d15033925c8f29f2" - integrity sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA== + version "3.0.9" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.9.tgz#6410af31b26bd0520933d02cbc64fce9ce3fbf0b" + integrity sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw== d@1, d@^1.0.1: version "1.0.1" @@ -6311,12 +6294,12 @@ debug@^3.2.7: debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" - integrity sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw== + integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= decamelize-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" - integrity sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg== + integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= dependencies: decamelize "^1.1.0" map-obj "^1.0.0" @@ -6324,12 +6307,12 @@ decamelize-keys@^1.1.0: decamelize@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= decompress-response@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA== + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= dependencies: mimic-response "^1.0.0" @@ -6363,7 +6346,7 @@ default-gateway@^6.0.3: defaults@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" - integrity sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA== + integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= dependencies: clone "^1.0.2" @@ -6407,7 +6390,7 @@ delayed-stream@~1.0.0: delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= depd@2.0.0: version "2.0.0" @@ -6417,7 +6400,7 @@ depd@2.0.0: depd@^1.1.2, depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= deprecation@^2.0.0, deprecation@^2.3.1: version "2.3.1" @@ -6439,7 +6422,7 @@ detab@2.0.4: detect-indent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" - integrity sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g== + integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50= detect-indent@^6.0.0: version "6.1.0" @@ -6473,9 +6456,9 @@ detect-port@^1.3.0: debug "^2.6.0" dezalgo@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81" - integrity sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig== + version "1.0.3" + resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" + integrity sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY= dependencies: asap "^2.0.0" wrappy "1" @@ -6553,10 +6536,10 @@ domelementtype@^2.0.1, domelementtype@^2.2.0, domelementtype@^2.3.0: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== -domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" - integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== +domhandler@^4.0.0, domhandler@^4.2.0: + version "4.2.2" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.2.tgz#e825d721d19a86b8c201a35264e226c678ee755f" + integrity sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w== dependencies: domelementtype "^2.2.0" @@ -6567,7 +6550,7 @@ domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3: dependencies: domelementtype "^2.3.0" -domutils@^2.5.2, domutils@^2.8.0: +domutils@^2.5.2, domutils@^2.6.0: version "2.8.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== @@ -6624,7 +6607,7 @@ downlevel-dts@>=0.10.0: duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA== + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= duplexer@^0.1.1, duplexer@^0.1.2: version "0.1.2" @@ -6639,7 +6622,7 @@ eastasianwidth@^0.2.0: ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= ejs@^3.1.6, ejs@^3.1.7: version "3.1.8" @@ -6686,7 +6669,7 @@ emoticon@^3.2.0: encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= encoding@^0.1.13: version "0.1.13" @@ -6853,12 +6836,12 @@ escape-goat@^2.0.0: escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= escape-string-regexp@^2.0.0: version "2.0.0" @@ -7121,7 +7104,7 @@ eta@^1.12.3: etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= eval@^0.1.8: version "0.1.8" @@ -7182,7 +7165,7 @@ execa@^6.1.0: exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= expect@^29.0.0, expect@^29.1.2: version "29.1.2" @@ -7242,7 +7225,7 @@ ext@^1.1.2: extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= dependencies: is-extendable "^0.1.0" @@ -7300,12 +7283,12 @@ fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: fast-levenshtein@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= fast-url-parser@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" - integrity sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ== + integrity sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0= dependencies: punycode "^1.3.2" @@ -7342,12 +7325,12 @@ fbjs-css-vars@^1.0.0: resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8" integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== -fbjs@^3.0.0, fbjs@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.4.tgz#e1871c6bd3083bac71ff2da868ad5067d37716c6" - integrity sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ== +fbjs@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.1.tgz#70a053d34a96c2b513b559eaea124daed49ace64" + integrity sha512-8+vkGyT4lNDRKHQNPp0yh/6E7FfkLg89XqQbOYnvntRh+8RiSD43yrh9E5ejp1muCizTL4nDVG+y8W4e+LROHg== dependencies: - cross-fetch "^3.1.5" + cross-fetch "^3.0.4" fbjs-css-vars "^1.0.0" loose-envify "^1.0.0" object-assign "^4.1.0" @@ -7385,9 +7368,9 @@ file-loader@^6.2.0: schema-utils "^3.0.0" filelist@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5" - integrity sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q== + version "1.0.3" + resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.3.tgz#448607750376484932f67ef1b9ff07386b036c83" + integrity sha512-LwjCsruLWQULGYKy7TX0OPtrL9kLpojOFKc5VCTxdFTV7w5zbsgqVKfnkKG7Qgjtq50gKfO56hJv88OfcGb70Q== dependencies: minimatch "^5.0.1" @@ -7428,7 +7411,7 @@ find-cache-dir@^3.3.1: find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= dependencies: locate-path "^2.0.0" @@ -7476,17 +7459,17 @@ flat@^5.0.2: integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== flatted@^3.1.0: - version "3.2.5" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" - integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== + version "3.2.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.2.tgz#64bfed5cb68fe3ca78b3eb214ad97b63bedce561" + integrity sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA== flux@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/flux/-/flux-4.0.3.tgz#573b504a24982c4768fdfb59d8d2ea5637d72ee7" - integrity sha512-yKAbrp7JhZhj6uiT1FTuVMlIAT1J4jqEyBpFApi1kxpGZCvacMVc/t1pMQyotqHhAgvoE3bNvAykhCo2CLjnYw== + version "4.0.2" + resolved "https://registry.yarnpkg.com/flux/-/flux-4.0.2.tgz#d71dcaf6cb51ca059f303f3d964d6f325d444952" + integrity sha512-u/ucO5ezm3nBvdaSGkWpDlzCePoV+a9x3KHmy13TV/5MzOaCZDN8Mfd94jmf0nOi8ZZay+nOKbBUkOe2VNaupQ== dependencies: fbemitter "^3.0.0" - fbjs "^3.0.1" + fbjs "^3.0.0" follow-redirects@^1.0.0, follow-redirects@^1.14.0, follow-redirects@^1.14.7, follow-redirects@^1.15.0: version "1.15.2" @@ -7494,9 +7477,9 @@ follow-redirects@^1.0.0, follow-redirects@^1.14.0, follow-redirects@^1.14.7, fol integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== fork-ts-checker-webpack-plugin@^6.5.0: - version "6.5.2" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz#4f67183f2f9eb8ba7df7177ce3cf3e75cdafb340" - integrity sha512-m5cUmF30xkZ7h4tWUgTAcEaKmUW7tfyUyTqNNOz7OxWJ0v1VWKTcOvH8FWHUwSjlW/356Ijc9vi3XfcPstpQKA== + version "6.5.0" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz#0282b335fa495a97e167f69018f566ea7d2a2b5e" + integrity sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw== dependencies: "@babel/code-frame" "^7.8.3" "@types/json-schema" "^7.0.5" @@ -7534,7 +7517,7 @@ fraction.js@^4.2.0: fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= fs-constants@^1.0.0: version "1.0.0" @@ -7584,7 +7567,7 @@ fs-monkey@1.0.3: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@^2.3.2, fsevents@~2.3.2: version "2.3.2" @@ -7609,7 +7592,7 @@ function.prototype.name@^1.1.5: functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= functions-have-names@^1.2.2: version "1.2.3" @@ -7730,7 +7713,7 @@ git-raw-commits@^2.0.8: git-remote-origin-url@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz#5282659dae2107145a11126112ad3216ec5fa65f" - integrity sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw== + integrity sha1-UoJlna4hBxRaERJhEq0yFuxfpl8= dependencies: gitconfiglocal "^1.0.0" pify "^2.3.0" @@ -7761,7 +7744,7 @@ git-url-parse@^13.1.0: gitconfiglocal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz#41d045f3851a5ea88f03f24ca1c6178114464b9b" - integrity sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ== + integrity sha1-QdBF84UaXqiPA/JMocYXgRRGS5s= dependencies: ini "^1.3.2" @@ -7834,7 +7817,7 @@ glob@^7.0.0, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: global-dirs@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" - integrity sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg== + integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU= dependencies: ini "^1.3.4" @@ -7866,17 +7849,10 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^13.15.0: - version "13.15.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.15.0.tgz#38113218c907d2f7e98658af246cef8b77e90bac" - integrity sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog== - dependencies: - type-fest "^0.20.2" - -globals@^13.9.0: - version "13.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.18.0.tgz#fb224daeeb2bb7d254cd2c640f003528b8d0c1dc" - integrity sha512-/mR4KI8Ps2spmoc0Ulu9L7agOF0du1CZNQ3dke8yItYlyKNmGrkONemBbd6V8UTc1Wgcqn21t3WYB7dbRmh6/A== +globals@^13.6.0, globals@^13.9.0: + version "13.11.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.11.0.tgz#40ef678da117fe7bd2e28f1fab24951bd0255be7" + integrity sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g== dependencies: type-fest "^0.20.2" @@ -7947,7 +7923,7 @@ handle-thing@^2.0.0: resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== -handlebars@^4.7.7: +handlebars@^4.7.6: version "4.7.7" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== @@ -7977,7 +7953,7 @@ has-bigints@^1.0.1, has-bigints@^1.0.2: has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= has-flag@^4.0.0: version "4.0.0" @@ -8011,7 +7987,7 @@ has-tostringtag@^1.0.0: has-unicode@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= has-yarn@^2.1.0: version "2.1.0" @@ -8130,9 +8106,9 @@ hosted-git-info@^3.0.6: lru-cache "^6.0.0" hosted-git-info@^4.0.0, hosted-git-info@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" - integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== + version "4.0.2" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.0.2.tgz#5e425507eede4fea846b7262f0838456c4209961" + integrity sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg== dependencies: lru-cache "^6.0.0" @@ -8146,7 +8122,7 @@ hosted-git-info@^5.0.0: hpack.js@^2.1.6: version "2.1.6" resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" - integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ== + integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI= dependencies: inherits "^2.0.1" obuf "^1.0.0" @@ -8154,9 +8130,9 @@ hpack.js@^2.1.6: wbuf "^1.1.0" html-entities@^2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" - integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA== + version "2.3.2" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.2.tgz#760b404685cb1d794e4f4b744332e3b00dcfe488" + integrity sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ== html-escaper@^2.0.0: version "2.0.2" @@ -8225,7 +8201,7 @@ http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0: http-deceiver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" - integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== + integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= http-errors@2.0.0: version "2.0.0" @@ -8241,7 +8217,7 @@ http-errors@2.0.0: http-errors@~1.6.2: version "1.6.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== + integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= dependencies: depd "~1.1.2" inherits "2.0.3" @@ -8249,9 +8225,9 @@ http-errors@~1.6.2: statuses ">= 1.4.0 < 2" http-parser-js@>=0.5.1: - version "0.5.6" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.6.tgz#2e02406ab2df8af8a7abfba62e0da01c62b95afd" - integrity sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA== + version "0.5.3" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9" + integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg== http-proxy-agent@^5.0.0: version "5.0.0" @@ -8283,9 +8259,9 @@ http-proxy@^1.18.1: requires-port "^1.0.0" https-proxy-agent@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" - integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== dependencies: agent-base "6" debug "4" @@ -8303,7 +8279,7 @@ human-signals@^3.0.1: humanize-ms@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" - integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ== + integrity sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0= dependencies: ms "^2.0.0" @@ -8339,7 +8315,7 @@ idb@^7.0.1: identity-obj-proxy@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz#94d2bda96084453ef36fbc5aaec37e0f79f1fc14" - integrity sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA== + integrity sha1-lNK9qWCERT7zb7xarsN+D3nx/BQ= dependencies: harmony-reflect "^1.4.6" @@ -8368,9 +8344,9 @@ image-size@^1.0.1: queue "6.0.2" immer@^9.0.7: - version "9.0.14" - resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.14.tgz#e05b83b63999d26382bb71676c9d827831248a48" - integrity sha512-ubBeqQutOSLIFCUBN03jGeOS6a3DoYlSYwYJTa+gSKEZKU5redJIqkIdZ3JVv/4RZpfcXdAWH5zCNLWPRv2WDw== + version "9.0.12" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.12.tgz#2d33ddf3ee1d247deab9d707ca472c8c942a0f20" + integrity sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA== import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" @@ -8383,7 +8359,7 @@ import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.3 import-lazy@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" - integrity sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A== + integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= import-lazy@~4.0.0: version "4.0.0" @@ -8391,9 +8367,9 @@ import-lazy@~4.0.0: integrity sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw== import-local@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" - integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + version "3.0.3" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.3.tgz#4d51c2c495ca9393da259ec66b62e022920211e0" + integrity sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA== dependencies: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" @@ -8401,7 +8377,7 @@ import-local@^3.0.2: imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= indent-string@^4.0.0: version "4.0.0" @@ -8421,7 +8397,7 @@ infima@0.2.0-alpha.42: inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: once "^1.3.0" wrappy "1" @@ -8434,7 +8410,7 @@ inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, i inherits@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= ini@2.0.0: version "2.0.0" @@ -8542,7 +8518,7 @@ is-alphanumerical@^1.0.0: is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= is-bigint@^1.0.1: version "1.0.4" @@ -8617,12 +8593,12 @@ is-docker@^2.0.0, is-docker@^2.1.1: is-extendable@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= is-fullwidth-code-point@^3.0.0: version "3.0.0" @@ -8667,12 +8643,12 @@ is-interactive@^1.0.0: is-lambda@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" - integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ== + integrity sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU= is-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" - integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g== + integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE= is-negative-zero@^2.0.2: version "2.0.2" @@ -8685,9 +8661,9 @@ is-npm@^5.0.0: integrity sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA== is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== + version "1.0.6" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" + integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== dependencies: has-tostringtag "^1.0.0" @@ -8699,7 +8675,7 @@ is-number@^7.0.0: is-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg== + integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= is-obj@^2.0.0: version "2.0.0" @@ -8719,7 +8695,7 @@ is-path-inside@^3.0.2: is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= is-plain-obj@^2.0.0: version "2.1.0" @@ -8766,7 +8742,7 @@ is-regex@^1.1.4: is-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" - integrity sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA== + integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= is-root@^2.1.0: version "2.1.0" @@ -8814,14 +8790,14 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: is-text-path@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-1.0.1.tgz#4e1aa0fb51bfbcb3e92688001397202c1775b66e" - integrity sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w== + integrity sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4= dependencies: text-extensions "^1.0.0" is-typedarray@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= is-unicode-supported@^0.1.0: version "0.1.0" @@ -8860,22 +8836,22 @@ is-yarn-global@^0.3.0: isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: version "3.2.0" @@ -8883,9 +8859,9 @@ istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz#31d18bdd127f825dd02ea7bfdfd906f8ab840e9f" - integrity sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A== + version "5.1.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz#7b49198b657b27a730b8e9cb601f1e1bff24c59a" + integrity sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q== dependencies: "@babel/core" "^7.12.3" "@babel/parser" "^7.14.7" @@ -9318,7 +9294,7 @@ jest@^29.0.3: jju@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" - integrity sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA== + integrity sha1-o6vicYryQaKykE+EpiWXDzia4yo= joi@^17.6.0: version "17.6.0" @@ -9359,12 +9335,12 @@ jsesc@^2.5.1: jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= json-buffer@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ== + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= json-parse-better-errors@^1.0.1: version "1.0.2" @@ -9414,7 +9390,7 @@ json-schema@*, json-schema@^0.4.0: json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= json-stringify-nice@^1.1.4: version "1.1.4" @@ -9424,7 +9400,7 @@ json-stringify-nice@^1.1.4: json-stringify-safe@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= json5@^1.0.1: version "1.0.1" @@ -9451,7 +9427,7 @@ jsonc-parser@~3.1.0: jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= optionalDependencies: graceful-fs "^4.1.6" @@ -9467,7 +9443,7 @@ jsonfile@^6.0.1: jsonparse@^1.2.0, jsonparse@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" - integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== + integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= jsonpointer@^5.0.0: version "5.0.1" @@ -9542,7 +9518,7 @@ language-subtag-registry@~0.3.2: language-tags@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.5.tgz#d321dbc4da30ba8bf3024e040fa5c14661f9193a" - integrity sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ== + integrity sha1-0yHbxNowuovzAk4ED6XBRmH5GTo= dependencies: language-subtag-registry "~0.3.2" @@ -9622,9 +9598,9 @@ lilconfig@2.0.5, lilconfig@^2.0.3: integrity sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg== lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + version "1.1.6" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= linkify-it@^4.0.1: version "4.0.1" @@ -9669,7 +9645,7 @@ listr2@^4.0.5: load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - integrity sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw== + integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= dependencies: graceful-fs "^4.1.2" parse-json "^4.0.0" @@ -9687,14 +9663,14 @@ load-json-file@^6.2.0: type-fest "^0.6.0" loader-runner@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" - integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== + version "4.2.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" + integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== loader-utils@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129" - integrity sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A== + version "2.0.1" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.1.tgz#3b8d4386f42378d6434d32d7bc08e7a52d39575e" + integrity sha512-g4miPa9uUrZz4iElkaVJgDFwKJGh8aQGM7pUL4ejXl6cu7kSb30seQOVGNMP6sW8j7DW77X68hJZ+GM7UGhXeQ== dependencies: big.js "^5.2.2" emojis-list "^3.0.0" @@ -9708,7 +9684,7 @@ loader-utils@^3.2.0: locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= dependencies: p-locate "^2.0.0" path-exists "^3.0.0" @@ -9738,37 +9714,37 @@ locate-path@^6.0.0: lodash.curry@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.curry/-/lodash.curry-4.1.1.tgz#248e36072ede906501d75966200a86dab8b23170" - integrity sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA== + integrity sha1-JI42By7ekGUB11lmIAqG2riyMXA= lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= lodash.flow@^3.3.0: version "3.5.0" resolved "https://registry.yarnpkg.com/lodash.flow/-/lodash.flow-3.5.0.tgz#87bf40292b8cf83e4e8ce1a3ae4209e20071675a" - integrity sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw== + integrity sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o= lodash.get@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ== + integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= lodash.isequal@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== + integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= lodash.ismatch@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" - integrity sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g== + integrity sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc= lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= lodash.merge@^4.6.2: version "4.6.2" @@ -9783,7 +9759,7 @@ lodash.sortby@^4.7.0: lodash.uniq@4.5.0, lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== + integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@~4.17.15: version "4.17.21" @@ -9924,7 +9900,7 @@ makeerror@1.0.12: map-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg== + integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= map-obj@^4.0.0: version "4.3.0" @@ -10026,17 +10002,17 @@ mdn-data@2.0.14: mdurl@^1.0.0, mdurl@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" - integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== + integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= -memfs@^3.1.2, memfs@^3.4.3: - version "3.4.4" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.4.tgz#e8973cd8060548916adcca58a248e7805c715e89" - integrity sha512-W4gHNUE++1oSJVn8Y68jPXi+mkx3fXR5ITE/Ubz6EQ3xRpCN5k2CQ4AUR8094Z7211F876TyoBACGsIveqgiGA== +memfs@^3.1.2, memfs@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.1.tgz#b78092f466a0dce054d63d39275b24c71d3f1305" + integrity sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw== dependencies: fs-monkey "1.0.3" @@ -10074,7 +10050,7 @@ meow@^8.0.0: merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= merge-stream@^2.0.0: version "2.0.0" @@ -10089,7 +10065,7 @@ merge2@^1.3.0, merge2@^1.4.1: methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: version "4.0.5" @@ -10128,6 +10104,11 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== +mime@^2.3.1: + version "2.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" + integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -10303,11 +10284,6 @@ monaco-editor@^0.33.0: resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.33.0.tgz#842e244f3750a2482f8a29c676b5684e75ff34af" integrity sha512-VcRWPSLIUEgQJQIE0pVT8FcGBIgFoxz7jtqctE+IiCxWugD0DwgyQBcZBhdSrdMC84eumoqMZsGl2GTreOzwqw== -mrmime@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.0.tgz#14d387f0585a5233d291baba339b063752a2398b" - integrity sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ== - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -10369,12 +10345,12 @@ natural-compare-lite@^1.4.0: natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= ncp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" - integrity sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA== + integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M= negotiator@0.6.3, negotiator@^0.6.3: version "0.6.3" @@ -10429,9 +10405,9 @@ node-forge@^1: integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== node-gyp-build@^4.3.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.4.0.tgz#42e99687ce87ddeaf3a10b99dc06abc11021f3f4" - integrity sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ== + version "4.3.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" + integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q== node-gyp@^9.0.0: version "9.0.0" @@ -10452,7 +10428,7 @@ node-gyp@^9.0.0: node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= node-machine-id@^1.1.12: version "1.1.12" @@ -10509,7 +10485,7 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: normalize-range@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== + integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= normalize-url@^4.1.0: version "4.5.1" @@ -10625,7 +10601,7 @@ nprogress@^0.2.0: resolved "https://registry.yarnpkg.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1" integrity sha1-y480xTIT2JVyP8urkH6UIq28r7E= -nth-check@^2.0.1: +nth-check@^2.0.0, nth-check@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== @@ -10956,11 +10932,11 @@ p-reduce@^2.0.0, p-reduce@^2.1.0: integrity sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw== p-retry@^4.5.0: - version "4.6.2" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" - integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== + version "4.6.1" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.1.tgz#8fcddd5cdf7a67a0911a9cf2ef0e5df7f602316c" + integrity sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA== dependencies: - "@types/retry" "0.12.0" + "@types/retry" "^0.12.0" retry "^0.13.1" p-timeout@^3.2.0: @@ -11526,9 +11502,9 @@ postcss-reduce-transforms@^5.1.0: postcss-value-parser "^4.2.0" postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: - version "6.0.10" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d" - integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w== + version "6.0.9" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f" + integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" @@ -11970,13 +11946,13 @@ react-style-proptype@^3.2.2: prop-types "^15.5.4" react-textarea-autosize@^8.3.2: - version "8.3.4" - resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.4.tgz#270a343de7ad350534141b02c9cb78903e553524" - integrity sha512-CdtmP8Dc19xL8/R6sWvtknD/eCXkQr30dtvC4VmGInhRsfF8X/ihXCq6+9l9qbxmKRiq407/7z5fxE7cVWQNgQ== + version "8.3.3" + resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz#f70913945369da453fd554c168f6baacd1fa04d8" + integrity sha512-2XlHXK2TDxS6vbQaoPbMOfQ8GK7+irc2fVK6QFIcC8GOnH3zI/v481n+j1L0WaPVvKxwesnY93fEfH++sus2rQ== dependencies: "@babel/runtime" "^7.10.2" - use-composed-ref "^1.3.0" - use-latest "^1.2.1" + use-composed-ref "^1.0.0" + use-latest "^1.0.0" react@^18.1.0: version "18.2.0" @@ -12752,12 +12728,12 @@ signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== sirv@^1.0.7: - version "1.0.19" - resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49" - integrity sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ== + version "1.0.18" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.18.tgz#105fab52fb656ce8a2bebbf36b11052005952899" + integrity sha512-f2AOPogZmXgJ9Ma2M22ZEhc1dNtRIzcEkiflMFeVTRq+OViOZMvH1IPMVOwrKaxpSaHioBJiDR0SluRqGa7atA== dependencies: "@polka/url" "^1.0.0-next.20" - mrmime "^1.0.0" + mime "^2.3.1" totalist "^1.0.0" sisteransi@^1.0.5: @@ -12936,9 +12912,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.11" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95" - integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== + version "3.0.10" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz#0d9becccde7003d6c658d487dd48a32f0bf3014b" + integrity sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA== spdy-transport@^3.0.0: version "3.0.0" @@ -13017,9 +12993,9 @@ statuses@2.0.1: integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= std-env@^3.0.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.1.1.tgz#1f19c4d3f6278c52efd08a94574a2a8d32b7d092" - integrity sha512-/c645XdExBypL01TpFKiG/3RAa/Qmu+zRi0MwAmrdEkwHNuN0ebo8ccAXBBDa5Z0QOJgBskUIbuCK91x0sCVEw== + version "3.0.1" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.0.1.tgz#bc4cbc0e438610197e34c2d79c3df30b491f5182" + integrity sha512-mC1Ps9l77/97qeOZc+HrOL7TIaOboHqMZ24dGVQrlxFcpPpfCHpH+qfUT7Dz+6mlG8+JPA1KfBQo19iC/+Ngcw== string-argv@^0.3.1, string-argv@~0.3.1: version "0.3.1" @@ -13492,6 +13468,11 @@ trough@^1.0.0: resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== +ts-essentials@^2.0.3: + version "2.0.12" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-2.0.12.tgz#c9303f3d74f75fa7528c3d49b80e089ab09d8745" + integrity sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w== + ts-node@^10.7.0: version "10.7.0" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.7.0.tgz#35d503d0fab3e2baa672a0e94f4b40653c2463f5" @@ -13612,9 +13593,9 @@ type-fest@^0.8.1: integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== type-fest@^2.5.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.13.0.tgz#d1ecee38af29eb2e863b22299a3d68ef30d2abfb" - integrity sha512-lPfAm42MxE4/456+QyIaaVBAwgpJb6xZ8PRu09utnhPdWwcyj9vgy6Sq0Z5yNbJ21EdxB5dRU/Qg8bsyAMtlcw== + version "2.12.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.12.1.tgz#d2be8f50bf5f8f0a5fd916d29bf3e98c17e960be" + integrity sha512-AiknQSEqKVGDDjtZqeKrUoTlcj7FKhupmnVUgz6KoOKtvMwRGE6hUNJ/nVear+h7fnUPO1q/htSkYKb1pyntkQ== type-is@~1.6.18: version "1.6.18" @@ -13662,9 +13643,9 @@ uc.micro@^1.0.1, uc.micro@^1.0.5: integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== uglify-js@^3.1.4: - version "3.15.5" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.15.5.tgz#2b10f9e0bfb3f5c15a8e8404393b6361eaeb33b3" - integrity sha512-hNM5q5GbBRB5xB+PMqVRcgYe4c8jbyZ1pzZhS6jbq54/4F2gFK869ZheiE5A8/t+W5jtTNpWef/5Q9zk639FNQ== + version "3.14.2" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.14.2.tgz#d7dd6a46ca57214f54a2d0a43cad0f35db82ac99" + integrity sha512-rtPMlmcO4agTUfz10CbgJ1k6UAoXM2gWb3GoMPPZB/+/Ackf8lNWk11K4rYi2D0apgoFRLtQOZhb+/iGNJq26A== unbox-primitive@^1.0.2: version "1.0.2" @@ -13891,22 +13872,24 @@ url-parse-lax@^3.0.0: dependencies: prepend-http "^2.0.0" -use-composed-ref@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/use-composed-ref/-/use-composed-ref-1.3.0.tgz#3d8104db34b7b264030a9d916c5e94fbe280dbda" - integrity sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ== +use-composed-ref@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/use-composed-ref/-/use-composed-ref-1.1.0.tgz#9220e4e94a97b7b02d7d27eaeab0b37034438bbc" + integrity sha512-my1lNHGWsSDAhhVAT4MKs6IjBUtG6ZG11uUqexPH9PptiIZDQOzaF4f5tEbJ2+7qvNbtXNBbU3SfmN+fXlWDhg== + dependencies: + ts-essentials "^2.0.3" -use-isomorphic-layout-effect@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb" - integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA== +use-isomorphic-layout-effect@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz#7bb6589170cd2987a152042f9084f9effb75c225" + integrity sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ== -use-latest@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/use-latest/-/use-latest-1.2.1.tgz#d13dfb4b08c28e3e33991546a2cee53e14038cf2" - integrity sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw== +use-latest@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/use-latest/-/use-latest-1.2.0.tgz#a44f6572b8288e0972ec411bdd0840ada366f232" + integrity sha512-d2TEuG6nSLKQLAfW3By8mKr8HurOlTkul0sOpxbClIv4SQ4iOd7BYr7VIzdbktUCnv7dua/60xzd8igMU6jmyw== dependencies: - use-isomorphic-layout-effect "^1.1.1" + use-isomorphic-layout-effect "^1.0.0" util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" @@ -13933,10 +13916,10 @@ uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== -v8-compile-cache-lib@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" - integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== +v8-compile-cache-lib@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz#0582bcb1c74f3a2ee46487ceecf372e46bce53e8" + integrity sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA== v8-compile-cache@2.3.0, v8-compile-cache@^2.0.3: version "2.3.0" @@ -14098,12 +14081,12 @@ webpack-bundle-analyzer@^4.5.0: ws "^7.3.1" webpack-dev-middleware@^5.3.1: - version "5.3.3" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz#efae67c2793908e7311f1d9b06f2a08dcc97e51f" - integrity sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA== + version "5.3.1" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz#aa079a8dedd7e58bfeab358a9af7dab304cee57f" + integrity sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg== dependencies: colorette "^2.0.10" - memfs "^3.4.3" + memfs "^3.4.1" mime-types "^2.1.31" range-parser "^1.2.1" schema-utils "^4.0.0" @@ -14544,9 +14527,9 @@ ws@^7.3.1: integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w== ws@^8.4.2: - version "8.7.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.7.0.tgz#eaf9d874b433aa00c0e0d8752532444875db3957" - integrity sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg== + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== xdg-basedir@^4.0.0: version "4.0.0" @@ -14642,15 +14625,15 @@ yocto-queue@^0.1.0: integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== z-schema@~5.0.2: - version "5.0.3" - resolved "https://registry.yarnpkg.com/z-schema/-/z-schema-5.0.3.tgz#68fafb9b735fc7f3c89eabb3e5a6353b4d7b4935" - integrity sha512-sGvEcBOTNum68x9jCpCVGPFJ6mWnkD0YxOcddDlJHRx3tKdB2q8pCHExMVZo/AV/6geuVJXG7hljDaWG8+5GDw== + version "5.0.2" + resolved "https://registry.yarnpkg.com/z-schema/-/z-schema-5.0.2.tgz#f410394b2c9fcb9edaf6a7511491c0bb4e89a504" + integrity sha512-40TH47ukMHq5HrzkeVE40Ad7eIDKaRV2b+Qpi2prLc9X9eFJFzV7tMe5aH12e6avaSS/u5l653EQOv+J9PirPw== dependencies: lodash.get "^4.4.2" lodash.isequal "^4.5.0" validator "^13.7.0" optionalDependencies: - commander "^2.20.3" + commander "^2.7.1" zwitch@^1.0.0: version "1.0.5" From c37165cc4035a27549dd3cb82b1a2bef77a32b1a Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Fri, 25 Nov 2022 04:00:34 -0500 Subject: [PATCH 68/88] Continued fixing the build --- .../eslint-plugin-tslint/src/rules/config.ts | 12 +++---- .../src/rules/no-implied-eval.ts | 1 - .../src/rules/no-unnecessary-qualifier.ts | 1 - .../rules/no-unnecessary-type-arguments.ts | 1 - .../non-nullable-type-assertion-style.ts | 1 + .../eslint-plugin/src/rules/return-await.ts | 1 - .../strict-enums-assignment.test.ts | 8 +++-- .../strict-enums-comparison.test.ts | 36 +++++++++++++------ .../strict-enums-functions.test.ts | 16 ++++----- .../strict-enums-incrementing.test.ts | 6 ++-- packages/type-utils/src/getEnum.ts | 33 ----------------- packages/type-utils/src/getEnumNames.ts | 14 ++++++++ packages/type-utils/src/index.ts | 2 +- packages/type-utils/src/typeFlagUtils.ts | 31 +++------------- 14 files changed, 67 insertions(+), 96 deletions(-) delete mode 100644 packages/type-utils/src/getEnum.ts create mode 100644 packages/type-utils/src/getEnumNames.ts diff --git a/packages/eslint-plugin-tslint/src/rules/config.ts b/packages/eslint-plugin-tslint/src/rules/config.ts index 9fcfa844da11..b2cc2a289f50 100644 --- a/packages/eslint-plugin-tslint/src/rules/config.ts +++ b/packages/eslint-plugin-tslint/src/rules/config.ts @@ -98,18 +98,14 @@ export default createRule({ ], }, defaultOptions: [{}], - create(context) { + create( + context, + [{ rules: tslintRules, rulesDirectory: tslintRulesDirectory, lintFile }], + ) { const fileName = context.getFilename(); const sourceCode = context.getSourceCode().text; const parserServices = ESLintUtils.getParserServices(context); - /** - * The TSLint rules configuration passed in by the user - */ - const [ - { rules: tslintRules, rulesDirectory: tslintRulesDirectory, lintFile }, - ] = context.options; - const program = parserServices.program; /** diff --git a/packages/eslint-plugin/src/rules/no-implied-eval.ts b/packages/eslint-plugin/src/rules/no-implied-eval.ts index 38c57488c4cf..2247494ef5a0 100644 --- a/packages/eslint-plugin/src/rules/no-implied-eval.ts +++ b/packages/eslint-plugin/src/rules/no-implied-eval.ts @@ -1,6 +1,5 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts b/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts index 0707f2abb11e..371520328d51 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts @@ -1,6 +1,5 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts b/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts index 6f53eae67da5..bd39a1f12286 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts @@ -1,5 +1,4 @@ import type { TSESTree } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; diff --git a/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts b/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts index 1daea4d92aef..2b80ab1681c8 100644 --- a/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts +++ b/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts @@ -2,6 +2,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; + import * as util from '../util'; export default util.createRule({ diff --git a/packages/eslint-plugin/src/rules/return-await.ts b/packages/eslint-plugin/src/rules/return-await.ts index 1c226adae180..1797e47e1276 100644 --- a/packages/eslint-plugin/src/rules/return-await.ts +++ b/packages/eslint-plugin/src/rules/return-await.ts @@ -174,7 +174,6 @@ export default util.createRule({ ts.SyntaxKind.AwaitExpression, ts.SyntaxKind.Unknown, ); - return nodePrecedence > awaitPrecedence; } diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts index 9977ab5f9883..0273919c99e5 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts @@ -1,8 +1,10 @@ -import { +import type { InvalidTestCase, ValidTestCase, } from '@typescript-eslint/utils/src/ts-eslint'; -import rule, { MessageIds } from '../../../src/rules/strict-enums'; + +import type { MessageIds } from '../../../src/rules/strict-enums'; +import rule from '../../../src/rules/strict-enums'; import { fruit2EnumDefinition, fruitEnumDefinition, @@ -36,7 +38,7 @@ valid.push({ code: ` const myArray = [1]; const [firstElement] = myArray; - `, + `, }); valid.push({ diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts index 0a52ea326f1a..d0934e624f7b 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts @@ -1,8 +1,10 @@ -import { +import type { InvalidTestCase, ValidTestCase, } from '@typescript-eslint/utils/src/ts-eslint'; -import rule, { MessageIds } from '../../../src/rules/strict-enums'; + +import type { MessageIds } from '../../../src/rules/strict-enums'; +import rule from '../../../src/rules/strict-enums'; import { fruit2EnumDefinition, fruitEnumDefinition, @@ -326,9 +328,16 @@ fruitOrBoolean === true; valid.push({ name: "Comparing various valid types (Brad's test)", code: ` -enum Str { A = 'a' } -enum Num { B = 1 } -enum Mixed { A = 'a', B = 1 } +enum Str { + A = 'a', +} +enum Num { + B = 1, +} +enum Mixed { + A = 'a', + B = 1, +} declare const str: Str; declare const strOrString: Str | string; @@ -361,15 +370,22 @@ str === someFunction; num === someFunction; mixed === someFunction; */ - `, + `, }); invalid.push({ name: "Comparing various invalid types (Brad's test)", code: ` -enum Str { A = 'a' } -enum Num { B = 1 } -enum Mixed { A = 'a', B = 1 } +enum Str { + A = 'a', +} +enum Num { + B = 1, +} +enum Mixed { + A = 'a', + B = 1, +} declare const str: Str; declare const num: Num; @@ -380,7 +396,7 @@ str === 'a'; num === 1; mixed === 'a'; mixed === 1; - `, + `, errors: [ { messageId: 'mismatchedComparison' }, { messageId: 'mismatchedComparison' }, diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts index 8b15940ad8a1..425e508f4328 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts @@ -1,8 +1,10 @@ -import { +import type { InvalidTestCase, ValidTestCase, } from '@typescript-eslint/utils/src/ts-eslint'; -import rule, { MessageIds } from '../../../src/rules/strict-enums'; + +import type { MessageIds } from '../../../src/rules/strict-enums'; +import rule from '../../../src/rules/strict-enums'; import { fruitEnumDefinition, strictEnumsRuleTester, @@ -999,12 +1001,8 @@ toEqual(0, 0); valid.push({ name: 'Using JSON.stringify', code: ` -JSON.stringify( - {}, - (_, value: unknown) => value ?? undefined, - 2, -); - `, +JSON.stringify({}, (_, value: unknown) => value ?? undefined, 2); + `, }); valid.push({ @@ -1013,7 +1011,7 @@ valid.push({ function flatten(arr: T[][]): T[] { return arr.reduce((acc, a) => acc.concat(a), []); } - `, + `, }); strictEnumsRuleTester.run('strict-enums-functions', rule, { diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-incrementing.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-incrementing.test.ts index 9ffcc1eb6b46..9da3927ce726 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-incrementing.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-incrementing.test.ts @@ -1,8 +1,10 @@ -import { +import type { InvalidTestCase, ValidTestCase, } from '@typescript-eslint/utils/src/ts-eslint'; -import rule, { MessageIds } from '../../../src/rules/strict-enums'; + +import type { MessageIds } from '../../../src/rules/strict-enums'; +import rule from '../../../src/rules/strict-enums'; import { fruitEnumDefinition, strictEnumsRuleTester } from './strict-enums'; const valid: ValidTestCase[] = []; diff --git a/packages/type-utils/src/getEnum.ts b/packages/type-utils/src/getEnum.ts deleted file mode 100644 index 469fb2d03cbb..000000000000 --- a/packages/type-utils/src/getEnum.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Helper function to get only the keys of an enum. - * - * (By default, TypeScript will put the values inside of the keys of a - * number-based enum, so those have to be filtered out.) - * - * This function will work properly for both number and string enums. - */ -function getEnumNames( - transpiledEnum: Record, -): T[] { - const keys = Object.keys(transpiledEnum); - return keys.filter(x => isNaN(parseInt(x, 10))) as T[]; -} - -/** - * Helper function to get the only the values of an enum. - * - * (By default, TypeScript will put the keys inside of the values of a - * number-based enum, so those have to be filtered out.) - * - * This function will work properly for both number and string enums. - */ -function getEnumValues(transpiledEnum: Record): T[] { - const values = Object.values(transpiledEnum); - const numberValues = values.filter(value => typeof value === 'number'); - - // If there are no number values, then this must be a string enum, and no filtration is required - const valuesToReturn = numberValues.length > 0 ? numberValues : values; - return valuesToReturn as T[]; -} - -export { getEnumNames, getEnumValues }; diff --git a/packages/type-utils/src/getEnumNames.ts b/packages/type-utils/src/getEnumNames.ts new file mode 100644 index 000000000000..48a61fcaec89 --- /dev/null +++ b/packages/type-utils/src/getEnumNames.ts @@ -0,0 +1,14 @@ +/** + * Gets the keys of an enum. + * + * (By default, TypeScript will put the values inside of the keys of a + * number-based enum, so those have to be filtered out.) + * + * This function will work properly for both number and string enums. + */ +export function getEnumNames( + enumObject: Record, +): T[] { + const keys = Object.keys(enumObject); + return keys.filter(x => isNaN(parseInt(x, 10))) as T[]; +} diff --git a/packages/type-utils/src/index.ts b/packages/type-utils/src/index.ts index 85166ab97fe8..c5643cea4821 100644 --- a/packages/type-utils/src/index.ts +++ b/packages/type-utils/src/index.ts @@ -2,7 +2,7 @@ export * from './containsAllTypesByName'; export * from './getConstrainedTypeAtLocation'; export * from './getContextualType'; export * from './getDeclaration'; -export * from './getEnum'; +export * from './getEnumNames'; export * from './getSourceFileOfNode'; export * from './getTokenAtPosition'; export * from './getTypeArguments'; diff --git a/packages/type-utils/src/typeFlagUtils.ts b/packages/type-utils/src/typeFlagUtils.ts index eee2b2712527..f0fe1ae82169 100644 --- a/packages/type-utils/src/typeFlagUtils.ts +++ b/packages/type-utils/src/typeFlagUtils.ts @@ -1,8 +1,6 @@ import { unionTypeParts } from 'tsutils'; import * as ts from 'typescript'; -import { getEnumValues } from './getEnum'; - const ANY_OR_UNKNOWN = ts.TypeFlags.Any | ts.TypeFlags.Unknown; /** @@ -16,24 +14,6 @@ export function getTypeFlags(type: ts.Type): number | ts.TypeFlags { return flags; } -/** - * Returns an array containing the names of every type flag that matches the - * given type flags. - * - * Useful for debugging and inspecting the AST. - */ -export function getTypeFlagNames(type: ts.Type): string[] { - const flagNames: string[] = []; - for (const flag of getEnumValues(ts.TypeFlags)) { - if (isTypeFlagSet(type, flag)) { - const flagName = ts.TypeFlags[flag]; - flagNames.push(flagName); - } - } - - return flagNames; -} - function isFlagSet(flags: number, flag: number): boolean { return (flags & flag) !== 0; } @@ -49,13 +29,13 @@ export function isSymbolFlagSet( } /** + * @param flagsToCheck The composition of one or more `ts.TypeFlags`. + * @param isReceiver Whether the type is a receiving type (i.e. the type of a + * called function's parameter). + * @remarks * Note that if the type is a union, this function will decompose it into the * parts and get the flags of every union constituent. If this is not desired, * use the `isTypeFlagSetSimple` function instead. - * - * @param flagsToCheck The composition of one or more `ts.TypeFlags`. - * @param isReceiver True if the type is a receiving type (i.e. the type of a - * called function's parameter). */ export function isTypeFlagSet( type: ts.Type, @@ -73,8 +53,7 @@ export function isTypeFlagSet( /** * Similar to the `isTypeFlagSet` function, but does not decompose unions. - * - * This is just a very simple bit flag check. + * Instead performs a single bit flag check. */ export function isTypeFlagSetSimple( type: ts.Type, From 3f37c6733729a3282a77d48c3749c5cb2645f800 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Fri, 25 Nov 2022 04:22:16 -0500 Subject: [PATCH 69/88] Passing build --- .../eslint-plugin/docs/rules/strict-enums.md | 49 +++++-------------- packages/eslint-plugin/src/configs/strict.ts | 1 + .../src/rules/no-confusing-void-expression.ts | 2 +- .../src/rules/no-implied-eval.ts | 6 +-- .../src/rules/no-misused-promises.ts | 3 +- .../no-unnecessary-boolean-literal-compare.ts | 4 +- .../src/rules/no-unnecessary-qualifier.ts | 3 +- .../rules/no-unnecessary-type-arguments.ts | 3 +- .../non-nullable-type-assertion-style.ts | 4 +- .../src/rules/strict-boolean-expressions.ts | 12 ++--- .../eslint-plugin/src/rules/strict-enums.ts | 38 +++++--------- packages/eslint-plugin/src/util/misc.ts | 5 ++ packages/type-utils/src/getEnumNames.ts | 14 ------ packages/type-utils/src/index.ts | 1 - packages/type-utils/src/isTypeReadonly.ts | 2 +- packages/type-utils/src/typeFlagUtils.ts | 21 -------- 16 files changed, 50 insertions(+), 118 deletions(-) delete mode 100644 packages/type-utils/src/getEnumNames.ts diff --git a/packages/eslint-plugin/docs/rules/strict-enums.md b/packages/eslint-plugin/docs/rules/strict-enums.md index 501adff8e691..f40b36e169cf 100644 --- a/packages/eslint-plugin/docs/rules/strict-enums.md +++ b/packages/eslint-plugin/docs/rules/strict-enums.md @@ -1,10 +1,10 @@ # `strict-enums` -Disallows the usage of unsafe enum patterns. +Disallows the usage of unsafe enum code patterns. ## Rule Details -Horrifyingly, the TypeScript compiler will allow you to set any number to a variable containing a number enum, like this: +The TypeScript compiler will allow you to set any number to a variable containing a number enum, like this: ```ts enum Fruit { @@ -16,22 +16,16 @@ let fruit = Fruit.Apple; fruit = 999; // No error ``` -This has resulted in many TypeScript programmers avoiding the use of enums altogether. Instead, they should use this rule, which bans working with enums in potentially unsafe ways. +This rule flags the following unsafe enum practices: -See the examples below for the types of patterns that are prevented. - -## Goals - -The goal of this rule is to make enums work like they do in other languages. One of the main benefits of enums is that they allow you to write code that is future-safe, because enums are supposed to be resilient to reorganization. If you arbitrarily change the values of an enum (or change the ordering of an enum with computed values), the idea is that nothing in your code-base should break. - -## Banned Patterns - -This rule bans: - -1. Enum incrementing/decrementing - `incorrectIncrement` -1. Mismatched enum declarations/assignments - `mismatchedAssignment` -1. Mismatched enum comparisons - `mismatchedComparison` -1. Mismatched enum function arguments - `mismatchedFunctionArgument` +- Incrementing or decrementing an enum value + - Enums are supposed to be resilient to reorganization, so you should explicitly assign a new value instead. Changing the values of the enum can potentially break code assumptions made on the original values. +- The type of the assignment does not match the declared enum type of the variable. + - In other words, you are trying to assign a `Foo` enum value to a variable with a `Bar` type. Enums are supposed to be resilient to reorganization, so these kinds of assignments can be dangerous. +- The two things in the comparison do not have a shared enum type. + - You might be trying to compare using a number literal, like `Foo.Value1 === 1`. Or, you might be trying to compare use a disparate enum type, like `Foo.Value1 === Bar.Value1`. Either way, you need to use a value that corresponds to the correct enum, like `foo === Foo.Value1`, where `foo` is type `Foo`. Enums are supposed to be resilient to reorganization, so these types of comparisons can be dangerous. +- The argument in the function call does not match the declared enum type of the function signature. + - You might be trying to use a number literal, like `useFoo(1)`. Or, you might be trying to use a disparate enum type, like `useFoo(Bar.Value1)`. Either way, you need to use a value that corresponds to the correct enum, like `useFoo(Foo.Value1)`. Enums are supposed to be resilient to reorganization, so non-exact function calls like this can be dangerous. @@ -86,17 +80,6 @@ function useFruit(fruit: Fruit) {} useFruit(Fruit.Apple); ``` -## Error Information - -- `incorrectIncrement` - You cannot increment or decrement an enum type. - - Enums are supposed to be resilient to reorganization, so you should explicitly assign a new value instead. For example, if someone someone reassigned/reordered the values of the enum, then it could potentially break your code. -- `mismatchedAssignment` - The type of the assignment does not match the declared enum type of the variable. - - In other words, you are trying to assign a `Foo` enum value to a variable with a `Bar` type. Enums are supposed to be resilient to reorganization, so these kinds of assignments can be dangerous. -- `mismatchedComparison` - The two things in the comparison do not have a shared enum type. - - You might be trying to compare using a number literal, like `Foo.Value1 === 1`. Or, you might be trying to compare use a disparate enum type, like `Foo.Value1 === Bar.Value1`. Either way, you need to use a value that corresponds to the correct enum, like `foo === Foo.Value1`, where `foo` is type `Foo`. Enums are supposed to be resilient to reorganization, so these types of comparisons can be dangerous. -- `mismatchedFunctionArgument` - The argument in the function call does not match the declared enum type of the function signature. - - You might be trying to use a number literal, like `useFoo(1)`. Or, you might be trying to use a disparate enum type, like `useFoo(Bar.Value1)`. Either way, you need to use a value that corresponds to the correct enum, like `useFoo(Foo.Value1)`. Enums are supposed to be resilient to reorganization, so non-exact function calls like this can be dangerous. - ## Number Enums vs String Enums Surprisingly, the TypeScript compiler deals with string enums in a safer way than it does with number enums. If we duplicate the first example above by using a string enum, the TypeScript compiler will correctly throw an error: @@ -137,13 +120,3 @@ if (fruit > Fruit.Banana) { ``` This pattern allows you to select a subset of enums. However, it can lead to bugs when enum values are arbitrarily changed, because the subset will also change. The TypeScript compiler cannot warn you about this, so you should use this pattern with care. - -## Options - -No options are provided. - -## Attributes - -- [ ] ✅ Recommended -- [ ] 🔧 Fixable -- [x] 💭 Requires type information diff --git a/packages/eslint-plugin/src/configs/strict.ts b/packages/eslint-plugin/src/configs/strict.ts index ccd44b85a0a1..a13f8f5dfc92 100644 --- a/packages/eslint-plugin/src/configs/strict.ts +++ b/packages/eslint-plugin/src/configs/strict.ts @@ -41,6 +41,7 @@ export = { '@typescript-eslint/prefer-return-this-type': 'warn', '@typescript-eslint/prefer-string-starts-ends-with': 'warn', '@typescript-eslint/prefer-ts-expect-error': 'warn', + '@typescript-eslint/strict-enums': 'warn', '@typescript-eslint/unified-signatures': 'warn', }, }; diff --git a/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts b/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts index 92eb59a2b2a5..01e5b45dbb8b 100644 --- a/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts +++ b/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts @@ -84,7 +84,7 @@ export default util.createRule({ const checker = parserServices.program.getTypeChecker(); const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); const type = util.getConstrainedTypeAtLocation(checker, tsNode); - if (!util.isTypeFlagSet(type, ts.TypeFlags.VoidLike)) { + if (!tsutils.isTypeFlagSet(type, ts.TypeFlags.VoidLike)) { // not a void expression return; } diff --git a/packages/eslint-plugin/src/rules/no-implied-eval.ts b/packages/eslint-plugin/src/rules/no-implied-eval.ts index 2247494ef5a0..fb180ffe2e1c 100644 --- a/packages/eslint-plugin/src/rules/no-implied-eval.ts +++ b/packages/eslint-plugin/src/rules/no-implied-eval.ts @@ -1,5 +1,6 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; +import { isSymbolFlagSet } from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -70,10 +71,7 @@ export default util.createRule({ if ( symbol && - util.isSymbolFlagSet( - symbol, - ts.SymbolFlags.Function | ts.SymbolFlags.Method, - ) + isSymbolFlagSet(symbol, ts.SymbolFlags.Function | ts.SymbolFlags.Method) ) { return true; } diff --git a/packages/eslint-plugin/src/rules/no-misused-promises.ts b/packages/eslint-plugin/src/rules/no-misused-promises.ts index 7c3b718a93dd..c458b1fc0b87 100644 --- a/packages/eslint-plugin/src/rules/no-misused-promises.ts +++ b/packages/eslint-plugin/src/rules/no-misused-promises.ts @@ -1,6 +1,7 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'tsutils'; +import { isTypeFlagSet } from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -655,7 +656,7 @@ function isVoidReturningFunctionType( return false; } - hadVoidReturn ||= util.isTypeFlagSet(returnType, ts.TypeFlags.Void); + hadVoidReturn ||= isTypeFlagSet(returnType, ts.TypeFlags.Void); } } diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts b/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts index 77519c108062..f874905b738b 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts @@ -113,7 +113,7 @@ export default util.createRule({ } function isBooleanType(expressionType: ts.Type): boolean { - return util.isTypeFlagSetSimple( + return tsutils.isTypeFlagSet( expressionType, ts.TypeFlags.Boolean | ts.TypeFlags.BooleanLiteral, ); @@ -134,7 +134,7 @@ export default util.createRule({ const nonNullishTypes = types.filter( type => - !util.isTypeFlagSetSimple( + !tsutils.isTypeFlagSet( type, ts.TypeFlags.Undefined | ts.TypeFlags.Null, ), diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts b/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts index 371520328d51..fbf3b41e9668 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts @@ -1,5 +1,6 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; +import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -34,7 +35,7 @@ export default util.createRule({ symbol: ts.Symbol, checker: ts.TypeChecker, ): ts.Symbol | null { - return util.isSymbolFlagSet(symbol, ts.SymbolFlags.Alias) + return tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.Alias) ? checker.getAliasedSymbol(symbol) : null; } diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts b/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts index bd39a1f12286..6d300b36fe12 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts @@ -1,4 +1,5 @@ import type { TSESTree } from '@typescript-eslint/utils'; +import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -179,7 +180,7 @@ function getAliasedSymbol( symbol: ts.Symbol, checker: ts.TypeChecker, ): ts.Symbol { - return util.isSymbolFlagSet(symbol, ts.SymbolFlags.Alias) + return tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.Alias) ? checker.getAliasedSymbol(symbol) : symbol; } diff --git a/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts b/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts index 2b80ab1681c8..4953cf8041ea 100644 --- a/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts +++ b/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts @@ -33,7 +33,9 @@ export default util.createRule({ parserServices.esTreeNodeToTSNodeMap.get(node), ); - if (util.isTypeFlagSet(type, ts.TypeFlags.Any | ts.TypeFlags.Unknown)) { + if ( + tsutils.isTypeFlagSet(type, ts.TypeFlags.Any | ts.TypeFlags.Unknown) + ) { return undefined; } diff --git a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts index 20e7fd6838b0..1e327a8a4b83 100644 --- a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts +++ b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts @@ -764,7 +764,7 @@ export default util.createRule({ if ( types.some(type => - util.isTypeFlagSet( + tsutils.isTypeFlagSet( type, ts.TypeFlags.Null | ts.TypeFlags.Undefined | ts.TypeFlags.VoidLike, ), @@ -773,7 +773,7 @@ export default util.createRule({ variantTypes.add('nullish'); } const booleans = types.filter(type => - util.isTypeFlagSet(type, ts.TypeFlags.BooleanLike), + tsutils.isTypeFlagSet(type, ts.TypeFlags.BooleanLike), ); // If incoming type is either "true" or "false", there will be one type @@ -789,7 +789,7 @@ export default util.createRule({ } const strings = types.filter(type => - util.isTypeFlagSet(type, ts.TypeFlags.StringLike), + tsutils.isTypeFlagSet(type, ts.TypeFlags.StringLike), ); if (strings.length) { @@ -801,7 +801,7 @@ export default util.createRule({ } const numbers = types.filter(type => - util.isTypeFlagSet( + tsutils.isTypeFlagSet( type, ts.TypeFlags.NumberLike | ts.TypeFlags.BigIntLike, ), @@ -817,7 +817,7 @@ export default util.createRule({ if ( types.some( type => - !util.isTypeFlagSet( + !tsutils.isTypeFlagSet( type, ts.TypeFlags.Null | ts.TypeFlags.Undefined | @@ -849,7 +849,7 @@ export default util.createRule({ variantTypes.add('any'); } - if (types.some(type => util.isTypeFlagSet(type, ts.TypeFlags.Never))) { + if (types.some(type => tsutils.isTypeFlagSet(type, ts.TypeFlags.Never))) { variantTypes.add('never'); } diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index c61f8d4a3a4e..bd72cf31d569 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -60,7 +60,7 @@ export default util.createRule({ mismatchedComparison: 'The two things in the comparison do not have a shared enum type.', mismatchedFunctionArgument: - 'The {{ ordinal }} argument in the function call does not match the declared enum type of the function signature.', + 'Argument {{ ordinal }} in the function call does not match the declared enum type of the function signature.', }, schema: [], }, @@ -87,7 +87,7 @@ export default util.createRule({ return type; } - if (!util.isSymbolFlagSet(symbol, ts.SymbolFlags.EnumMember)) { + if (!tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.EnumMember)) { return type; } @@ -96,7 +96,7 @@ export default util.createRule({ return type; } - const parentType = getTypeFromTSNode(valueDeclaration.parent); + const parentType = typeChecker.getTypeAtLocation(valueDeclaration.parent); if (parentType === undefined) { return type; } @@ -233,21 +233,13 @@ export default util.createRule({ } function getTypeFromNode(node: TSESTree.Node): ts.Type { - const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); - return getTypeFromTSNode(tsNode); - } - - function getTypeFromTSNode(tsNode: ts.Node): ts.Type { - return typeChecker.getTypeAtLocation(tsNode); - } - - function getTypeName(type: ts.Type): string { - return util.getTypeName(typeChecker, type); + return typeChecker.getTypeAtLocation( + parserServices.esTreeNodeToTSNodeMap.get(node), + ); } function hasEnumTypes(type: ts.Type): boolean { - const enumTypes = getEnumTypes(type); - return enumTypes.size > 0; + return getEnumTypes(type).size > 0; } function hasIntersection(type: ts.Type): boolean { @@ -369,7 +361,7 @@ export default util.createRule({ */ const parameter = declaration.parameters[i]; if (parameter !== undefined) { - const parameterTSNode = getTypeFromTSNode(parameter); + const parameterTSNode = typeChecker.getTypeAtLocation(parameter); const constraint = parameterTSNode.getConstraint(); if (constraint !== undefined) { parameterType = constraint; @@ -389,9 +381,7 @@ export default util.createRule({ node: node.arguments[i], messageId: 'mismatchedFunctionArgument', data: { - ordinal: getOrdinalSuffix(i + 1), // e.g. 0 --> 1st - argumentType: getTypeName(argumentType), - parameterType: getTypeName(parameterType), + ordinal: getOrdinalSuffix(i + 1), }, }); } @@ -785,17 +775,13 @@ export default util.createRule({ * expects a `ts.BindingName` instead of a `ts.VariableDeclaration`. * https://github.com/microsoft/TypeScript/issues/48878 */ - const leftType = getTypeFromTSNode(leftTSNode.name); - const rightType = getTypeFromTSNode(leftTSNode.initializer); + const leftType = typeChecker.getTypeAtLocation(leftTSNode.name); + const rightType = typeChecker.getTypeAtLocation(leftTSNode.initializer); if (isAssigningNonEnumValueToEnumVariable(leftType, rightType)) { context.report({ - node, messageId: 'mismatchedAssignment', - data: { - assignmentType: getTypeName(rightType), - declaredType: getTypeName(leftType), - }, + node, }); } }, diff --git a/packages/eslint-plugin/src/util/misc.ts b/packages/eslint-plugin/src/util/misc.ts index ff16e247c75c..2bdc8ee0f591 100644 --- a/packages/eslint-plugin/src/util/misc.ts +++ b/packages/eslint-plugin/src/util/misc.ts @@ -158,6 +158,10 @@ type RequireKeys< TKeys extends keyof TObj, > = ExcludeKeys & { [k in TKeys]-?: Exclude }; +function getEnumNames(myEnum: Record): T[] { + return Object.keys(myEnum).filter(x => isNaN(parseInt(x))) as T[]; +} + /** * Given an array of words, returns an English-friendly concatenation, separated with commas, with * the `and` clause inserted before the last item. @@ -183,6 +187,7 @@ export { ExcludeKeys, findFirstResult, formatWordList, + getEnumNames, getNameFromIndexSignature, getNameFromMember, isDefinitionFile, diff --git a/packages/type-utils/src/getEnumNames.ts b/packages/type-utils/src/getEnumNames.ts deleted file mode 100644 index 48a61fcaec89..000000000000 --- a/packages/type-utils/src/getEnumNames.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Gets the keys of an enum. - * - * (By default, TypeScript will put the values inside of the keys of a - * number-based enum, so those have to be filtered out.) - * - * This function will work properly for both number and string enums. - */ -export function getEnumNames( - enumObject: Record, -): T[] { - const keys = Object.keys(enumObject); - return keys.filter(x => isNaN(parseInt(x, 10))) as T[]; -} diff --git a/packages/type-utils/src/index.ts b/packages/type-utils/src/index.ts index c5643cea4821..dde032e1770c 100644 --- a/packages/type-utils/src/index.ts +++ b/packages/type-utils/src/index.ts @@ -2,7 +2,6 @@ export * from './containsAllTypesByName'; export * from './getConstrainedTypeAtLocation'; export * from './getContextualType'; export * from './getDeclaration'; -export * from './getEnumNames'; export * from './getSourceFileOfNode'; export * from './getTokenAtPosition'; export * from './getTypeArguments'; diff --git a/packages/type-utils/src/isTypeReadonly.ts b/packages/type-utils/src/isTypeReadonly.ts index a4e43d5997c3..7ba2b300089a 100644 --- a/packages/type-utils/src/isTypeReadonly.ts +++ b/packages/type-utils/src/isTypeReadonly.ts @@ -4,13 +4,13 @@ import { isIntersectionType, isObjectType, isPropertyReadonlyInType, + isSymbolFlagSet, isUnionType, unionTypeParts, } from 'tsutils'; import * as ts from 'typescript'; import { getTypeOfPropertyOfType } from './propertyTypes'; -import { isSymbolFlagSet } from './typeFlagUtils'; const enum Readonlyness { /** the type cannot be handled by the function */ diff --git a/packages/type-utils/src/typeFlagUtils.ts b/packages/type-utils/src/typeFlagUtils.ts index f0fe1ae82169..bb978686bbdd 100644 --- a/packages/type-utils/src/typeFlagUtils.ts +++ b/packages/type-utils/src/typeFlagUtils.ts @@ -18,16 +18,6 @@ function isFlagSet(flags: number, flag: number): boolean { return (flags & flag) !== 0; } -/** - * @param flagsToCheck The composition of one or more `ts.SymbolFlags`. - */ -export function isSymbolFlagSet( - symbol: ts.Symbol, - flagsToCheck: number | ts.SymbolFlags, -): boolean { - return isFlagSet(symbol.flags, flagsToCheck); -} - /** * @param flagsToCheck The composition of one or more `ts.TypeFlags`. * @param isReceiver Whether the type is a receiving type (i.e. the type of a @@ -50,14 +40,3 @@ export function isTypeFlagSet( return isFlagSet(flags, flagsToCheck); } - -/** - * Similar to the `isTypeFlagSet` function, but does not decompose unions. - * Instead performs a single bit flag check. - */ -export function isTypeFlagSetSimple( - type: ts.Type, - flagsToCheck: number | ts.TypeFlags, -): boolean { - return isFlagSet(type.flags, flagsToCheck); -} From c942261421fabc6ca4582484f573ee3752d0f311 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Fri, 25 Nov 2022 04:22:57 -0500 Subject: [PATCH 70/88] Update packages/eslint-plugin/src/rules/strict-enums.ts --- packages/eslint-plugin/src/rules/strict-enums.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index bd72cf31d569..1250268ac25b 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -50,7 +50,7 @@ export default util.createRule({ type: 'suggestion', docs: { description: 'Disallow the usage of unsafe enum code patterns', - recommended: false, + recommended: 'strict', requiresTypeChecking: true, }, messages: { From b2947f9b5bf48fc98947b19b98f1f35df4b7dbcc Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Fri, 25 Nov 2022 04:23:19 -0500 Subject: [PATCH 71/88] Update packages/eslint-plugin/src/rules/strict-enums.ts --- packages/eslint-plugin/src/rules/strict-enums.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 1250268ac25b..e929a094c5ab 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -108,18 +108,6 @@ export default util.createRule({ * See the comment for the `EnumKind` enum. */ function getEnumKind(type: ts.Type): EnumKind { - if (type.isUnion()) { - throw new Error( - 'The "getEnumKind" function is not meant to be used on unions. Use the "getEnumKinds" function instead.', - ); - } - - if (type.isIntersection()) { - throw new Error( - 'The "getEnumKind" function is not meant to be used on intersections.', - ); - } - if (!isEnum(type)) { return EnumKind.NON_ENUM; } From a7772d2547e07ae8b7aa40a899fe34c1d166e0be Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Fri, 25 Nov 2022 04:31:47 -0500 Subject: [PATCH 72/88] A few more reverts --- packages/eslint-plugin/src/rules/no-implied-eval.ts | 7 +++++-- .../eslint-plugin/src/rules/no-misused-promises.ts | 3 +-- packages/scope-manager/src/referencer/Reference.ts | 4 ++-- packages/type-utils/src/typeFlagUtils.ts | 10 +++++----- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-implied-eval.ts b/packages/eslint-plugin/src/rules/no-implied-eval.ts index fb180ffe2e1c..0ae6698c533c 100644 --- a/packages/eslint-plugin/src/rules/no-implied-eval.ts +++ b/packages/eslint-plugin/src/rules/no-implied-eval.ts @@ -1,6 +1,6 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import { isSymbolFlagSet } from 'tsutils'; +import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -71,7 +71,10 @@ export default util.createRule({ if ( symbol && - isSymbolFlagSet(symbol, ts.SymbolFlags.Function | ts.SymbolFlags.Method) + tsutils.isSymbolFlagSet( + symbol, + ts.SymbolFlags.Function | ts.SymbolFlags.Method, + ) ) { return true; } diff --git a/packages/eslint-plugin/src/rules/no-misused-promises.ts b/packages/eslint-plugin/src/rules/no-misused-promises.ts index c458b1fc0b87..b6914ae2c392 100644 --- a/packages/eslint-plugin/src/rules/no-misused-promises.ts +++ b/packages/eslint-plugin/src/rules/no-misused-promises.ts @@ -1,7 +1,6 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'tsutils'; -import { isTypeFlagSet } from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -656,7 +655,7 @@ function isVoidReturningFunctionType( return false; } - hadVoidReturn ||= isTypeFlagSet(returnType, ts.TypeFlags.Void); + hadVoidReturn ||= tsutils.isTypeFlagSet(returnType, ts.TypeFlags.Void); } } diff --git a/packages/scope-manager/src/referencer/Reference.ts b/packages/scope-manager/src/referencer/Reference.ts index ba38d076a110..d74b628d8cc1 100644 --- a/packages/scope-manager/src/referencer/Reference.ts +++ b/packages/scope-manager/src/referencer/Reference.ts @@ -66,7 +66,7 @@ class Reference { /** * In some cases, a reference may be a type, value or both a type and value reference. */ - readonly #referenceType: number | ReferenceTypeFlag; + readonly #referenceType: ReferenceTypeFlag; /** * True if this reference can reference types @@ -89,7 +89,7 @@ class Reference { writeExpr?: TSESTree.Node | null, maybeImplicitGlobal?: ReferenceImplicitGlobal | null, init?: boolean, - referenceType: number | ReferenceTypeFlag = ReferenceTypeFlag.Value, + referenceType = ReferenceTypeFlag.Value, ) { this.identifier = identifier; this.from = scope; diff --git a/packages/type-utils/src/typeFlagUtils.ts b/packages/type-utils/src/typeFlagUtils.ts index bb978686bbdd..587930869eba 100644 --- a/packages/type-utils/src/typeFlagUtils.ts +++ b/packages/type-utils/src/typeFlagUtils.ts @@ -6,8 +6,8 @@ const ANY_OR_UNKNOWN = ts.TypeFlags.Any | ts.TypeFlags.Unknown; /** * Gets all of the type flags in a type, iterating through unions automatically. */ -export function getTypeFlags(type: ts.Type): number | ts.TypeFlags { - let flags = 0; +export function getTypeFlags(type: ts.Type): ts.TypeFlags { + let flags = 0 as ts.TypeFlags; for (const t of unionTypeParts(type)) { flags |= t.flags; } @@ -20,16 +20,16 @@ function isFlagSet(flags: number, flag: number): boolean { /** * @param flagsToCheck The composition of one or more `ts.TypeFlags`. - * @param isReceiver Whether the type is a receiving type (i.e. the type of a + * @param isReceiver Whether the type is a receiving type (e.g. the type of a * called function's parameter). * @remarks * Note that if the type is a union, this function will decompose it into the * parts and get the flags of every union constituent. If this is not desired, - * use the `isTypeFlagSetSimple` function instead. + * use the `isTypeFlag` function from tsutils. */ export function isTypeFlagSet( type: ts.Type, - flagsToCheck: number | ts.TypeFlags, + flagsToCheck: ts.TypeFlags, isReceiver?: boolean, ): boolean { const flags = getTypeFlags(type); From 4204a60eed522d4ab5a515f8b1d35e2ade96e7fb Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Fri, 25 Nov 2022 04:38:49 -0500 Subject: [PATCH 73/88] Just a bit more changing typeFlagUtils --- packages/type-utils/src/typeFlagUtils.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/type-utils/src/typeFlagUtils.ts b/packages/type-utils/src/typeFlagUtils.ts index 587930869eba..c74a6ccae9cb 100644 --- a/packages/type-utils/src/typeFlagUtils.ts +++ b/packages/type-utils/src/typeFlagUtils.ts @@ -14,10 +14,6 @@ export function getTypeFlags(type: ts.Type): ts.TypeFlags { return flags; } -function isFlagSet(flags: number, flag: number): boolean { - return (flags & flag) !== 0; -} - /** * @param flagsToCheck The composition of one or more `ts.TypeFlags`. * @param isReceiver Whether the type is a receiving type (e.g. the type of a @@ -34,9 +30,9 @@ export function isTypeFlagSet( ): boolean { const flags = getTypeFlags(type); - if (isReceiver && isFlagSet(flags, ANY_OR_UNKNOWN)) { + if (isReceiver && flags & ANY_OR_UNKNOWN) { return true; } - return isFlagSet(flags, flagsToCheck); + return (flags & flagsToCheck) !== 0; } From 89bcd73637e34287357a8a1ce7f14e677100f408 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Fri, 25 Nov 2022 05:02:32 -0500 Subject: [PATCH 74/88] Fixed strict-enums.md build --- .../eslint-plugin/docs/rules/strict-enums.md | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/strict-enums.md b/packages/eslint-plugin/docs/rules/strict-enums.md index f40b36e169cf..8f63ba31a04a 100644 --- a/packages/eslint-plugin/docs/rules/strict-enums.md +++ b/packages/eslint-plugin/docs/rules/strict-enums.md @@ -1,10 +1,13 @@ -# `strict-enums` +--- +description: 'Disallow the usage of unsafe enum code patterns.' +--- -Disallows the usage of unsafe enum code patterns. +> 🛑 This file is source code, not the primary documentation location! 🛑 +> +> See **https://typescript-eslint.io/rules/strict-enums** for documentation. -## Rule Details - -The TypeScript compiler will allow you to set any number to a variable containing a number enum, like this: +The TypeScript compiler can be surprisingly lenient when working with enums. +For example, it will allow you to assign any `number` value to a variable containing a numeric enum: ```ts enum Fruit { @@ -18,14 +21,14 @@ fruit = 999; // No error This rule flags the following unsafe enum practices: -- Incrementing or decrementing an enum value - - Enums are supposed to be resilient to reorganization, so you should explicitly assign a new value instead. Changing the values of the enum can potentially break code assumptions made on the original values. -- The type of the assignment does not match the declared enum type of the variable. - - In other words, you are trying to assign a `Foo` enum value to a variable with a `Bar` type. Enums are supposed to be resilient to reorganization, so these kinds of assignments can be dangerous. -- The two things in the comparison do not have a shared enum type. - - You might be trying to compare using a number literal, like `Foo.Value1 === 1`. Or, you might be trying to compare use a disparate enum type, like `Foo.Value1 === Bar.Value1`. Either way, you need to use a value that corresponds to the correct enum, like `foo === Foo.Value1`, where `foo` is type `Foo`. Enums are supposed to be resilient to reorganization, so these types of comparisons can be dangerous. -- The argument in the function call does not match the declared enum type of the function signature. - - You might be trying to use a number literal, like `useFoo(1)`. Or, you might be trying to use a disparate enum type, like `useFoo(Bar.Value1)`. Either way, you need to use a value that corresponds to the correct enum, like `useFoo(Foo.Value1)`. Enums are supposed to be resilient to reorganization, so non-exact function calls like this can be dangerous. +- Changing a numeric enum's value with math operators such as increments or multiplying + - TypeScript allows changing numeric enum values like `myValue++` as a convenience, even though the new value may not be in the enum. +- Assigning a value of one enum type to a recipient that's a different enum type + - In other words, you are trying to assign a `Fruit` enum value to a variable with a `Vegetable` type. +- Comparing an enum value with another value that is not its same enum type + - You might be trying to compare using a number literal, like `Fruit.Value1 === 1`. Or, you might be trying to compare use a disparate enum type, like `Fruit.Value1 === Vegetable.Value1`. +- Providing a value to a location where only one of those two is a particular enum type + - You might be trying to use a number literal, like `useFruit(1)`. Or, you might be trying to use a disparate enum type, like `useFruit(Vegetable.Value1)`, where `useFruit` receives a parameter of type `Foo`. @@ -80,7 +83,11 @@ function useFruit(fruit: Fruit) {} useFruit(Fruit.Apple); ``` -## Number Enums vs String Enums + + +## Rule Details + +### Number Enums vs String Enums Surprisingly, the TypeScript compiler deals with string enums in a safer way than it does with number enums. If we duplicate the first example above by using a string enum, the TypeScript compiler will correctly throw an error: @@ -110,7 +117,7 @@ if (vegetable === Vegetable.Lettuce) { } ``` -## Comparison Operators +### Comparison Operators Since it is a common pattern, this rule allows using greater than or less than to compare numeric enums, like this: From 4f13db4cd3ee6e8b3436ed6549bbb80ed7f91eb7 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Fri, 25 Nov 2022 05:38:41 -0500 Subject: [PATCH 75/88] Convert tests to not pushing --- .../strict-enums-assignment.test.ts | 465 ++-- .../strict-enums-comparison.test.ts | 607 +++--- .../strict-enums-functions.test.ts | 1870 ++++++++--------- .../strict-enums-incrementing.test.ts | 209 +- 4 files changed, 1438 insertions(+), 1713 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts index 0273919c99e5..dc575fb31639 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts @@ -1,9 +1,3 @@ -import type { - InvalidTestCase, - ValidTestCase, -} from '@typescript-eslint/utils/src/ts-eslint'; - -import type { MessageIds } from '../../../src/rules/strict-enums'; import rule from '../../../src/rules/strict-enums'; import { fruit2EnumDefinition, @@ -11,189 +5,88 @@ import { strictEnumsRuleTester, } from './strict-enums'; -const valid: ValidTestCase[] = []; -const invalid: InvalidTestCase[] = []; - -valid.push({ - name: 'Declaring an enum with an empty initializer', - code: - fruitEnumDefinition + - ` - let fruit: Fruit; - if (true) { - fruit = Fruit.Apple; - } else { - fruit = Fruit.Banana; - } - `, -}); - -/** - * In development, this would trigger run-time errors due to the - * `typeChecker.getTypeAtLocation` method being buggy and not having a proper - * function signature. - */ -valid.push({ - name: 'Declaring an "empty" variable with array destructuring', - code: ` - const myArray = [1]; - const [firstElement] = myArray; - `, -}); - -valid.push({ - name: 'Assigning a number enum literal to a number enum (with type-inference)', - code: - fruitEnumDefinition + - ` +strictEnumsRuleTester.run('strict-enums-assignment', rule, { + valid: [ + { + code: + fruitEnumDefinition + + ` + let fruit: Fruit; + if (true) { + fruit = Fruit.Apple; + } else { + fruit = Fruit.Banana; + } + `, + }, + { + code: ` +const myArray = [1]; +const [firstElement] = myArray; + `, + }, + { + code: + fruitEnumDefinition + + ` const fruit = Fruit.Apple; `, -}); - -valid.push({ - name: 'Assigning a number enum literal to a number enum (without type-inference)', - code: - fruitEnumDefinition + - ` + }, + { + code: + fruitEnumDefinition + + ` const fruit: Fruit = Fruit.Apple; `, -}); - -valid.push({ - name: 'Assigning a number enum value to a variable of the same type with const', - code: - fruitEnumDefinition + - ` + }, + { + code: + fruitEnumDefinition + + ` const apple = Fruit.Apple; const fruit: Fruit = apple; `, -}); - -invalid.push({ - name: 'Assigning a number literal to a number enum with const', - code: - fruitEnumDefinition + - ` -const fruit: Fruit = 0; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -valid.push({ - name: 'Assigning a number enum value to a variable of the same type with let', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Apple; -fruit = Fruit.Banana; - `, -}); - -invalid.push({ - name: 'Assigning a number literal to a number enum with let', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Apple; -fruit = 1; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -invalid.push({ - name: 'Assigning an enum parent to a number enum', - code: - fruitEnumDefinition + - ` -const fruit: Fruit = Fruit; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -invalid.push({ - name: 'Assigning a mismatched enum value to a number enum', - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` -const fruit: Fruit = Fruit2.Apple2; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -valid.push({ - name: 'Assigning a number enum literal to a variable with a union type of "number enum | null" with const', - code: - fruitEnumDefinition + - ` -const fruit: Fruit | null = Fruit.Apple; - `, -}); - -valid.push({ - name: 'Assigning a null value to a variable with a union type of "number enum | null" with const', - code: - fruitEnumDefinition + - ` -const fruit: Fruit | null = null; - `, -}); - -invalid.push({ - name: 'Assigning a number literal to a variable with a union type of "number enum | null" with const', - code: - fruitEnumDefinition + - ` -const fruit: Fruit | null = 0; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -valid.push({ - name: 'Assigning a number enum literal to a variable with a union type of "number enum | null" with let', - code: - fruitEnumDefinition + - ` -let fruit: Fruit | null = null; -fruit = Fruit.Apple; - `, -}); - -valid.push({ - name: 'Assigning a null value to a variable with a union type of "number enum | null" with let', - code: - fruitEnumDefinition + - ` -let fruit: Fruit | null = Fruit.Apple; -fruit = null; - `, -}); - -invalid.push({ - name: 'Assigning a number literal to a variable with a union type of "number enum | null" with let', - code: - fruitEnumDefinition + - ` -let fruit: Fruit | null = null; -fruit = 0; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -invalid.push({ - name: 'Assigning a enum literal to a variable with a union type of "number enum | number"', - code: - fruitEnumDefinition + - ` -declare const fruit: Fruit | number; -const fruitCopy: Fruit = fruit; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -valid.push({ - name: 'Assigning variables with a composition type that includes individual enum values', - code: ` + }, + { + code: + fruitEnumDefinition + + ` + let fruit = Fruit.Apple; + fruit = Fruit.Banana; + `, + }, + { + code: + fruitEnumDefinition + + ` + const fruit: Fruit | null = Fruit.Apple; + `, + }, + { + code: + fruitEnumDefinition + + ` + const fruit: Fruit | null = null; + `, + }, + { + code: + fruitEnumDefinition + + ` + let fruit: Fruit | null = null; + fruit = Fruit.Apple; + `, + }, + { + code: + fruitEnumDefinition + + ` + let fruit: Fruit | null = Fruit.Apple; + fruit = null; + `, + }, + { + code: ` enum Foo { A = 1, B = 2, @@ -206,93 +99,137 @@ declare const fooSubset: Foo.A | Foo.B | Foo.C; const x: Foo = fooSubset; const y: Foo.A | Foo.B | Foo.C = fooSubset; const z: Foo.A | Foo.B | Foo.C | Foo.D = foo; - `, -}); - -// Intersection types are always allowed; see the docs -valid.push({ - name: 'Assigning a variable with a intersection enum type', - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` + `, + }, + { + // Intersection types are always allowed + + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` const foo: Fruit & Fruit2 = Fruit.Apple; `, -}); - -valid.push({ - name: 'Assigning to a variable with a composition of binary flags', - code: ` + }, + { + code: ` enum Flag { Value1 = 1 << 0, Value2 = 1 << 1, } const flags = Flag.Value1 | Flag.Value2; - `, -}); - -valid.push({ - name: 'Assigning a number enum array to a variable with a number enum array', - code: - fruitEnumDefinition + - ` -declare let fruits: Fruit[]; -fruits = [Fruit.Apple, Fruit.Banana]; - `, -}); - -valid.push({ - name: 'Assigning a number enum array to a variable with a number array', - code: - fruitEnumDefinition + - ` -declare let numbers: number[]; -numbers = [Fruit.Apple, Fruit.Banana]; - `, -}); - -invalid.push({ - name: 'Assigning a number array to a variable with a number enum array', - code: - fruitEnumDefinition + - ` -declare let fruits: Fruit[]; -fruits = [0, 1]; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -valid.push({ - name: 'Assigning an empty array to a variable with a number enum array', - code: - fruitEnumDefinition + - ` -const fruitArray: Fruit[] = []; - `, -}); - -invalid.push({ - name: 'Assigning a mismatched number enum array', - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` -declare let fruits: Fruit[]; -fruits = [Fruit2.Apple2, Fruit2.Banana2]; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -valid.push({ - name: 'Assigning a new variable with a composition of bitflags', - code: - fruitEnumDefinition + - ` -const fruitFlags = Fruit.Apple | Fruit.Banana; - `, -}); - -strictEnumsRuleTester.run('strict-enums-assignment', rule, { - valid, - invalid, + `, + }, + { + code: + fruitEnumDefinition + + ` + declare let fruits: Fruit[]; + fruits = [Fruit.Apple, Fruit.Banana]; + `, + }, + { + code: + fruitEnumDefinition + + ` + declare let numbers: number[]; + numbers = [Fruit.Apple, Fruit.Banana]; + `, + }, + { + code: + fruitEnumDefinition + + ` + const fruitArray: Fruit[] = []; + `, + }, + { + code: + fruitEnumDefinition + + ` + const fruitFlags = Fruit.Apple | Fruit.Banana; + `, + }, + ], + invalid: [ + { + code: + fruitEnumDefinition + + ` + const fruit: Fruit = 0; + `, + errors: [{ messageId: 'mismatchedAssignment' }], + }, + { + code: + fruitEnumDefinition + + ` + let fruit = Fruit.Apple; + fruit = 1; + `, + errors: [{ messageId: 'mismatchedAssignment' }], + }, + { + code: + fruitEnumDefinition + + ` + const fruit: Fruit = Fruit; + `, + errors: [{ messageId: 'mismatchedAssignment' }], + }, + { + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` + const fruit: Fruit = Fruit2.Apple2; + `, + errors: [{ messageId: 'mismatchedAssignment' }], + }, + { + code: + fruitEnumDefinition + + ` + const fruit: Fruit | null = 0; + `, + errors: [{ messageId: 'mismatchedAssignment' }], + }, + { + code: + fruitEnumDefinition + + ` + let fruit: Fruit | null = null; + fruit = 0; + `, + errors: [{ messageId: 'mismatchedAssignment' }], + }, + { + code: + fruitEnumDefinition + + ` + declare const fruit: Fruit | number; + const fruitCopy: Fruit = fruit; + `, + errors: [{ messageId: 'mismatchedAssignment' }], + }, + { + code: + fruitEnumDefinition + + ` + declare let fruits: Fruit[]; + fruits = [0, 1]; + `, + errors: [{ messageId: 'mismatchedAssignment' }], + }, + { + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` + declare let fruits: Fruit[]; + fruits = [Fruit2.Apple2, Fruit2.Banana2]; + `, + errors: [{ messageId: 'mismatchedAssignment' }], + }, + ], }); diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts index d0934e624f7b..ef3a045d0ba3 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts @@ -1,9 +1,3 @@ -import type { - InvalidTestCase, - ValidTestCase, -} from '@typescript-eslint/utils/src/ts-eslint'; - -import type { MessageIds } from '../../../src/rules/strict-enums'; import rule from '../../../src/rules/strict-enums'; import { fruit2EnumDefinition, @@ -13,321 +7,153 @@ import { vegetableEnumDefinition, } from './strict-enums'; -const valid: ValidTestCase[] = []; -const invalid: InvalidTestCase[] = []; - -// ---------------------- -// COMPARISON TYPES TESTS -// ---------------------- - -valid.push({ - name: 'Comparing a number with a number', - code: - fruitEnumDefinition + - ` -1 === 2; - `, -}); - -valid.push({ - name: 'Comparing a number enum literal to any', - code: - fruitEnumDefinition + - ` -declare thing: any; -Fruit.Apple === thing; - `, -}); - -valid.push({ - name: 'Comparing a number enum literal to literal undefined', - code: - fruitEnumDefinition + - ` -Fruit.Apple === undefined; - `, -}); - -valid.push({ - name: 'Comparing a number enum literal to literal null', - code: - fruitEnumDefinition + - ` -Fruit.Apple === null; - `, -}); - -valid.push({ - name: 'Comparing a number enum literal with an enum literal of the same type', - code: - fruitEnumDefinition + - ` -Fruit.Apple === Fruit.Banana; - `, -}); - -valid.push({ - name: 'Comparing a number enum value with an enum literal of the same type', - code: - fruitEnumDefinition + - ` -const fruit = Fruit.Apple; -fruit === Fruit.Banana; - `, -}); - -valid.push({ - name: 'Comparing a string enum value with an enum literal of the same type', - code: - vegetableEnumDefinition + - ` -const vegetable = Vegetable.Lettuce; -vegetable === Vegetable.Carrot; - `, -}); - -valid.push({ - name: 'Comparing a number enum value with a value of the same type', - code: - fruitEnumDefinition + - ` -const fruit1 = Fruit.Apple; -const fruit2 = Fruit.Banana; -fruit1 === fruit2; - `, -}); - -valid.push({ - name: 'Comparing a string enum value with a value of the same type', - code: - vegetableEnumDefinition + - ` -const vegetable1 = Vegetable.Lettuce; -const vegetable2 = Vegetable.Carrot; -vegetable1 === vegetable2; - `, -}); - -invalid.push({ - name: 'Comparing a number enum literal with a number literal', - code: - fruitEnumDefinition + - ` -Fruit.Apple === 1; - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a string enum literal with a string literal', - code: - vegetableEnumDefinition + - ` -Vegetable.Lettuce === 'carrot'; - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a number literal with a number enum literal', - code: - fruitEnumDefinition + - ` -1 === Fruit.Apple; - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a string literal with a string enum literal', - code: - vegetableEnumDefinition + - ` -'carrot' === Vegetable.Lettuce; - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a number enum value with a number literal', - code: - fruitEnumDefinition + - ` -const fruit = Fruit.Apple; -fruit === 1; - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a string enum value with a string literal', - code: - vegetableEnumDefinition + - ` -const vegetable = Vegetable.Lettuce; -vegetable === 'carrot'; - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a number literal with an enum value', - code: - fruitEnumDefinition + - ` -const fruit = Fruit.Apple; -1 === fruit; - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a string literal with an enum value', - code: - vegetableEnumDefinition + - ` -const vegetable = Vegetable.Lettuce; -'carrot' === vegetable; - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a number enum literal with a different enum literal', - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` -Fruit.Apple === Fruit2.Apple2; - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a string enum literal with a different enum literal', - code: - vegetableEnumDefinition + - vegetable2EnumDefinition + - ` -Vegetable.Lettuce === Vegetable2.Lettuce2; - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a number enum value with a different enum literal', - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` -const fruit = Fruit.Apple; -fruit === Fruit2.Apple2; - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -invalid.push({ - name: 'Comparing a string enum value with a different enum literal', - code: - vegetableEnumDefinition + - vegetable2EnumDefinition + - ` -const vegetable = Vegetable.Lettuce; -vegetable === Vegetable2.Lettuce2; - `, - errors: [{ messageId: 'mismatchedComparison' }], -}); - -valid.push({ - name: 'Comparing a generic enum extension value with a number enum literal', - code: - fruitEnumDefinition + - ` -class FruitClass { - constructor(type: FruitType) { - if (type === Fruit.Apple) {} - } -} - `, -}); - -valid.push({ - name: 'Comparing a number union to a number union', - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` -declare const left: number | Fruit; -declare const right: number | Fruit2; -left === right; - `, -}); - -valid.push({ - name: 'Comparing a string union to a string union', - code: - vegetableEnumDefinition + - vegetable2EnumDefinition + - ` -declare const left: string | Vegetable; -declare const right: string | Vegetable2; -left === right; - `, -}); - -valid.push({ - name: 'Comparing a string enum literal to an intersection with a string (simple)', - code: - vegetableEnumDefinition + - ` -type WeirdString = string & { __someBrand: void; }; -declare weirdString: WeirdString; -Vegetable.Lettuce === weirdString; - `, -}); - -valid.push({ - name: 'Comparing a string literal to an intersection with a string (complicated)', - code: - vegetableEnumDefinition + - ` -enum InternalSymbolName { - Foo = "foo", - Bar = "bar", -} -type __String = - | (string & { __escapedIdentifier: void; }) - | (void & { __escapedIdentifier: void; }) - | InternalSymbolName; -declare const weirdString: __String; -weirdString === 'someArbitraryValue'; - `, -}); - -valid.push({ - name: 'Comparing using the in operator', - code: - vegetableEnumDefinition + - ` -const foo = {}; -const vegetable = Vegetable.Lettuce; -vegetable in foo; - `, -}); - -valid.push({ - name: 'Comparing using a type of enum | boolean', - code: - fruitEnumDefinition + - ` -declare const fruitOrBoolean: Fruit | boolean; -fruitOrBoolean === true; - `, -}); - -valid.push({ - name: "Comparing various valid types (Brad's test)", - code: ` +strictEnumsRuleTester.run('strict-enums-comparison', rule, { + valid: [ + { + code: + fruitEnumDefinition + + ` + 1 === 2; + `, + }, + { + code: + fruitEnumDefinition + + ` + declare thing: any; + Fruit.Apple === thing; + `, + }, + { + code: + fruitEnumDefinition + + ` + Fruit.Apple === undefined; + `, + }, + { + code: + fruitEnumDefinition + + ` + Fruit.Apple === null; + `, + }, + { + code: + fruitEnumDefinition + + ` + Fruit.Apple === Fruit.Banana; + `, + }, + { + code: + fruitEnumDefinition + + ` + const fruit = Fruit.Apple; + fruit === Fruit.Banana; + `, + }, + { + code: + vegetableEnumDefinition + + ` + const vegetable = Vegetable.Lettuce; + vegetable === Vegetable.Carrot; + `, + }, + { + code: + fruitEnumDefinition + + ` + const fruit1 = Fruit.Apple; + const fruit2 = Fruit.Banana; + fruit1 === fruit2; + `, + }, + { + code: + vegetableEnumDefinition + + ` + const vegetable1 = Vegetable.Lettuce; + const vegetable2 = Vegetable.Carrot; + vegetable1 === vegetable2; + `, + }, + { + code: + fruitEnumDefinition + + ` + class FruitClass { + constructor(type: FruitType) { + if (type === Fruit.Apple) {} + } + } + `, + }, + { + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` + declare const left: number | Fruit; + declare const right: number | Fruit2; + left === right; + `, + }, + { + code: + vegetableEnumDefinition + + vegetable2EnumDefinition + + ` + declare const left: string | Vegetable; + declare const right: string | Vegetable2; + left === right; + `, + }, + { + code: + vegetableEnumDefinition + + ` + type WeirdString = string & { __someBrand: void; }; + declare weirdString: WeirdString; + Vegetable.Lettuce === weirdString; + `, + }, + { + code: + vegetableEnumDefinition + + ` + enum InternalSymbolName { + Foo = "foo", + Bar = "bar", + } + type __String = + | (string & { __escapedIdentifier: void; }) + | (void & { __escapedIdentifier: void; }) + | InternalSymbolName; + declare const weirdString: __String; + weirdString === 'someArbitraryValue'; + `, + }, + { + code: + vegetableEnumDefinition + + ` + const foo = {}; + const vegetable = Vegetable.Lettuce; + vegetable in foo; + `, + }, + { + code: + fruitEnumDefinition + + ` + declare const fruitOrBoolean: Fruit | boolean; + fruitOrBoolean === true; + `, + }, + { + code: ` enum Str { A = 'a', } @@ -358,7 +184,6 @@ mixedOrStringOrNumber === 1; // following are all ignored because the value can never be an enum value str === 1; -/* num === 'a'; str === {}; num === {}; @@ -369,13 +194,118 @@ mixed === true; str === someFunction; num === someFunction; mixed === someFunction; -*/ - `, -}); - -invalid.push({ - name: "Comparing various invalid types (Brad's test)", - code: ` + `, + }, + ], + invalid: [ + { + code: + fruitEnumDefinition + + ` + Fruit.Apple === 1; + `, + errors: [{ messageId: 'mismatchedComparison' }], + }, + { + code: + vegetableEnumDefinition + + ` + Vegetable.Lettuce === 'carrot'; + `, + errors: [{ messageId: 'mismatchedComparison' }], + }, + { + code: + fruitEnumDefinition + + ` + 1 === Fruit.Apple; + `, + errors: [{ messageId: 'mismatchedComparison' }], + }, + { + code: + vegetableEnumDefinition + + ` + 'carrot' === Vegetable.Lettuce; + `, + errors: [{ messageId: 'mismatchedComparison' }], + }, + { + code: + fruitEnumDefinition + + ` + const fruit = Fruit.Apple; + fruit === 1; + `, + errors: [{ messageId: 'mismatchedComparison' }], + }, + { + code: + vegetableEnumDefinition + + ` + const vegetable = Vegetable.Lettuce; + vegetable === 'carrot'; + `, + errors: [{ messageId: 'mismatchedComparison' }], + }, + { + code: + fruitEnumDefinition + + ` + const fruit = Fruit.Apple; + 1 === fruit; + `, + errors: [{ messageId: 'mismatchedComparison' }], + }, + { + code: + vegetableEnumDefinition + + ` + const vegetable = Vegetable.Lettuce; + 'carrot' === vegetable; + `, + errors: [{ messageId: 'mismatchedComparison' }], + }, + { + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` + Fruit.Apple === Fruit2.Apple2; + `, + errors: [{ messageId: 'mismatchedComparison' }], + }, + { + code: + vegetableEnumDefinition + + vegetable2EnumDefinition + + ` + Vegetable.Lettuce === Vegetable2.Lettuce2; + `, + errors: [{ messageId: 'mismatchedComparison' }], + }, + { + code: + fruitEnumDefinition + + fruit2EnumDefinition + + ` + const fruit = Fruit.Apple; + fruit === Fruit2.Apple2; + `, + errors: [{ messageId: 'mismatchedComparison' }], + }, + { + code: + vegetableEnumDefinition + + vegetable2EnumDefinition + + ` + const vegetable = Vegetable.Lettuce; + vegetable === Vegetable2.Lettuce2; + `, + errors: [{ messageId: 'mismatchedComparison' }], + }, + { + code: ` enum Str { A = 'a', } @@ -396,16 +326,13 @@ str === 'a'; num === 1; mixed === 'a'; mixed === 1; - `, - errors: [ - { messageId: 'mismatchedComparison' }, - { messageId: 'mismatchedComparison' }, - { messageId: 'mismatchedComparison' }, - { messageId: 'mismatchedComparison' }, + `, + errors: [ + { messageId: 'mismatchedComparison' }, + { messageId: 'mismatchedComparison' }, + { messageId: 'mismatchedComparison' }, + { messageId: 'mismatchedComparison' }, + ], + }, ], }); - -strictEnumsRuleTester.run('strict-enums-comparison', rule, { - valid, - invalid, -}); diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts index 425e508f4328..c594c00d2453 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts @@ -1,9 +1,3 @@ -import type { - InvalidTestCase, - ValidTestCase, -} from '@typescript-eslint/utils/src/ts-eslint'; - -import type { MessageIds } from '../../../src/rules/strict-enums'; import rule from '../../../src/rules/strict-enums'; import { fruitEnumDefinition, @@ -11,9 +5,6 @@ import { vegetableEnumDefinition, } from './strict-enums'; -const valid: ValidTestCase[] = []; -const invalid: InvalidTestCase[] = []; - /** A function that takes a number enum. */ const fruitFunctionDefinition = fruitEnumDefinition + @@ -21,1000 +12,901 @@ const fruitFunctionDefinition = function useFruit(fruit: Fruit) {} `; -valid.push({ - name: 'Using a number enum literal on a non-existent function', - code: ` -useFruit(0); - `, -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes a number enum', - code: - fruitFunctionDefinition + - ` -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value on a function that takes a number enum', - code: - fruitFunctionDefinition + - ` -declare const fruit: Fruit.Apple; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes a number enum', - code: - fruitFunctionDefinition + - ` -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a matching number enum literal on a function that takes an enum literal', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple) {} -useFruit(Fruit.Apple); - `, -}); - -/** - * The TypeScript compiler will correctly handle this case, so the lint rule - * does not need to care. - */ -valid.push({ - name: 'Using a non-matching number enum literal on a function that takes an enum literal', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple) {} -useFruit(Fruit.Banana); - `, -}); - -valid.push({ - name: 'Using a matching number enum value on a function that takes an enum literal', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple) {} -declare const fruit: Fruit.Apple; -useFruit(fruit); - `, -}); - -/** - * The TypeScript compiler will correctly handle this case, so the lint rule - * does not need to care. - */ -valid.push({ - name: 'Using a non-matching number enum value on a function that takes an enum literal', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple) {} -declare const fruit: Fruit.Banana; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes an enum literal', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes a number enum with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit = Fruit.Apple) {} -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value on a function that takes a number enum with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit = Fruit.Apple) {} -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes a number enum with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit = Fruit.Apple) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes a number enum literal with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value on a function that takes a number enum literal with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes a number enum literal with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes a number enum | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null) {} -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value on a function that takes a number enum | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null) {} -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -valid.push({ - name: 'Using a null literal on a function that takes a number enum | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null) {} -useFruit(null); - `, -}); - -valid.push({ - name: 'Using a null value on a function that takes a number enum | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null) {} -const fruit = null; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes a number enum | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes a number enum | null with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null = Fruit.Apple) {} -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value on a function that takes a number enum | null with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null = Fruit.Apple) {} -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -valid.push({ - name: 'Using a null literal on a function that takes a number enum | null with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null = Fruit.Apple) {} -useFruit(null); - `, -}); - -valid.push({ - name: 'Using a null value on a function that takes a number enum | null with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null = Fruit.Apple) {} -const fruit = null; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes a number enum | null with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit | null = Fruit.Apple) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes a number enum literal | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null) {} -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value on a function that takes a number enum literal | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null) {} -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -valid.push({ - name: 'Using a null literal on a function that takes a number enum literal | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null) {} -useFruit(null); - `, -}); - -valid.push({ - name: 'Using a null value on a function that takes a number enum literal | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null) {} -const fruit = null; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes a number enum literal | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes a number enum literal | null with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value on a function that takes a number enum literal | null with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -valid.push({ - name: 'Using a null literal on a function that takes a number enum literal | null with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} -useFruit(null); - `, -}); - -valid.push({ - name: 'Using a null value on a function that takes a number enum literal | null with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} -const fruit = null; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes a number enum literal | null with a default argument', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes a number enum literal | number enum literal | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum value on a function that takes a number enum literal | number enum literal | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} -const fruit = Fruit.Apple; -useFruit(fruit); - `, -}); - -valid.push({ - name: 'Using a null literal on a function that takes a number enum literal | number enum literal | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} -useFruit(null); - `, -}); - -valid.push({ - name: 'Using a null value on a function that takes a number enum literal | number enum literal | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} -const fruit = null; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes a number enum literal | number enum literal | null', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using an enum from a composition type on a function that takes a number enum', - code: - fruitEnumDefinition + - ` -interface BaseNode { - type: Fruit; -} - -interface AppleNode extends BaseNode { - type: Fruit.Apple; - apple: number; -} - -interface BananaNode extends BaseNode { - type: Fruit.Apple; - banana: Number; -} - -type Node = AppleNode | BananaNode; - -const fruitNodesSet = new Set([ - Fruit.Apple, - Fruit.Banana, -]); - -const appleNode: AppleNode = { - type: Fruit.Apple, - apple: 1, -}; - -fruitNodesSet.has(appleNode.type); - `, -}); - -valid.push({ - name: 'Using an enum number literal in a Set method', - code: - fruitEnumDefinition + - ` -const fruitSet = new Set([ - Fruit.Apple, - Fruit.Banana, -]); - -fruitSet.has(Fruit.Apple); - `, -}); - -invalid.push({ - name: 'Using a number literal in a Set method', - code: - fruitEnumDefinition + - ` -const fruitSet = new Set([ - Fruit.Apple, - Fruit.Banana, -]); - -fruitSet.has(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a partial union type on a function that takes a number enum', - code: - fruitFunctionDefinition + - ` -declare const fruitUnion: Fruit.Apple | Fruit.Banana; -useFruit(fruitUnion); -`, -}); - -valid.push({ - name: 'Using a partial union type on a function that takes a partial union', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | Fruit.Banana) {} -declare const fruitUnion: Fruit.Apple | Fruit.Banana; -useFruit(fruitUnion); -`, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes a partial union', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | Fruit.Banana) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a full enum union on a function that takes a number enum', - code: - fruitFunctionDefinition + - ` -declare const fruitUnion: Fruit.Apple | Fruit.Banana | Fruit.Pear; -useFruit(fruitUnion); -`, -}); - -valid.push({ - name: 'Using a full enum union on a function that takes a full enum union', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | Fruit.Banana | Fruit.Pear) {} -declare const fruitUnion: Fruit.Apple | Fruit.Banana | Fruit.Pear; -useFruit(fruitUnion); -`, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes a full enum union', - code: - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit.Apple | Fruit.Banana | Fruit.Pear) {} +strictEnumsRuleTester.run('strict-enums-functions', rule, { + valid: [ + { + code: ` useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a partial enum union on a function that takes a number enum (from a type narrowing switch statement)', - code: - fruitFunctionDefinition + - ` -declare const fruit: Fruit; -switch (fruit) { - case Fruit.Apple: - case Fruit.Banana: { + `, + }, + + { + code: + fruitFunctionDefinition + + ` + useFruit(Fruit.Apple); + `, + }, + + { + code: + fruitFunctionDefinition + + ` + declare const fruit: Fruit.Apple; useFruit(fruit); - } -} -`, -}); - -valid.push({ - name: 'Using a number enum on a function that takes an extension type', - code: - fruitEnumDefinition + - ` -function useFruit(fruitType: FruitType) {} -useFruit(Fruit.Apple); -`, -}); - -valid.push({ - name: 'Using a number literal on a function that takes an extension type', - code: - fruitEnumDefinition + - ` -function useFruit(fruitType: FruitType) {} -useFruit(0); -`, -}); - -valid.push({ - name: 'Using a number enum on a function that takes an enum extension type', - code: - fruitEnumDefinition + - ` -function useFruit(fruitType: FruitType) {} -useFruit(Fruit.Apple); -`, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes an enum extension type', - code: - fruitEnumDefinition + - ` -function useFruit(fruitType: FruitType) {} -useFruit(0); -`, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum on a function that takes an enum extension type', - code: - fruitEnumDefinition + - ` -class FruitClass { - constructor(type: FruitType) {} - useFruit(type: FruitType) {} -} -const fruitClass = new FruitClass(Fruit.Apple); -fruitClass.useFruit(Fruit.Apple); -`, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes an enum extension type', - code: - fruitEnumDefinition + - ` -class FruitClass { - constructor(type: FruitType) {} - useFruit(type: FruitType) {} -} -const fruitClass = new FruitClass(0); -fruitClass.useFruit(0); - `, - errors: [ - { messageId: 'mismatchedFunctionArgument' }, - { messageId: 'mismatchedFunctionArgument' }, - ], -}); - -valid.push({ - name: 'Using a number array on a function that takes a number array', - code: - fruitEnumDefinition + - ` -function useNumbers(numberArray: number[]) {} -useNumbers([0, 1]); - `, -}); - -valid.push({ - name: 'Using a number enum array on a function that takes a number enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitArray: Fruit[]) {} -useFruit([Fruit.Apple, Fruit.Banana]); - `, -}); - -invalid.push({ - name: 'Using a number array on a function that takes a number enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitArray: Fruit[]) {} -useFruit([0, 1]); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -invalid.push({ - name: 'Using a mixed array on a function that takes a number enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitArray: Fruit[]) {} -useFruit([Fruit.Apple, 1]); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number literal on a function that takes a number', - code: ` -function useNumber(num: number) {} -useNumber(0); - `, -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes a number', - code: - fruitEnumDefinition + - ` -function useNumber(num: number) {} -useNumber(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a string literal on a function that takes a string', - code: - vegetableEnumDefinition + - ` -function useString(str: string) {} -useString('lettuce'); - `, -}); - -valid.push({ - name: 'Using a string enum literal on a function that takes a string', - code: - vegetableEnumDefinition + - ` -function useString(str: string) {} -useString(Vegetable.Lettuce); - `, -}); - -valid.push({ - name: 'Using a number literal on a function that takes any', - code: ` -function useAnything(something: any) {} -useAnything(0); - `, -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes any', - code: - fruitEnumDefinition + - ` -function useAnything(something: any) {} -useAnything(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number literal on a function that takes unknown', - code: ` -function useUnknown(something: unknown) {} -useUnknown(0); - `, -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes unknown', - code: - fruitEnumDefinition + - ` -function useUnknown(something: unknown) {} -useUnknown(Fruit.Apple); - `, -}); - -invalid.push({ - name: 'Using a number literal on a function that takes enum | enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a function that takes enum | enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} -useFruit(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum array on a function that takes enum | enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} -useFruit([Fruit.Apple, Fruit.Banana]); - `, -}); - -valid.push({ - name: 'Using a enum | enum array union on a function that takes enum | enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} -declare const fruit: Fruit | Fruit[]; -useFruit(fruit); - `, -}); - -invalid.push({ - name: 'Using a number array on a function that takes enum | enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} -useFruit([0, 1]); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number on a function that takes number | enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitOrFruitArray: number | Fruit[]) {} -useFruit(0); - `, -}); - -valid.push({ - name: 'Using an enum array on a function that takes number | enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitOrFruitArray: number | Fruit[]) {} -useFruit([Fruit.Apple, Fruit.Banana]); - `, -}); - -invalid.push({ - name: 'Using a number array on a function that takes number | enum array', - code: - fruitEnumDefinition + - ` -function useFruit(fruitOrFruitArray: number | Fruit[]) {} -useFruit([0, 1]); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -invalid.push({ - name: 'Using a number literal on a variadic function', - code: - fruitEnumDefinition + - ` -function useFruit(...fruits: Fruit[]) {} -useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a variadic function', - code: - fruitEnumDefinition + - ` -function useFruit(...fruits: Fruit[]) {} -useFruit(Fruit.Apple); -useFruit(Fruit.Apple, Fruit.Banana); - `, -}); - -invalid.push({ - name: 'Using a number enum literal and a number literal on a variadic function', - code: - fruitEnumDefinition + - ` -function useFruit(...fruits: Fruit[]) {} -useFruit(Fruit.Apple, 0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a generic function with a default generic type that is unspecified as any', - code: - fruitEnumDefinition + - ` -function toEqual(expected: E): void {} -toEqual(Fruit.Apple); - `, -}); - -valid.push({ - name: 'Using a number enum literal on a generic function with a default generic type that is unspecified as a number enum', - code: - fruitEnumDefinition + - ` -function toEqual(expected: E): void {} -toEqual(Fruit.Apple); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple) {} + useFruit(Fruit.Apple); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple) {} + useFruit(Fruit.Banana); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple) {} + declare const fruit: Fruit.Apple; + useFruit(fruit); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple) {} + declare const fruit: Fruit.Banana; + useFruit(fruit); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit = Fruit.Apple) {} + useFruit(Fruit.Apple); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit = Fruit.Apple) {} + const fruit = Fruit.Apple; + useFruit(fruit); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} + useFruit(Fruit.Apple); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} + const fruit = Fruit.Apple; + useFruit(fruit); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit | null) {} + useFruit(Fruit.Apple); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit | null) {} + const fruit = Fruit.Apple; + useFruit(fruit); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit | null) {} + useFruit(null); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit | null) {} + const fruit = null; + useFruit(fruit); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit | null = Fruit.Apple) {} + useFruit(Fruit.Apple); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit | null = Fruit.Apple) {} + const fruit = Fruit.Apple; + useFruit(fruit); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit | null = Fruit.Apple) {} + useFruit(null); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit | null = Fruit.Apple) {} + const fruit = null; + useFruit(fruit); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple | null) {} + useFruit(Fruit.Apple); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple | null) {} + const fruit = Fruit.Apple; + useFruit(fruit); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple | null) {} + useFruit(null); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple | null) {} + const fruit = null; + useFruit(fruit); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} + useFruit(Fruit.Apple); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} + const fruit = Fruit.Apple; + useFruit(fruit); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} + useFruit(null); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} + const fruit = null; + useFruit(fruit); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} + useFruit(Fruit.Apple); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} + const fruit = Fruit.Apple; + useFruit(fruit); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} + useFruit(null); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} + const fruit = null; + useFruit(fruit); + `, + }, + + { + code: + fruitEnumDefinition + + ` + interface BaseNode { + type: Fruit; + } + + interface AppleNode extends BaseNode { + type: Fruit.Apple; + apple: number; + } + + interface BananaNode extends BaseNode { + type: Fruit.Apple; + banana: Number; + } + + type Node = AppleNode | BananaNode; + + const fruitNodesSet = new Set([ + Fruit.Apple, + Fruit.Banana, + ]); + + const appleNode: AppleNode = { + type: Fruit.Apple, + apple: 1, + }; + + fruitNodesSet.has(appleNode.type); + `, + }, + + { + code: + fruitEnumDefinition + + ` + const fruitSet = new Set([ + Fruit.Apple, + Fruit.Banana, + ]); + + fruitSet.has(Fruit.Apple); + `, + }, + + { + code: + fruitFunctionDefinition + + ` + declare const fruitUnion: Fruit.Apple | Fruit.Banana; + useFruit(fruitUnion); `, -}); - -valid.push({ - name: 'Using a number enum literal on a generic function with a default generic type that is specified as any', - code: - fruitEnumDefinition + - ` -function toEqual(expected: E): void {} -toEqual(Fruit.Apple); + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple | Fruit.Banana) {} + declare const fruitUnion: Fruit.Apple | Fruit.Banana; + useFruit(fruitUnion); `, -}); - -valid.push({ - name: 'Using a number enum literal on a generic function with a default generic type that is specified as a number enum', - code: - fruitEnumDefinition + - ` -function toEqual(expected: E): void {} -toEqual(Fruit.Apple); + }, + + { + code: + fruitFunctionDefinition + + ` + declare const fruitUnion: Fruit.Apple | Fruit.Banana | Fruit.Pear; + useFruit(fruitUnion); `, -}); - -invalid.push({ - name: 'Using a number literal on a generic function with a default generic type that is specified as a number enum', - code: - fruitEnumDefinition + - ` -function toEqual(expected: E): void {} -toEqual(0); + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple | Fruit.Banana | Fruit.Pear) {} + declare const fruitUnion: Fruit.Apple | Fruit.Banana | Fruit.Pear; + useFruit(fruitUnion); `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using a number enum literal on a generic function with a default generic type that is unspecified as any + extra arg', - code: - fruitEnumDefinition + - ` -function toEqual(arg1: number, expected: E): void {} -toEqual(0, Fruit.Apple); + }, + + { + code: + fruitFunctionDefinition + + ` + declare const fruit: Fruit; + switch (fruit) { + case Fruit.Apple: + case Fruit.Banana: { + useFruit(fruit); + } + } `, -}); - -valid.push({ - name: 'Using a number enum literal on a generic function with a default generic type that is unspecified as a number enum + extra arg', - code: - fruitEnumDefinition + - ` -function toEqual(arg1: number, expected: E): void {} -toEqual(0, Fruit.Apple); + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruitType: FruitType) {} + useFruit(Fruit.Apple); `, -}); - -valid.push({ - name: 'Using a number enum literal on a generic function with a default generic type that is specified as any + extra arg', - code: - fruitEnumDefinition + - ` -function toEqual(arg1: number, expected: E): void {} -toEqual(0, Fruit.Apple); + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruitType: FruitType) {} + useFruit(0); `, -}); - -valid.push({ - name: 'Using a number enum literal on a generic function with a default generic type that is specified as a number enum + extra arg', - code: - fruitEnumDefinition + - ` -function toEqual(arg1: number, expected: E): void {} -toEqual(0, Fruit.Apple); + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruitType: FruitType) {} + useFruit(Fruit.Apple); `, -}); - -invalid.push({ - name: 'Using a number literal on a generic function with a default generic type that is specified as a number enum + extra arg', - code: - fruitEnumDefinition + - ` -function toEqual(arg1: number, expected: E): void {} -toEqual(0, 0); + }, + + { + code: + fruitEnumDefinition + + ` + class FruitClass { + constructor(type: FruitType) {} + useFruit(type: FruitType) {} + } + const fruitClass = new FruitClass(Fruit.Apple); + fruitClass.useFruit(Fruit.Apple); `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], -}); - -valid.push({ - name: 'Using JSON.stringify', - code: ` + }, + + { + code: + fruitEnumDefinition + + ` + function useNumbers(numberArray: number[]) {} + useNumbers([0, 1]); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruitArray: Fruit[]) {} + useFruit([Fruit.Apple, Fruit.Banana]); + `, + }, + + { + code: ` +function useNumber(num: number) {} +useNumber(0); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useNumber(num: number) {} + useNumber(Fruit.Apple); + `, + }, + + { + code: + vegetableEnumDefinition + + ` + function useString(str: string) {} + useString('lettuce'); + `, + }, + + { + code: + vegetableEnumDefinition + + ` + function useString(str: string) {} + useString(Vegetable.Lettuce); + `, + }, + + { + code: ` +function useAnything(something: any) {} +useAnything(0); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useAnything(something: any) {} + useAnything(Fruit.Apple); + `, + }, + + { + code: ` +function useUnknown(something: unknown) {} +useUnknown(0); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useUnknown(something: unknown) {} + useUnknown(Fruit.Apple); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} + useFruit(Fruit.Apple); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} + useFruit([Fruit.Apple, Fruit.Banana]); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} + declare const fruit: Fruit | Fruit[]; + useFruit(fruit); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruitOrFruitArray: number | Fruit[]) {} + useFruit(0); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruitOrFruitArray: number | Fruit[]) {} + useFruit([Fruit.Apple, Fruit.Banana]); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(...fruits: Fruit[]) {} + useFruit(Fruit.Apple); + useFruit(Fruit.Apple, Fruit.Banana); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function toEqual(expected: E): void {} + toEqual(Fruit.Apple); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function toEqual(expected: E): void {} + toEqual(Fruit.Apple); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function toEqual(expected: E): void {} + toEqual(Fruit.Apple); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function toEqual(expected: E): void {} + toEqual(Fruit.Apple); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function toEqual(arg1: number, expected: E): void {} + toEqual(0, Fruit.Apple); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function toEqual(arg1: number, expected: E): void {} + toEqual(0, Fruit.Apple); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function toEqual(arg1: number, expected: E): void {} + toEqual(0, Fruit.Apple); + `, + }, + + { + code: + fruitEnumDefinition + + ` + function toEqual(arg1: number, expected: E): void {} + toEqual(0, Fruit.Apple); + `, + }, + + { + code: ` JSON.stringify({}, (_, value: unknown) => value ?? undefined, 2); - `, -}); + `, + }, -valid.push({ - name: 'Using flatten', - code: ` + { + code: ` function flatten(arr: T[][]): T[] { return arr.reduce((acc, a) => acc.concat(a), []); } - `, -}); - -strictEnumsRuleTester.run('strict-enums-functions', rule, { - valid, - invalid, + `, + }, + ], + invalid: [ + { + code: + fruitFunctionDefinition + + ` + useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple) {} + useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit = Fruit.Apple) {} + useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} + useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit | null) {} + useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit | null = Fruit.Apple) {} + useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple | null) {} + useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} + useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} + useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + const fruitSet = new Set([ + Fruit.Apple, + Fruit.Banana, + ]); + + fruitSet.has(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple | Fruit.Banana) {} + useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruit: Fruit.Apple | Fruit.Banana | Fruit.Pear) {} + useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruitType: FruitType) {} + useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + class FruitClass { + constructor(type: FruitType) {} + useFruit(type: FruitType) {} + } + const fruitClass = new FruitClass(0); + fruitClass.useFruit(0); + `, + errors: [ + { messageId: 'mismatchedFunctionArgument' }, + { messageId: 'mismatchedFunctionArgument' }, + ], + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruitArray: Fruit[]) {} + useFruit([0, 1]); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruitArray: Fruit[]) {} + useFruit([Fruit.Apple, 1]); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} + useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} + useFruit([0, 1]); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(fruitOrFruitArray: number | Fruit[]) {} + useFruit([0, 1]); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(...fruits: Fruit[]) {} + useFruit(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + function useFruit(...fruits: Fruit[]) {} + useFruit(Fruit.Apple, 0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + function toEqual(expected: E): void {} + toEqual(0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + + { + code: + fruitEnumDefinition + + ` + function toEqual(arg1: number, expected: E): void {} + toEqual(0, 0); + `, + errors: [{ messageId: 'mismatchedFunctionArgument' }], + }, + ], }); diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-incrementing.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-incrementing.test.ts index 9da3927ce726..bb11727230aa 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-incrementing.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-incrementing.test.ts @@ -1,142 +1,111 @@ -import type { - InvalidTestCase, - ValidTestCase, -} from '@typescript-eslint/utils/src/ts-eslint'; - -import type { MessageIds } from '../../../src/rules/strict-enums'; import rule from '../../../src/rules/strict-enums'; import { fruitEnumDefinition, strictEnumsRuleTester } from './strict-enums'; -const valid: ValidTestCase[] = []; -const invalid: InvalidTestCase[] = []; - -valid.push({ - name: 'Incrementing a number (postfix)', - code: - fruitEnumDefinition + - ` +strictEnumsRuleTester.run('strict-enums-incrementing', rule, { + valid: [ + { + code: + fruitEnumDefinition + + ` let fruit = 0; fruit++; `, -}); - -invalid.push({ - name: 'Incrementing a number enum value (postfix)', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Apple; -fruit++; - `, - errors: [{ messageId: 'incorrectIncrement' }], -}); - -valid.push({ - name: 'Decrementing a number (postfix)', - code: - fruitEnumDefinition + - ` + }, + { + code: + fruitEnumDefinition + + ` let fruit = 1; fruit--; `, -}); - -invalid.push({ - name: 'Decrementing a number enum value (postfix)', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Banana; -fruit--; - `, - errors: [{ messageId: 'incorrectIncrement' }], -}); - -valid.push({ - name: 'Incrementing a number (prefix)', - code: - fruitEnumDefinition + - ` + }, + { + code: + fruitEnumDefinition + + ` let fruit = 0; ++fruit; `, -}); - -invalid.push({ - name: 'Incrementing a number enum value (prefix)', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Apple; -++fruit; - `, - errors: [{ messageId: 'incorrectIncrement' }], -}); - -valid.push({ - name: 'Decrementing a number (prefix)', - code: - fruitEnumDefinition + - ` + }, + { + code: + fruitEnumDefinition + + ` let fruit = 1; --fruit `, -}); - -invalid.push({ - name: 'Decrementing a number enum value (prefix)', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Banana; ---fruit; - `, - errors: [{ messageId: 'incorrectIncrement' }], -}); - -valid.push({ - name: 'Incrementing a number (assignment operator)', - code: - fruitEnumDefinition + - ` + }, + { + code: + fruitEnumDefinition + + ` let fruit = 0; fruit += 1; `, -}); - -invalid.push({ - name: 'Incrementing a number enum value (assignment operator)', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Apple; -fruit += 1; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -valid.push({ - name: 'Decrementing a number (assignment operator)', - code: - fruitEnumDefinition + - ` + }, + { + code: + fruitEnumDefinition + + ` let fruit = 1; fruit -= 1; `, -}); - -invalid.push({ - name: 'Decrementing a number enum value (assignment operator)', - code: - fruitEnumDefinition + - ` -let fruit = Fruit.Banana; -fruit -= 1; - `, - errors: [{ messageId: 'mismatchedAssignment' }], -}); - -strictEnumsRuleTester.run('strict-enums-incrementing', rule, { - valid, - invalid, + }, + ], + invalid: [ + { + code: + fruitEnumDefinition + + ` + let fruit = Fruit.Apple; + fruit++; + `, + errors: [{ messageId: 'incorrectIncrement' }], + }, + { + code: + fruitEnumDefinition + + ` + let fruit = Fruit.Banana; + fruit--; + `, + errors: [{ messageId: 'incorrectIncrement' }], + }, + { + code: + fruitEnumDefinition + + ` + let fruit = Fruit.Apple; + ++fruit; + `, + errors: [{ messageId: 'incorrectIncrement' }], + }, + { + code: + fruitEnumDefinition + + ` + let fruit = Fruit.Banana; + --fruit; + `, + errors: [{ messageId: 'incorrectIncrement' }], + }, + { + code: + fruitEnumDefinition + + ` + let fruit = Fruit.Apple; + fruit += 1; + `, + errors: [{ messageId: 'mismatchedAssignment' }], + }, + { + code: + fruitEnumDefinition + + ` + let fruit = Fruit.Banana; + fruit -= 1; + `, + errors: [{ messageId: 'mismatchedAssignment' }], + }, + ], }); From 4706e4f67d65ebb3b879353066d338ec7f3b43b4 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Fri, 25 Nov 2022 06:04:36 -0500 Subject: [PATCH 76/88] Simplified the rule a whole bunch --- .../eslint-plugin/src/rules/strict-enums.ts | 360 ++++++------------ packages/eslint-plugin/src/util/misc.ts | 5 - .../{strict-enums.ts => shared.ts} | 0 .../strict-enums-assignment.test.ts | 2 +- .../strict-enums-comparison.test.ts | 2 +- .../strict-enums-functions.test.ts | 2 +- .../strict-enums-incrementing.test.ts | 2 +- 7 files changed, 116 insertions(+), 257 deletions(-) rename packages/eslint-plugin/tests/rules/strict-enums/{strict-enums.ts => shared.ts} (100%) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index e929a094c5ab..4da7d9e4b89e 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -44,6 +44,73 @@ export type MessageIds = | 'mismatchedComparison' | 'mismatchedFunctionArgument'; +/** + * See the comment for the `EnumKind` enum. + */ +function getEnumKind(type: ts.Type): EnumKind { + if (!util.isTypeFlagSet(type, ts.TypeFlags.EnumLike)) { + return EnumKind.NON_ENUM; + } + + const isStringLiteral = util.isTypeFlagSet(type, ts.TypeFlags.StringLiteral); + const isNumberLiteral = util.isTypeFlagSet(type, ts.TypeFlags.NumberLiteral); + + if (isStringLiteral && !isNumberLiteral) { + return EnumKind.HAS_STRING_VALUES; + } + + if (isNumberLiteral && !isStringLiteral) { + return EnumKind.HAS_NUMBER_VALUES; + } + + throw new Error( + 'Failed to derive the type of enum, since it did not have string values or number values.', + ); +} + +/** + * Returns a set containing the single `EnumKind` (if it is not a union), or + * a set containing N `EnumKind` (if it is a union). + */ +function getEnumKinds(type: ts.Type): Set { + if (type.isUnion()) { + return new Set(tsutils.unionTypeParts(type).map(getEnumKind)); + } + + return new Set([getEnumKind(type)]); +} + +function setHasAnyElementFromSet(set1: Set, set2: Set): boolean { + for (const value of set2.values()) { + if (set1.has(value)) { + return true; + } + } + + return false; +} + +function typeHasIntersection(type: ts.Type): boolean { + return ( + type.isIntersection() || + (type.isUnion() && + tsutils.unionTypeParts(type).every(subType => subType.isIntersection())) + ); +} + +function isNullOrUndefinedOrAnyOrUnknownOrNever(...types: ts.Type[]): boolean { + return types.some(type => + util.isTypeFlagSet( + type, + ts.TypeFlags.Null | + ts.TypeFlags.Undefined | + ts.TypeFlags.Any | + ts.TypeFlags.Unknown | + ts.TypeFlags.Never, + ), + ); +} + export default util.createRule({ name: 'strict-enums', meta: { @@ -60,7 +127,7 @@ export default util.createRule({ mismatchedComparison: 'The two things in the comparison do not have a shared enum type.', mismatchedFunctionArgument: - 'Argument {{ ordinal }} in the function call does not match the declared enum type of the function signature.', + 'Argument {{ i }} in the function call does not match the declared enum type of the function signature.', }, schema: [], }, @@ -69,10 +136,6 @@ export default util.createRule({ const parserServices = util.getParserServices(context); const typeChecker = parserServices.program.getTypeChecker(); - // ---------------- - // Helper functions - // ---------------- - /** * If passed an enum member, returns the type of the parent. Otherwise, * returns itself. @@ -83,11 +146,10 @@ export default util.createRule({ */ function getBaseEnumType(type: ts.Type): ts.Type { const symbol = type.getSymbol(); - if (symbol === undefined) { - return type; - } - - if (!tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.EnumMember)) { + if ( + symbol === undefined || + !tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.EnumMember) + ) { return type; } @@ -96,63 +158,7 @@ export default util.createRule({ return type; } - const parentType = typeChecker.getTypeAtLocation(valueDeclaration.parent); - if (parentType === undefined) { - return type; - } - - return parentType; - } - - /** - * See the comment for the `EnumKind` enum. - */ - function getEnumKind(type: ts.Type): EnumKind { - if (!isEnum(type)) { - return EnumKind.NON_ENUM; - } - - const isStringLiteral = util.isTypeFlagSet( - type, - ts.TypeFlags.StringLiteral, - ); - const isNumberLiteral = util.isTypeFlagSet( - type, - ts.TypeFlags.NumberLiteral, - ); - - if (isStringLiteral && !isNumberLiteral) { - return EnumKind.HAS_STRING_VALUES; - } - - if (isNumberLiteral && !isStringLiteral) { - return EnumKind.HAS_NUMBER_VALUES; - } - - throw new Error( - 'Failed to derive the type of enum, since it did not have string values or number values.', - ); - } - - /** - * Returns a set containing the single `EnumKind` (if it is not a union), or - * a set containing N `EnumKind` (if it is a union). - */ - function getEnumKinds(type: ts.Type): Set { - if (type.isUnion()) { - const subTypes = tsutils.unionTypeParts(type); - const enumKinds = subTypes.map(subType => getEnumKind(subType)); - return new Set(enumKinds); - } - - if (type.isIntersection()) { - throw new Error( - 'The getEnumKinds function is not meant to be used on intersections.', - ); - } - - const enumKind = getEnumKind(type); - return new Set([enumKind]); + return typeChecker.getTypeAtLocation(valueDeclaration.parent) ?? type; } /** @@ -184,139 +190,27 @@ export default util.createRule({ }); const enumSubTypes = subTypesConstraints.filter(subType => - isEnum(subType), - ); - const baseEnumSubTypes = enumSubTypes.map(subType => - getBaseEnumType(subType), + util.isTypeFlagSet(subType, ts.TypeFlags.EnumLiteral), ); + const baseEnumSubTypes = enumSubTypes.map(getBaseEnumType); return new Set(baseEnumSubTypes); } - /** - * Given a set A and set B, return a set that contains only elements that are in - * both sets. - */ - function getIntersectingSet(a: Set, b: Set): Set { - const intersectingValues = [...a.values()].filter(value => b.has(value)); - return new Set(intersectingValues); - } - - /** - * From: - * https://stackoverflow.com/questions/13627308/add-st-nd-rd-and-th-ordinal-suffix-to-a-number - */ - function getOrdinalSuffix(i: number): string { - const j = i % 10; - const k = i % 100; - if (j == 1 && k != 11) { - return `${i}st`; - } - if (j == 2 && k != 12) { - return `${i}nd`; - } - if (j == 3 && k != 13) { - return `${i}rd`; - } - return `${i}th`; - } - function getTypeFromNode(node: TSESTree.Node): ts.Type { return typeChecker.getTypeAtLocation( parserServices.esTreeNodeToTSNodeMap.get(node), ); } - function hasEnumTypes(type: ts.Type): boolean { - return getEnumTypes(type).size > 0; - } - - function hasIntersection(type: ts.Type): boolean { - if (type.isIntersection()) { - return true; - } - - if (type.isUnion()) { - const subTypes = tsutils.unionTypeParts(type); - for (const subType of subTypes) { - if (subType.isIntersection()) { - return true; - } - } - } - - return false; - } - - function isEnum(type: ts.Type): boolean { - /** - * The "EnumLiteral" flag will be set on both enum base types and enum - * members/values. - */ - return util.isTypeFlagSet(type, ts.TypeFlags.EnumLiteral); - } - - function isNullOrUndefinedOrAnyOrUnknownOrNever( - ...types: ts.Type[] - ): boolean { - return types.some(type => - util.isTypeFlagSet( - type, - ts.TypeFlags.Null | - ts.TypeFlags.Undefined | - ts.TypeFlags.Any | - ts.TypeFlags.Unknown | - ts.TypeFlags.Never, - ), - ); - } - - function isNumber(type: ts.Type): boolean { - /** - * The "NumberLike" flag will be set on both number literals and number - * variables. - */ - return util.isTypeFlagSet(type, ts.TypeFlags.NumberLike); - } - - function isString(type: ts.Type): boolean { - /** - * The "StrikeLike" flag will be set on both string literals and string - * variables. - */ - return util.isTypeFlagSet(type, ts.TypeFlags.StringLike); - } - - function setHasAnyElementFromSet(set1: Set, set2: Set): boolean { - for (const value of set2.values()) { - if (set1.has(value)) { - return true; - } - } - - return false; - } - - // -------------- - // Main functions - // -------------- - function checkCallExpression( node: TSESTree.CallExpression | TSESTree.NewExpression, ): void { const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); - if (!ts.isCallLikeExpression(tsNode)) { - return; - } - const signature = typeChecker.getResolvedSignature(tsNode); if (signature === undefined) { return; } - /** - * The `getDeclaration` method actually returns - * `ts.SignatureDeclaration | undefined`, not `ts.SignatureDeclaration`. - */ const declaration = signature.getDeclaration(); if (declaration === undefined) { return; @@ -368,9 +262,7 @@ export default util.createRule({ context.report({ node: node.arguments[i], messageId: 'mismatchedFunctionArgument', - data: { - ordinal: getOrdinalSuffix(i + 1), - }, + data: { i }, }); } } @@ -425,19 +317,14 @@ export default util.createRule({ } /** - * As a special case, allow assignment of certain types that the + * As a special case, allow assignment of bottom and top types that the * TypeScript compiler should handle properly. */ if (isNullOrUndefinedOrAnyOrUnknownOrNever(rightType)) { return false; } - const rightEnumTypes = getEnumTypes(rightType); - const intersectingTypes = getIntersectingSet( - leftEnumTypes, - rightEnumTypes, - ); - return intersectingTypes.size === 0; + return setHasAnyElementFromSet(leftEnumTypes, getEnumTypes(rightType)); } function isMismatchedEnumComparison( @@ -461,7 +348,7 @@ export default util.createRule({ * Allow comparisons to any intersection. Enum intersections would be rare * in real-life code, so they are out of scope for this rule. */ - if (hasIntersection(leftType) || hasIntersection(rightType)) { + if (typeHasIntersection(leftType) || typeHasIntersection(rightType)) { return false; } @@ -498,32 +385,33 @@ export default util.createRule({ * lint rule is unneeded.) */ const leftEnumKinds = getEnumKinds(leftType); - const rightEnumKinds = getEnumKinds(rightType); if ( leftEnumKinds.has(EnumKind.HAS_STRING_VALUES) && leftEnumKinds.size === 1 && - isNumber(rightType) + util.isTypeFlagSet(rightType, ts.TypeFlags.NumberLike) ) { return false; } if ( leftEnumKinds.has(EnumKind.HAS_NUMBER_VALUES) && leftEnumKinds.size === 1 && - isString(rightType) + util.isTypeFlagSet(rightType, ts.TypeFlags.StringLike) ) { return false; } + + const rightEnumKinds = getEnumKinds(rightType); if ( rightEnumKinds.has(EnumKind.HAS_STRING_VALUES) && rightEnumKinds.size === 1 && - isNumber(leftType) + util.isTypeFlagSet(leftType, ts.TypeFlags.NumberLike) ) { return false; } if ( rightEnumKinds.has(EnumKind.HAS_NUMBER_VALUES) && rightEnumKinds.size === 1 && - isString(leftType) + util.isTypeFlagSet(leftType, ts.TypeFlags.StringLike) ) { return false; } @@ -535,11 +423,7 @@ export default util.createRule({ * if (fruit === 0) {} * ``` */ - const intersectingTypes = getIntersectingSet( - leftEnumTypes, - rightEnumTypes, - ); - return intersectingTypes.size === 0; + return setHasAnyElementFromSet(leftEnumTypes, rightEnumTypes); } function isMismatchedEnumFunctionArgument( @@ -600,7 +484,6 @@ export default util.createRule({ * useNumber(0); * ``` */ - const argumentEnumTypes = getEnumTypes(argumentType); const parameterEnumTypes = getEnumTypes(parameterType); if (parameterEnumTypes.size === 0) { return false; @@ -640,7 +523,10 @@ export default util.createRule({ */ const argumentSubTypes = tsutils.unionTypeParts(argumentType); for (const argumentSubType of argumentSubTypes) { - if (argumentSubType.isLiteral() && !isEnum(argumentSubType)) { + if ( + argumentSubType.isLiteral() && + !util.isTypeFlagSet(argumentSubType, ts.TypeFlags.EnumLiteral) + ) { return true; } } @@ -669,7 +555,9 @@ export default util.createRule({ * useFruit(Fruit.Apple); * ``` */ - if (setHasAnyElementFromSet(argumentEnumTypes, parameterEnumTypes)) { + if ( + setHasAnyElementFromSet(getEnumTypes(argumentType), parameterEnumTypes) + ) { return false; } @@ -681,7 +569,6 @@ export default util.createRule({ // ------------------ return { - /** When something is assigned to a variable. */ AssignmentExpression(node): void { const leftType = getTypeFromNode(node.left); const rightType = getTypeFromNode(node.right); @@ -694,7 +581,6 @@ export default util.createRule({ } }, - /** When a comparison between two things happen. */ BinaryExpression(node): void { const leftType = getTypeFromNode(node.left); const rightType = getTypeFromNode(node.right); @@ -707,17 +593,9 @@ export default util.createRule({ } }, - /** When a function is invoked or a class is instantiated. */ - 'CallExpression, NewExpression': function callExpressionOrNewExpression( - node: TSESTree.CallExpression | TSESTree.NewExpression, - ): void { - checkCallExpression(node); - }, + 'CallExpression, NewExpression': checkCallExpression, - /** When a unary operator is invoked. */ UpdateExpression(node): void { - const argumentType = getTypeFromNode(node.argument); - /** * Disallow using enums with unary operators, like the following: * @@ -726,7 +604,7 @@ export default util.createRule({ * fruit++; * ``` */ - if (hasEnumTypes(argumentType)) { + if (getEnumTypes(getTypeFromNode(node.argument)).size > 0) { context.report({ node, messageId: 'incorrectIncrement', @@ -734,37 +612,23 @@ export default util.createRule({ } }, - /** When a new variable is created. */ - VariableDeclarator(node): void { - const leftTSNode = parserServices.esTreeNodeToTSNodeMap.get(node); - if (!ts.isVariableDeclaration(leftTSNode)) { - return; - } - - /** - * Allow enum declarations without an initializer, like the following: - * - * ```ts - * let fruit: Fruit; - * if (something()) { - * fruit = Fruit.Apple; - * } else { - * fruit = Fruit.Banana; - * } - * ``` - */ - if (leftTSNode.initializer === undefined) { - return; - } - - /** - * We have to use `leftTSNode.name` instead of `leftTSNode` to avoid - * runtime errors because the `typeChecker.getTypeAtLocation` method - * expects a `ts.BindingName` instead of a `ts.VariableDeclaration`. - * https://github.com/microsoft/TypeScript/issues/48878 - */ - const leftType = typeChecker.getTypeAtLocation(leftTSNode.name); - const rightType = typeChecker.getTypeAtLocation(leftTSNode.initializer); + /** + * Allow enum declarations without an initializer, like the following: + * + * ```ts + * let fruit: Fruit; + * if (something()) { + * fruit = Fruit.Apple; + * } else { + * fruit = Fruit.Banana; + * } + * ``` + */ + 'VariableDeclarator[init]'( + node: TSESTree.VariableDeclarator & { init: TSESTree.Expression }, + ): void { + const leftType = getTypeFromNode(node.id); + const rightType = getTypeFromNode(node.init); if (isAssigningNonEnumValueToEnumVariable(leftType, rightType)) { context.report({ diff --git a/packages/eslint-plugin/src/util/misc.ts b/packages/eslint-plugin/src/util/misc.ts index 2bdc8ee0f591..ff16e247c75c 100644 --- a/packages/eslint-plugin/src/util/misc.ts +++ b/packages/eslint-plugin/src/util/misc.ts @@ -158,10 +158,6 @@ type RequireKeys< TKeys extends keyof TObj, > = ExcludeKeys & { [k in TKeys]-?: Exclude }; -function getEnumNames(myEnum: Record): T[] { - return Object.keys(myEnum).filter(x => isNaN(parseInt(x))) as T[]; -} - /** * Given an array of words, returns an English-friendly concatenation, separated with commas, with * the `and` clause inserted before the last item. @@ -187,7 +183,6 @@ export { ExcludeKeys, findFirstResult, formatWordList, - getEnumNames, getNameFromIndexSignature, getNameFromMember, isDefinitionFile, diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums.ts b/packages/eslint-plugin/tests/rules/strict-enums/shared.ts similarity index 100% rename from packages/eslint-plugin/tests/rules/strict-enums/strict-enums.ts rename to packages/eslint-plugin/tests/rules/strict-enums/shared.ts diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts index dc575fb31639..dd51e49647e1 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts @@ -3,7 +3,7 @@ import { fruit2EnumDefinition, fruitEnumDefinition, strictEnumsRuleTester, -} from './strict-enums'; +} from './shared'; strictEnumsRuleTester.run('strict-enums-assignment', rule, { valid: [ diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts index ef3a045d0ba3..1a078593af6b 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts @@ -5,7 +5,7 @@ import { strictEnumsRuleTester, vegetable2EnumDefinition, vegetableEnumDefinition, -} from './strict-enums'; +} from './shared'; strictEnumsRuleTester.run('strict-enums-comparison', rule, { valid: [ diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts index c594c00d2453..7af6ce0d0310 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts @@ -3,7 +3,7 @@ import { fruitEnumDefinition, strictEnumsRuleTester, vegetableEnumDefinition, -} from './strict-enums'; +} from './shared'; /** A function that takes a number enum. */ const fruitFunctionDefinition = diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-incrementing.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-incrementing.test.ts index bb11727230aa..c2cde406ff73 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-incrementing.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-incrementing.test.ts @@ -1,5 +1,5 @@ import rule from '../../../src/rules/strict-enums'; -import { fruitEnumDefinition, strictEnumsRuleTester } from './strict-enums'; +import { fruitEnumDefinition, strictEnumsRuleTester } from './shared'; strictEnumsRuleTester.run('strict-enums-incrementing', rule, { valid: [ From be144e328c99c5934cf2c407ec29ed0f25ea8864 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Fri, 25 Nov 2022 06:11:07 -0500 Subject: [PATCH 77/88] Add back getEnumNames --- packages/eslint-plugin/src/util/misc.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/eslint-plugin/src/util/misc.ts b/packages/eslint-plugin/src/util/misc.ts index ff16e247c75c..2bdc8ee0f591 100644 --- a/packages/eslint-plugin/src/util/misc.ts +++ b/packages/eslint-plugin/src/util/misc.ts @@ -158,6 +158,10 @@ type RequireKeys< TKeys extends keyof TObj, > = ExcludeKeys & { [k in TKeys]-?: Exclude }; +function getEnumNames(myEnum: Record): T[] { + return Object.keys(myEnum).filter(x => isNaN(parseInt(x))) as T[]; +} + /** * Given an array of words, returns an English-friendly concatenation, separated with commas, with * the `and` clause inserted before the last item. @@ -183,6 +187,7 @@ export { ExcludeKeys, findFirstResult, formatWordList, + getEnumNames, getNameFromIndexSignature, getNameFromMember, isDefinitionFile, From e4ac325c6612e98a6deb727cb668e515d6ce24d5 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Fri, 25 Nov 2022 06:30:17 -0500 Subject: [PATCH 78/88] Even more trimming down --- .../eslint-plugin/src/rules/strict-enums.ts | 211 +++++++----------- 1 file changed, 78 insertions(+), 133 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 4da7d9e4b89e..4342cb4f66ff 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -13,16 +13,14 @@ import * as util from '../util'; */ enum EnumKind { NON_ENUM, - HAS_NUMBER_VALUES, - HAS_STRING_VALUES, + HasNumberValues, + HasStringValues, } -/** These operators are always considered to be safe. */ -const ALLOWED_ENUM_OPERATORS = new Set(['in', '|', '&', '^', '|=', '&=', '^=']); +/** These bitwise operators are always considered to be safe comparisons. */ +const ALLOWED_ENUM_OPERATORS = new Set(['|=', '&=', '^=']); /** - * See the comment for `EnumKind`. - * * This rule can safely ignore other kinds of types (and leave the validation in * question to the TypeScript compiler). */ @@ -56,11 +54,11 @@ function getEnumKind(type: ts.Type): EnumKind { const isNumberLiteral = util.isTypeFlagSet(type, ts.TypeFlags.NumberLiteral); if (isStringLiteral && !isNumberLiteral) { - return EnumKind.HAS_STRING_VALUES; + return EnumKind.HasStringValues; } if (isNumberLiteral && !isStringLiteral) { - return EnumKind.HAS_NUMBER_VALUES; + return EnumKind.HasNumberValues; } throw new Error( @@ -73,11 +71,9 @@ function getEnumKind(type: ts.Type): EnumKind { * a set containing N `EnumKind` (if it is a union). */ function getEnumKinds(type: ts.Type): Set { - if (type.isUnion()) { - return new Set(tsutils.unionTypeParts(type).map(getEnumKind)); - } - - return new Set([getEnumKind(type)]); + return type.isUnion() + ? new Set(tsutils.unionTypeParts(type).map(getEnumKind)) + : new Set([getEnumKind(type)]); } function setHasAnyElementFromSet(set1: Set, set2: Set): boolean { @@ -162,7 +158,7 @@ export default util.createRule({ } /** - * A thing can have 0 or more enum types. For example: + * A type can have 0 or more enum types. For example: * - 123 --> [] * - {} --> [] * - Fruit.Apple --> [Fruit] @@ -171,29 +167,18 @@ export default util.createRule({ * - T extends Fruit --> [Fruit] */ function getEnumTypes(type: ts.Type): Set { - /** - * First, we get all the parts of the union. For non-union types, this - * will be an array with the type in it. For example: - * - Fruit --> [Fruit] - * - Fruit | Vegetable --> [Fruit, Vegetable] - */ - const subTypes = tsutils.unionTypeParts(type); - - /** - * Next, we must resolve generic types with constraints. For example: - * - Fruit --> Fruit - * - T extends Fruit --> Fruit - */ - const subTypesConstraints = subTypes.map(subType => { - const constraint = subType.getConstraint(); - return constraint === undefined ? subType : constraint; - }); - - const enumSubTypes = subTypesConstraints.filter(subType => - util.isTypeFlagSet(subType, ts.TypeFlags.EnumLiteral), + return new Set( + tsutils + // We resolve the type (or its constituents)... + .unionTypeParts(type) + // ...to any generic constraint... + .map(subType => subType.getConstraint() ?? subType) + // ...and only look at base types of enum types + .filter(subType => + util.isTypeFlagSet(subType, ts.TypeFlags.EnumLiteral), + ) + .map(getBaseEnumType), ); - const baseEnumSubTypes = enumSubTypes.map(getBaseEnumType); - return new Set(baseEnumSubTypes); } function getTypeFromNode(node: TSESTree.Node): ts.Type { @@ -202,7 +187,7 @@ export default util.createRule({ ); } - function checkCallExpression( + function checkCallOrNewExpression( node: TSESTree.CallExpression | TSESTree.NewExpression, ): void { const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); @@ -216,10 +201,8 @@ export default util.createRule({ return; } - /** - * Iterate through the arguments provided to the call function and cross - * reference their types to the types of the "real" function parameters. - */ + // Iterate through the arguments provided to the call function and cross + // reference their types to the types of the "real" function parameters. for (let i = 0; i < node.arguments.length; i++) { const argument = node.arguments[i]; const argumentType = getTypeFromNode(argument); @@ -272,14 +255,12 @@ export default util.createRule({ leftType: ts.Type, rightType: ts.Type, ): boolean { - /** - * First, recursively check for containers like the following: - * - * ```ts - * declare let fruits: Fruit[]; - * fruits = [0, 1]; - * ``` - */ + // First, recursively check for containers like the following: + // + // ```ts + // declare let fruits: Fruit[]; + // fruits = [0, 1]; + // ``` if ( util.isTypeReferenceType(leftType) && util.isTypeReferenceType(rightType) @@ -287,20 +268,15 @@ export default util.createRule({ const leftTypeArguments = typeChecker.getTypeArguments(leftType); const rightTypeArguments = typeChecker.getTypeArguments(rightType); - for (let i = 0; i < leftTypeArguments.length; i++) { - const leftTypeArgument = leftTypeArguments[i]; - const rightTypeArgument = rightTypeArguments[i]; - if ( - leftTypeArgument === undefined || - rightTypeArgument === undefined - ) { - continue; - } - + for ( + let i = 0; + i < Math.min(leftTypeArguments.length, rightTypeArguments.length); + i += 1 + ) { if ( isAssigningNonEnumValueToEnumVariable( - leftTypeArgument, - rightTypeArgument, + leftTypeArguments[i], + rightTypeArguments[i], ) ) { return true; @@ -310,16 +286,14 @@ export default util.createRule({ return false; } + // If the recipient is not an enum, this is not an enum assignment. const leftEnumTypes = getEnumTypes(leftType); if (leftEnumTypes.size === 0) { - // This is not an enum assignment return false; } - /** - * As a special case, allow assignment of bottom and top types that the - * TypeScript compiler should handle properly. - */ + // As a special case, allow assignment of bottom and top types that the + // TypeScript compiler should handle properly. if (isNullOrUndefinedOrAnyOrUnknownOrNever(rightType)) { return false; } @@ -332,33 +306,28 @@ export default util.createRule({ leftType: ts.Type, rightType: ts.Type, ): boolean { - /** Allow comparisons with whitelisted operators. */ + // Allow comparisons with allowlisted operators. if (ALLOWED_ENUM_OPERATORS.has(operator)) { return false; } - /** Allow comparisons that don't have anything to do with enums. */ + // Allow comparisons that don't have anything to do with enums. const leftEnumTypes = getEnumTypes(leftType); const rightEnumTypes = getEnumTypes(rightType); if (leftEnumTypes.size === 0 && rightEnumTypes.size === 0) { return false; } - /** - * Allow comparisons to any intersection. Enum intersections would be rare - * in real-life code, so they are out of scope for this rule. - */ + // Allow comparisons to any intersection. Enum intersections would be rare + // in real-life code, so they are out of scope for this rule. if (typeHasIntersection(leftType) || typeHasIntersection(rightType)) { return false; } - /** - * Allow comparisons to things with a type that can never be an enum (like - * a function). - * - * (The TypeScript compiler should properly type-check these cases, so the - * lint rule is unneeded.) - */ + // Allow comparisons to types that can never be an enum (like a function). + // + // (The TypeScript compiler should properly type-check these cases, so the + // lint rule is unneeded.) if ( util.isTypeFlagSet(leftType, IMPOSSIBLE_ENUM_TYPES) || util.isTypeFlagSet(rightType, IMPOSSIBLE_ENUM_TYPES) @@ -366,34 +335,30 @@ export default util.createRule({ return false; } - /** - * Allow exact comparisons to some standard types, like null and - * undefined. - * - * The TypeScript compiler should properly type-check these cases, so the - * lint rule is unneeded. - */ + // Allow exact comparisons to some standard types, like null and + // undefined. + // + // The TypeScript compiler should properly type-check these cases, so the + // lint rule is unneeded. if (isNullOrUndefinedOrAnyOrUnknownOrNever(leftType, rightType)) { return false; } - /** - * Allow number enums to be compared with strings and string enums to be - * compared with numbers. - * - * (The TypeScript compiler should properly type-check these cases, so the - * lint rule is unneeded.) - */ + // Allow number enums to be compared with strings and string enums to be + // compared with numbers. + // + // (The TypeScript compiler should properly type-check these cases, so the + // lint rule is unneeded.) const leftEnumKinds = getEnumKinds(leftType); if ( - leftEnumKinds.has(EnumKind.HAS_STRING_VALUES) && + leftEnumKinds.has(EnumKind.HasStringValues) && leftEnumKinds.size === 1 && util.isTypeFlagSet(rightType, ts.TypeFlags.NumberLike) ) { return false; } if ( - leftEnumKinds.has(EnumKind.HAS_NUMBER_VALUES) && + leftEnumKinds.has(EnumKind.HasNumberValues) && leftEnumKinds.size === 1 && util.isTypeFlagSet(rightType, ts.TypeFlags.StringLike) ) { @@ -402,27 +367,25 @@ export default util.createRule({ const rightEnumKinds = getEnumKinds(rightType); if ( - rightEnumKinds.has(EnumKind.HAS_STRING_VALUES) && + rightEnumKinds.has(EnumKind.HasStringValues) && rightEnumKinds.size === 1 && util.isTypeFlagSet(leftType, ts.TypeFlags.NumberLike) ) { return false; } if ( - rightEnumKinds.has(EnumKind.HAS_NUMBER_VALUES) && + rightEnumKinds.has(EnumKind.HasNumberValues) && rightEnumKinds.size === 1 && util.isTypeFlagSet(leftType, ts.TypeFlags.StringLike) ) { return false; } - /** - * Disallow mismatched comparisons, like the following: - * - * ```ts - * if (fruit === 0) {} - * ``` - */ + // Disallow mismatched comparisons, like the following: + // + // ```ts + // if (fruit === 0) {} + // ``` return setHasAnyElementFromSet(leftEnumTypes, rightEnumTypes); } @@ -564,10 +527,6 @@ export default util.createRule({ return true; } - // ------------------ - // AST node callbacks - // ------------------ - return { AssignmentExpression(node): void { const leftType = getTypeFromNode(node.left); @@ -575,55 +534,41 @@ export default util.createRule({ if (isAssigningNonEnumValueToEnumVariable(leftType, rightType)) { context.report({ - node, messageId: 'mismatchedAssignment', + node, }); } }, - BinaryExpression(node): void { + 'BinaryExpression[operator=/=/]'(node: TSESTree.BinaryExpression): void { const leftType = getTypeFromNode(node.left); const rightType = getTypeFromNode(node.right); if (isMismatchedEnumComparison(node.operator, leftType, rightType)) { context.report({ - node, messageId: 'mismatchedComparison', + node, }); } }, - 'CallExpression, NewExpression': checkCallExpression, + 'CallExpression, NewExpression': checkCallOrNewExpression, UpdateExpression(node): void { - /** - * Disallow using enums with unary operators, like the following: - * - * ```ts - * const fruit = Fruit.Apple; - * fruit++; - * ``` - */ + // Disallow using enums with unary operators, like the following: + // + // ```ts + // const fruit = Fruit.Apple; + // fruit++; + // ``` if (getEnumTypes(getTypeFromNode(node.argument)).size > 0) { context.report({ - node, messageId: 'incorrectIncrement', + node, }); } }, - /** - * Allow enum declarations without an initializer, like the following: - * - * ```ts - * let fruit: Fruit; - * if (something()) { - * fruit = Fruit.Apple; - * } else { - * fruit = Fruit.Banana; - * } - * ``` - */ 'VariableDeclarator[init]'( node: TSESTree.VariableDeclarator & { init: TSESTree.Expression }, ): void { From 62ccdb1f78e38895b08bdb95877d210fcef63abf Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Fri, 25 Nov 2022 06:33:40 -0500 Subject: [PATCH 79/88] ...and just a bit more --- .../eslint-plugin/src/rules/strict-enums.ts | 183 ++++++++---------- 1 file changed, 80 insertions(+), 103 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index 4342cb4f66ff..b4624fe5cc28 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -8,11 +8,11 @@ import * as util from '../util'; * TypeScript only allows number enums, string enums, or mixed enums with both * numbers and strings. * - * Mixed enums are be a union of a number enum and a string enum, so there is + * Mixed enums are a union of a number enum and a string enum, so there is * no separate kind for them. */ enum EnumKind { - NON_ENUM, + NonEnum, HasNumberValues, HasStringValues, } @@ -42,12 +42,9 @@ export type MessageIds = | 'mismatchedComparison' | 'mismatchedFunctionArgument'; -/** - * See the comment for the `EnumKind` enum. - */ function getEnumKind(type: ts.Type): EnumKind { if (!util.isTypeFlagSet(type, ts.TypeFlags.EnumLike)) { - return EnumKind.NON_ENUM; + return EnumKind.NonEnum; } const isStringLiteral = util.isTypeFlagSet(type, ts.TypeFlags.StringLiteral); @@ -132,14 +129,12 @@ export default util.createRule({ const parserServices = util.getParserServices(context); const typeChecker = parserServices.program.getTypeChecker(); - /** - * If passed an enum member, returns the type of the parent. Otherwise, - * returns itself. - * - * For example: - * - `Fruit` --> `Fruit` - * - `Fruit.Apple` --> `Fruit` - */ + // If passed an enum member, returns the type of the parent. Otherwise, + // returns itself. + // + // For example: + // - `Fruit` --> `Fruit` + // - `Fruit.Apple` --> `Fruit` function getBaseEnumType(type: ts.Type): ts.Type { const symbol = type.getSymbol(); if ( @@ -157,15 +152,13 @@ export default util.createRule({ return typeChecker.getTypeAtLocation(valueDeclaration.parent) ?? type; } - /** - * A type can have 0 or more enum types. For example: - * - 123 --> [] - * - {} --> [] - * - Fruit.Apple --> [Fruit] - * - Fruit.Apple | Vegetable.Lettuce --> [Fruit, Vegetable] - * - Fruit.Apple | Vegetable.Lettuce | 123 --> [Fruit, Vegetable] - * - T extends Fruit --> [Fruit] - */ + // A type can have 0 or more enum types. For example: + // - 123 --> [] + // - {} --> [] + // - Fruit.Apple --> [Fruit] + // - Fruit.Apple | Vegetable.Lettuce --> [Fruit, Vegetable] + // - Fruit.Apple | Vegetable.Lettuce | 123 --> [Fruit, Vegetable] + // - T extends Fruit --> [Fruit] function getEnumTypes(type: ts.Type): Set { return new Set( tsutils @@ -208,22 +201,20 @@ export default util.createRule({ const argumentType = getTypeFromNode(argument); let parameterType = signature.getTypeParameterAtPosition(i); - /** - * If this function parameter is a generic type that extends another - * type, we want to compare the calling argument to the constraint - * instead. - * - * For example: - * - * ```ts - * function useFruit(fruitType: FruitType) {} - * useFruit(0) - * ``` - * - * Here, we want to compare `Fruit.Apple` to `Fruit`, not `FruitType`, - * because `FruitType` would just be equal to 0 in this case (and - * would be unsafe). - */ + // If this function parameter is a generic type that extends another + // type, we want to compare the calling argument to the constraint + // instead. + // + // For example: + // + // ```ts + // function useFruit(fruitType: FruitType) {} + // useFruit(0) + // ``` + // + // Here, we want to compare `Fruit.Apple` to `Fruit`, not `FruitType`, + // because `FruitType` would just be equal to 0 in this case (and + // would be unsafe). const parameter = declaration.parameters[i]; if (parameter !== undefined) { const parameterTSNode = typeChecker.getTypeAtLocation(parameter); @@ -233,14 +224,12 @@ export default util.createRule({ } } - /** - * Disallow mismatched function calls, like the following: - * - * ```ts - * function useFruit(fruit: Fruit) {} - * useFruit(0); - * ``` - */ + // Disallow mismatched function calls, like the following: + // + // ```ts + // function useFruit(fruit: Fruit) {} + // useFruit(0); + // ``` if (isMismatchedEnumFunctionArgument(argumentType, parameterType)) { context.report({ node: node.arguments[i], @@ -393,15 +382,13 @@ export default util.createRule({ argumentType: ts.Type, // From the function call parameterType: ts.Type, // From the function itself ): boolean { - /** - * First, recursively check for functions with type containers like the - * following: - * - * ```ts - * function useFruits(fruits: Fruit[]) {} - * useFruits([0, 1]); - * ``` - */ + // First, recursively check for functions with type containers like the + // following: + // + // ```ts + // function useFruits(fruits: Fruit[]) {} + // useFruits([0, 1]); + // ``` if (util.isTypeReferenceType(argumentType)) { const argumentTypeArguments = typeChecker.getTypeArguments(argumentType); @@ -438,30 +425,26 @@ export default util.createRule({ return false; } - /** - * Allow function calls that have nothing to do with enums, like the - * following: - * - * ```ts - * function useNumber(num: number) {} - * useNumber(0); - * ``` - */ + // Allow function calls that have nothing to do with enums, like the + // following: + // + // ```ts + // function useNumber(num: number) {} + // useNumber(0); + // ``` const parameterEnumTypes = getEnumTypes(parameterType); if (parameterEnumTypes.size === 0) { return false; } - /** - * Allow passing enum values into functions that take in the "any" type - * and similar types that should basically match any enum, like the - * following: - * - * ```ts - * function useNumber(num: number) {} - * useNumber(Fruit.Apple); - * ``` - */ + // Allow passing enum values into functions that take in the "any" type + // and similar types that should basically match any enum, like the + // following: + // + // ```ts + // function useNumber(num: number) {} + // useNumber(Fruit.Apple); + // ``` const parameterSubTypes = tsutils.unionTypeParts(parameterType); for (const parameterSubType of parameterSubTypes) { if ( @@ -474,16 +457,14 @@ export default util.createRule({ } } - /** - * Disallow passing number literals or string literals into functions that - * take in an enum, like the following: - * - * ```ts - * function useFruit(fruit: Fruit) {} - * declare const fruit: Fruit.Apple | 1; - * useFruit(fruit) - * ``` - */ + // Disallow passing number literals or string literals into functions that + // take in an enum, like the following: + // + // ```ts + // function useFruit(fruit: Fruit) {} + // declare const fruit: Fruit.Apple | 1; + // useFruit(fruit) + // ``` const argumentSubTypes = tsutils.unionTypeParts(argumentType); for (const argumentSubType of argumentSubTypes) { if ( @@ -494,30 +475,26 @@ export default util.createRule({ } } - /** - * Allow function calls that match one of the types in a union, like the - * following: - * - * ```ts - * function useApple(fruitOrNull: Fruit | null) {} - * useApple(null); - * ``` - */ + // Allow function calls that match one of the types in a union, like the + // following: + // + // ```ts + // function useApple(fruitOrNull: Fruit | null) {} + // useApple(null); + // ``` const argumentSubTypesSet = new Set(argumentSubTypes); const parameterSubTypesSet = new Set(parameterSubTypes); if (setHasAnyElementFromSet(argumentSubTypesSet, parameterSubTypesSet)) { return false; } - /** - * Allow function calls that have a base enum that match the function - * type, like the following: - * - * ```ts - * function useFruit(fruit: Fruit) {} - * useFruit(Fruit.Apple); - * ``` - */ + // Allow function calls that have a base enum that match the function + // type, like the following: + // + // ```ts + // function useFruit(fruit: Fruit) {} + // useFruit(Fruit.Apple); + // ``` if ( setHasAnyElementFromSet(getEnumTypes(argumentType), parameterEnumTypes) ) { From da7501ae856165ad47027d7b12640133b3d8d1b5 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Fri, 25 Nov 2022 12:45:47 -0500 Subject: [PATCH 80/88] Undo some JSDoc changes --- .../eslint-plugin/src/rules/strict-enums.ts | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts index b4624fe5cc28..de975c7be754 100644 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ b/packages/eslint-plugin/src/rules/strict-enums.ts @@ -129,12 +129,14 @@ export default util.createRule({ const parserServices = util.getParserServices(context); const typeChecker = parserServices.program.getTypeChecker(); - // If passed an enum member, returns the type of the parent. Otherwise, - // returns itself. - // - // For example: - // - `Fruit` --> `Fruit` - // - `Fruit.Apple` --> `Fruit` + /* + * If passed an enum member, returns the type of the parent. Otherwise, + * returns itself. + * + * For example: + * - `Fruit` --> `Fruit` + * - `Fruit.Apple` --> `Fruit` + */ function getBaseEnumType(type: ts.Type): ts.Type { const symbol = type.getSymbol(); if ( @@ -152,13 +154,15 @@ export default util.createRule({ return typeChecker.getTypeAtLocation(valueDeclaration.parent) ?? type; } - // A type can have 0 or more enum types. For example: - // - 123 --> [] - // - {} --> [] - // - Fruit.Apple --> [Fruit] - // - Fruit.Apple | Vegetable.Lettuce --> [Fruit, Vegetable] - // - Fruit.Apple | Vegetable.Lettuce | 123 --> [Fruit, Vegetable] - // - T extends Fruit --> [Fruit] + /** + * A type can have 0 or more enum types. For example: + * - 123 --> [] + * - {} --> [] + * - Fruit.Apple --> [Fruit] + * - Fruit.Apple | Vegetable.Lettuce --> [Fruit, Vegetable] + * - Fruit.Apple | Vegetable.Lettuce | 123 --> [Fruit, Vegetable] + * - T extends Fruit --> [Fruit] + */ function getEnumTypes(type: ts.Type): Set { return new Set( tsutils From 83c33cb6ecb454ce189981a01b07e31f373aac5e Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 26 Nov 2022 16:39:21 -0500 Subject: [PATCH 81/88] Progress: no-unsafe-enum-assignment is tested --- .../docs/rules/no-unsafe-enum-assignment.md | 62 ++ .../docs/rules/no-unsafe-enum-comparison.md | 51 ++ .../eslint-plugin/docs/rules/strict-enums.md | 129 ---- packages/eslint-plugin/src/configs/all.ts | 3 +- packages/eslint-plugin/src/configs/strict.ts | 3 +- packages/eslint-plugin/src/rules/index.ts | 6 +- .../src/rules/no-unsafe-enum-assignment.ts | 365 +++++++++++ .../src/rules/no-unsafe-enum-comparison.ts | 271 +++++++++ .../eslint-plugin/src/rules/strict-enums.ts | 568 ------------------ .../rules/no-unsafe-enum-assignment.test.ts | 426 +++++++++++++ .../tests/rules/strict-enums/shared.ts | 8 +- .../strict-enums-assignment.test.ts | 235 -------- .../strict-enums-comparison.test.ts | 2 +- .../strict-enums-functions.test.ts | 2 +- .../strict-enums-incrementing.test.ts | 111 ---- .../eslint-plugin/typings/typescript.d.ts | 2 + 16 files changed, 1189 insertions(+), 1055 deletions(-) create mode 100644 packages/eslint-plugin/docs/rules/no-unsafe-enum-assignment.md create mode 100644 packages/eslint-plugin/docs/rules/no-unsafe-enum-comparison.md delete mode 100644 packages/eslint-plugin/docs/rules/strict-enums.md create mode 100644 packages/eslint-plugin/src/rules/no-unsafe-enum-assignment.ts create mode 100644 packages/eslint-plugin/src/rules/no-unsafe-enum-comparison.ts delete mode 100644 packages/eslint-plugin/src/rules/strict-enums.ts create mode 100644 packages/eslint-plugin/tests/rules/no-unsafe-enum-assignment.test.ts delete mode 100644 packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts delete mode 100644 packages/eslint-plugin/tests/rules/strict-enums/strict-enums-incrementing.test.ts diff --git a/packages/eslint-plugin/docs/rules/no-unsafe-enum-assignment.md b/packages/eslint-plugin/docs/rules/no-unsafe-enum-assignment.md new file mode 100644 index 000000000000..030b9ec29359 --- /dev/null +++ b/packages/eslint-plugin/docs/rules/no-unsafe-enum-assignment.md @@ -0,0 +1,62 @@ +--- +description: 'Disallow providing non-enum values to enum typed locations.' +--- + +> 🛑 This file is source code, not the primary documentation location! 🛑 +> +> See **https://typescript-eslint.io/rules/no-unsafe-enum-assignment** for documentation. + +The TypeScript compiler can be surprisingly lenient when working with enums. +For example, it will allow you to assign any `number` value to a variable containing a numeric enum: + +```ts +enum Fruit { + Apple, + Banana, +} + +let fruit = Fruit.Apple; +fruit = 999; // No error +``` + +This rule flags when a `number` value is provided in a location that expects an enum type. + + + +### ❌ Incorrect + +```ts +let fruit = Fruit.Apple; +fruit++; +``` + +```ts +const fruit: Fruit = 0; +``` + +```ts +function useFruit(fruit: Fruit) {} +useFruit(0); +``` + +### ✅ Correct + +```ts +let fruit = Fruit.Apple; +fruit = Fruit.Banana; +``` + +```ts +const fruit: Fruit = Fruit.Apple; +``` + +```ts +function useFruit(fruit: Fruit) {} +useFruit(Fruit.Apple); +``` + + + +## When Not to Use It + +If you use enums as shorthands for numbers and don't mind potentially unsafe `number`-typed values assigned to them, you likely don't need this rule. diff --git a/packages/eslint-plugin/docs/rules/no-unsafe-enum-comparison.md b/packages/eslint-plugin/docs/rules/no-unsafe-enum-comparison.md new file mode 100644 index 000000000000..df254d9b6c41 --- /dev/null +++ b/packages/eslint-plugin/docs/rules/no-unsafe-enum-comparison.md @@ -0,0 +1,51 @@ +--- +description: 'Disallow comparing an enum value with a non-enum value.' +--- + +> 🛑 This file is source code, not the primary documentation location! 🛑 +> +> See **https://typescript-eslint.io/rules/no-unsafe-enum-comparison** for documentation. + +The TypeScript compiler can be surprisingly lenient when working with enums. +For example, it will allow you to compare enum values against numbers even though they might not have any type overlap: + +```ts +enum Fruit { + Apple, + Banana, +} + +let fruit = Fruit.Apple; +fruit === 999; // No error +``` + +This rule flags when an enum typed value is compared to a non-enum `number`. + + + +### ❌ Incorrect + +```ts +let fruit = Fruit.Apple; +fruit === 999; +``` + +### ✅ Correct + +```ts +let fruit = Fruit.Apple; +fruit === Fruit.Banana; +``` + + + +## To Do: Add Option For Comparison Operators + +Since it is a common pattern, this rule allows using greater than or less than to compare numeric enums, like this: + +```ts +if (fruit > Fruit.Banana) { +} +``` + +This pattern allows you to select a subset of enums. However, it can lead to bugs when enum values are arbitrarily changed, because the subset will also change. The TypeScript compiler cannot warn you about this, so you should use this pattern with care. diff --git a/packages/eslint-plugin/docs/rules/strict-enums.md b/packages/eslint-plugin/docs/rules/strict-enums.md deleted file mode 100644 index 8f63ba31a04a..000000000000 --- a/packages/eslint-plugin/docs/rules/strict-enums.md +++ /dev/null @@ -1,129 +0,0 @@ ---- -description: 'Disallow the usage of unsafe enum code patterns.' ---- - -> 🛑 This file is source code, not the primary documentation location! 🛑 -> -> See **https://typescript-eslint.io/rules/strict-enums** for documentation. - -The TypeScript compiler can be surprisingly lenient when working with enums. -For example, it will allow you to assign any `number` value to a variable containing a numeric enum: - -```ts -enum Fruit { - Apple, - Banana, -} - -let fruit = Fruit.Apple; -fruit = 999; // No error -``` - -This rule flags the following unsafe enum practices: - -- Changing a numeric enum's value with math operators such as increments or multiplying - - TypeScript allows changing numeric enum values like `myValue++` as a convenience, even though the new value may not be in the enum. -- Assigning a value of one enum type to a recipient that's a different enum type - - In other words, you are trying to assign a `Fruit` enum value to a variable with a `Vegetable` type. -- Comparing an enum value with another value that is not its same enum type - - You might be trying to compare using a number literal, like `Fruit.Value1 === 1`. Or, you might be trying to compare use a disparate enum type, like `Fruit.Value1 === Vegetable.Value1`. -- Providing a value to a location where only one of those two is a particular enum type - - You might be trying to use a number literal, like `useFruit(1)`. Or, you might be trying to use a disparate enum type, like `useFruit(Vegetable.Value1)`, where `useFruit` receives a parameter of type `Foo`. - - - -### ❌ Incorrect - -```ts -let fruit = Fruit.Apple; -fruit++; -``` - -```ts -const fruit: Fruit = 0; -``` - -```ts -if (fruit === 0) { -} -if (vegetable === 'lettuce') { -} -``` - -```ts -function useFruit(fruit: Fruit) {} -useFruit(0); -``` - -### ✅ Correct - -```ts -let fruit = Fruit.Apple; -fruit = Fruit.Banana; -``` - -```ts -const fruit = Fruit.Apple; -``` - -```ts -let fruit = Fruit.Apple; -fruit = Fruit.Banana; -``` - -```ts -if (fruit === Fruit.Apple) { -} -if (vegetable === Vegetable.Lettuce) { -} -``` - -```ts -function useFruit(fruit: Fruit) {} -useFruit(Fruit.Apple); -``` - - - -## Rule Details - -### Number Enums vs String Enums - -Surprisingly, the TypeScript compiler deals with string enums in a safer way than it does with number enums. If we duplicate the first example above by using a string enum, the TypeScript compiler will correctly throw an error: - -```ts -enum Vegetable { - Lettuce = 'lettuce', - Carrot = 'carrot', -} - -let vegetable = Vegetable.Lettuce; -vegetable = 'definitelyNotAVegetable'; // Type '"definitelyNotAVegetable"' is not assignable to type 'Vegetable'. - -// Even "valid" strings will not work, which is good! -vegetable = 'carrot'; // Type '"carrot"' is not assignable to type 'Vegetable'. -``` - -Thus, the `strict-enums` rule is mostly concerned with throwing errors for misused number enums. However, it still prevents mismatched comparison, which slips by the TypeScript compiler even for string enums: - -```ts -// Bad -if (vegetable === 'lettuce') { - // The TypeScript compiler allows this, but the `strict-enums` rule does not -} - -// Good -if (vegetable === Vegetable.Lettuce) { -} -``` - -### Comparison Operators - -Since it is a common pattern, this rule allows using greater than or less than to compare numeric enums, like this: - -```ts -if (fruit > Fruit.Banana) { -} -``` - -This pattern allows you to select a subset of enums. However, it can lead to bugs when enum values are arbitrarily changed, because the subset will also change. The TypeScript compiler cannot warn you about this, so you should use this pattern with care. diff --git a/packages/eslint-plugin/src/configs/all.ts b/packages/eslint-plugin/src/configs/all.ts index 6dbe7e762963..65b5299003ed 100644 --- a/packages/eslint-plugin/src/configs/all.ts +++ b/packages/eslint-plugin/src/configs/all.ts @@ -109,6 +109,8 @@ export = { '@typescript-eslint/no-unsafe-assignment': 'error', '@typescript-eslint/no-unsafe-call': 'error', '@typescript-eslint/no-unsafe-declaration-merging': 'error', + '@typescript-eslint/no-unsafe-enum-assignment': 'error', + '@typescript-eslint/no-unsafe-enum-comparison': 'error', '@typescript-eslint/no-unsafe-member-access': 'error', '@typescript-eslint/no-unsafe-return': 'error', 'no-unused-expressions': 'off', @@ -162,7 +164,6 @@ export = { 'space-infix-ops': 'off', '@typescript-eslint/space-infix-ops': 'error', '@typescript-eslint/strict-boolean-expressions': 'error', - '@typescript-eslint/strict-enums': 'error', '@typescript-eslint/switch-exhaustiveness-check': 'error', '@typescript-eslint/triple-slash-reference': 'error', '@typescript-eslint/type-annotation-spacing': 'error', diff --git a/packages/eslint-plugin/src/configs/strict.ts b/packages/eslint-plugin/src/configs/strict.ts index a13f8f5dfc92..cec3d261e139 100644 --- a/packages/eslint-plugin/src/configs/strict.ts +++ b/packages/eslint-plugin/src/configs/strict.ts @@ -28,6 +28,8 @@ export = { '@typescript-eslint/no-unnecessary-condition': 'warn', '@typescript-eslint/no-unnecessary-type-arguments': 'warn', '@typescript-eslint/no-unsafe-declaration-merging': 'warn', + '@typescript-eslint/no-unsafe-enum-assignment': 'warn', + '@typescript-eslint/no-unsafe-enum-comparison': 'warn', 'no-useless-constructor': 'off', '@typescript-eslint/no-useless-constructor': 'warn', '@typescript-eslint/non-nullable-type-assertion-style': 'warn', @@ -41,7 +43,6 @@ export = { '@typescript-eslint/prefer-return-this-type': 'warn', '@typescript-eslint/prefer-string-starts-ends-with': 'warn', '@typescript-eslint/prefer-ts-expect-error': 'warn', - '@typescript-eslint/strict-enums': 'warn', '@typescript-eslint/unified-signatures': 'warn', }, }; diff --git a/packages/eslint-plugin/src/rules/index.ts b/packages/eslint-plugin/src/rules/index.ts index 7298fb4ac583..ca68fd258efc 100644 --- a/packages/eslint-plugin/src/rules/index.ts +++ b/packages/eslint-plugin/src/rules/index.ts @@ -79,6 +79,8 @@ import noUnsafeArgument from './no-unsafe-argument'; import noUnsafeAssignment from './no-unsafe-assignment'; import noUnsafeCall from './no-unsafe-call'; import noUnsafeDeclarationMerging from './no-unsafe-declaration-merging'; +import noUnsafeEnumAssignment from './no-unsafe-enum-assignment'; +import noUnsafeEnumComparison from './no-unsafe-enum-comparison'; import noUnsafeMemberAccess from './no-unsafe-member-access'; import noUnsafeReturn from './no-unsafe-return'; import noUnusedExpressions from './no-unused-expressions'; @@ -121,7 +123,6 @@ import spaceBeforeBlocks from './space-before-blocks'; import spaceBeforeFunctionParen from './space-before-function-paren'; import spaceInfixOps from './space-infix-ops'; import strictBooleanExpressions from './strict-boolean-expressions'; -import strictEnums from './strict-enums'; import switchExhaustivenessCheck from './switch-exhaustiveness-check'; import tripleSlashReference from './triple-slash-reference'; import typeAnnotationSpacing from './type-annotation-spacing'; @@ -211,6 +212,8 @@ export default { 'no-unsafe-assignment': noUnsafeAssignment, 'no-unsafe-call': noUnsafeCall, 'no-unsafe-declaration-merging': noUnsafeDeclarationMerging, + 'no-unsafe-enum-assignment': noUnsafeEnumAssignment, + 'no-unsafe-enum-comparison': noUnsafeEnumComparison, 'no-unsafe-member-access': noUnsafeMemberAccess, 'no-unsafe-return': noUnsafeReturn, 'no-unused-expressions': noUnusedExpressions, @@ -253,7 +256,6 @@ export default { 'space-before-function-paren': spaceBeforeFunctionParen, 'space-infix-ops': spaceInfixOps, 'strict-boolean-expressions': strictBooleanExpressions, - 'strict-enums': strictEnums, 'switch-exhaustiveness-check': switchExhaustivenessCheck, 'triple-slash-reference': tripleSlashReference, 'type-annotation-spacing': typeAnnotationSpacing, diff --git a/packages/eslint-plugin/src/rules/no-unsafe-enum-assignment.ts b/packages/eslint-plugin/src/rules/no-unsafe-enum-assignment.ts new file mode 100644 index 000000000000..d75f6ce01fb2 --- /dev/null +++ b/packages/eslint-plugin/src/rules/no-unsafe-enum-assignment.ts @@ -0,0 +1,365 @@ +import type { TSESTree } from '@typescript-eslint/utils'; +import * as tsutils from 'tsutils'; +import * as ts from 'typescript'; + +import * as util from '../util'; + +const ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT = + ts.TypeFlags.Unknown | ts.TypeFlags.Number | ts.TypeFlags.String; + +export default util.createRule({ + name: 'no-unsafe-enum-assignment', + meta: { + type: 'suggestion', + docs: { + description: 'Disallow providing non-enum values to enum typed locations', + recommended: 'strict', + requiresTypeChecking: true, + }, + messages: { + operation: + 'This {{ operator }} may change the enum value to one not present in its enum type.', + provided: 'Unsafe non enum type provided to an enum value.', + }, + schema: [], + }, + defaultOptions: [], + create(context) { + const parserServices = util.getParserServices(context); + const typeChecker = parserServices.program.getTypeChecker(); + + /* + * If passed an enum member, returns the type of the parent. Otherwise, + * returns itself. + * + * For example: + * - `Fruit` --> `Fruit` + * - `Fruit.Apple` --> `Fruit` + */ + function getBaseEnumType(type: ts.Type): ts.Type { + const symbol = type.getSymbol(); + if ( + !symbol?.valueDeclaration?.parent || + !tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.EnumMember) + ) { + return type; + } + + return typeChecker.getTypeAtLocation(symbol.valueDeclaration.parent); + } + + /** + * A type can have 0 or more enum types. For example: + * - 123 --> [] + * - {} --> [] + * - Fruit.Apple --> [Fruit] + * - Fruit.Apple | Vegetable.Lettuce --> [Fruit, Vegetable] + * - Fruit.Apple | Vegetable.Lettuce | 123 --> [Fruit, Vegetable] + * - T extends Fruit --> [Fruit] + */ + function getEnumTypes(type: ts.Type): ts.Type[] { + return tsutils + .unionTypeParts(type) + .filter(subType => + util.isTypeFlagSet(subType, ts.TypeFlags.EnumLiteral), + ) + .map(getBaseEnumType); + } + + /** + * Similar to `getEnumTypes`, but returns early as soon as it finds one. + */ + function hasEnumType(type: ts.Type): boolean { + return tsutils + .unionTypeParts(type) + .some(subType => util.isTypeFlagSet(subType, ts.TypeFlags.EnumLiteral)); + } + + function getTypeFromNode(node: TSESTree.Node): ts.Type { + return typeChecker.getTypeAtLocation( + parserServices.esTreeNodeToTSNodeMap.get(node), + ); + } + + /** + * @returns Whether the recipient type is an enum and the provided type + * unsafely provides it a number. + */ + function isProvidedTypeUnsafe( + providedType: ts.Type, + recipientType: ts.Type, + ): boolean { + // This short-circuits most logic: if the types are the same, we're happy. + if (providedType === recipientType) { + return false; + } + + // `any` types can't be reasoned with + if ( + tsutils.isTypeFlagSet(recipientType, ts.TypeFlags.Any) || + tsutils.isTypeFlagSet(providedType, ts.TypeFlags.Any) + ) { + return false; + } + + // If the two types are containers, check each matching type recursively. + // + // ```ts + // declare let fruits: Fruit[]; + // fruits = [0, 1]; + // ``` + if ( + util.isTypeReferenceType(recipientType) && + util.isTypeReferenceType(providedType) + ) { + return isProvidedReferenceValueMismatched(providedType, recipientType); + } + + // If the recipient is not an enum, we don't care about it. + const recipientEnumTypes = new Set(getEnumTypes(recipientType)); + if (recipientEnumTypes.size === 0) { + return false; + } + + const providedUnionTypes = tsutils.unionTypeParts(providedType); + + // Either every provided type should match the recipient enum... + if ( + providedUnionTypes.every(providedType => + recipientEnumTypes.has(getBaseEnumType(providedType)), + ) + ) { + return false; + } + + // ...or none of them can be an enum at all + return !providedUnionTypes.every(tsutils.isEnumType); + } + + /** + * Finds the first mismatched type reference: meaning, a non-enum type in + * the provided type compared to an enum type in the recipient type. + */ + function isProvidedReferenceValueMismatched( + providedType: ts.TypeReference, + recipientType: ts.TypeReference, + ): boolean { + const providedTypeArguments = typeChecker.getTypeArguments(providedType); + const recipientTypeArguments = + typeChecker.getTypeArguments(recipientType); + + for ( + let i = 0; + i < + Math.min(recipientTypeArguments.length, providedTypeArguments.length); + i += 1 + ) { + if ( + isProvidedTypeUnsafe( + providedTypeArguments[i], + recipientTypeArguments[i], + ) + ) { + return true; + } + } + + return false; + } + + /** + * @returns The type of the parameter to the node, accounting for generic + * type parameters. + */ + function getParameterType( + node: TSESTree.CallExpression | TSESTree.NewExpression, + signature: ts.Signature, + index: number, + ): ts.Type { + // If possible, try to find the original parameter to retrieve any generic + // type parameter. For example: + // + // ```ts + // declare function useFruit(fruitType: FruitType); + // useFruit(0) + // ``` + const parameter = signature.getDeclaration()?.parameters[index]; + if (parameter !== undefined) { + const parameterType = typeChecker.getTypeAtLocation(parameter); + const constraint = parameterType.getConstraint(); + if (constraint !== undefined) { + return constraint; + } + } + + // Failing that, defer to whatever TypeScript sees as the contextual type. + return typeChecker.getContextualTypeForArgumentAtIndex( + parserServices.esTreeNodeToTSNodeMap.get(node), + index, + ); + } + + function isMismatchedEnumFunctionArgument( + argumentType: ts.Type, + parameterType: ts.Type, + ): boolean { + // First, recursively check for functions with type containers like: + // + // ```ts + // declare function useFruits(fruits: Fruit[]); + // useFruits([0, 1]); + // ``` + if (util.isTypeReferenceType(argumentType)) { + const argumentTypeArguments = + typeChecker.getTypeArguments(argumentType); + + const parameterSubTypes = tsutils.unionTypeParts(parameterType); + for (const parameterSubType of parameterSubTypes) { + if (!util.isTypeReferenceType(parameterSubType)) { + continue; + } + const parameterTypeArguments = + typeChecker.getTypeArguments(parameterSubType); + + for (let i = 0; i < argumentTypeArguments.length; i++) { + if ( + isMismatchedEnumFunctionArgument( + argumentTypeArguments[i], + parameterTypeArguments[i], + ) + ) { + return true; + } + } + } + + return false; + } + + // Allow function calls that have nothing to do with enums, like: + // + // ```ts + // declare function useNumber(num: number); + // useNumber(0); + // ``` + const parameterEnumTypes = getEnumTypes(parameterType); + if (parameterEnumTypes.length === 0) { + return false; + } + + // Allow passing enum values into functions that take in the "any" type + // and similar types that should basically match any enum, like: + // + // ```ts + // declare function useNumber(num: number); + // useNumber(Fruit.Apple); + // ``` + const parameterSubTypes = tsutils.unionTypeParts(parameterType); + for (const parameterSubType of parameterSubTypes) { + if ( + util.isTypeFlagSet( + parameterSubType, + ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT, + ) + ) { + return false; + } + } + + // Disallow passing number literals into enum parameters, like: + // + // ```ts + // declare function useFruit(fruit: Fruit); + // declare const fruit: Fruit.Apple | 1; + // useFruit(fruit) + // ``` + return tsutils + .unionTypeParts(argumentType) + .some( + argumentSubType => + argumentSubType.isLiteral() && + !util.isTypeFlagSet(argumentSubType, ts.TypeFlags.EnumLiteral), + ); + } + + /** + * Checks whether a provided node mismatches + * + * @param provided + * @param recipient + */ + function compareProvidedNode( + provided: TSESTree.Node, + recipient: TSESTree.Node, + ): void { + const providedType = getTypeFromNode(provided); + const recipientType = getTypeFromNode(recipient); + + if (isProvidedTypeUnsafe(providedType, recipientType)) { + context.report({ + messageId: 'provided', + node: provided, + }); + } + } + + return { + AssignmentExpression(node): void { + compareProvidedNode(node.right, node.left); + }, + + 'CallExpression, NewExpression'( + node: TSESTree.CallExpression | TSESTree.NewExpression, + ): void { + const signature = typeChecker.getResolvedSignature( + parserServices.esTreeNodeToTSNodeMap.get(node), + undefined, + node.arguments.length, + )!; + + // Iterate through the arguments provided to the call function and cross + // reference their types to the types of the "real" function parameters. + for (let i = 0; i < node.arguments.length; i++) { + // any-typed arguments can be ignored altogether + const argumentType = getTypeFromNode(node.arguments[i]); + if (tsutils.isTypeFlagSet(argumentType, ts.TypeFlags.Any)) { + continue; + } + + const parameterType = getParameterType(node, signature, i); + + // Disallow mismatched function calls, like: + // + // ```ts + // declare function useFruit(fruit: Fruit); + // useFruit(0); + // ``` + if (isMismatchedEnumFunctionArgument(argumentType, parameterType)) { + context.report({ + messageId: 'provided', + node: node.arguments[i], + }); + } + } + }, + + UpdateExpression(node): void { + if (hasEnumType(getTypeFromNode(node.argument))) { + context.report({ + data: { + operator: node.operator, + }, + messageId: 'operation', + node, + }); + } + }, + + 'VariableDeclarator[init]'( + node: TSESTree.VariableDeclarator & { init: TSESTree.Expression }, + ): void { + compareProvidedNode(node.init, node.id); + }, + }; + }, +}); diff --git a/packages/eslint-plugin/src/rules/no-unsafe-enum-comparison.ts b/packages/eslint-plugin/src/rules/no-unsafe-enum-comparison.ts new file mode 100644 index 000000000000..b2b007086bca --- /dev/null +++ b/packages/eslint-plugin/src/rules/no-unsafe-enum-comparison.ts @@ -0,0 +1,271 @@ +import type { TSESTree } from '@typescript-eslint/utils'; +import * as tsutils from 'tsutils'; +import * as ts from 'typescript'; + +import * as util from '../util'; + +/** + * TypeScript only allows number enums, string enums, or mixed enums with both + * numbers and strings. + * + * Mixed enums are a union of a number enum and a string enum, so there is + * no separate kind for them. + */ +enum EnumKind { + NonEnum, + HasNumberValues, + HasStringValues, +} + +/** These bitwise operators are always considered to be safe comparisons. */ +const ALLOWED_ENUM_OPERATORS = new Set(['|=', '&=', '^=']); + +/** + * This rule can safely ignore other kinds of types (and leave the validation in + * question to the TypeScript compiler). + */ +const IMPOSSIBLE_ENUM_TYPES = + ts.TypeFlags.BooleanLike | + ts.TypeFlags.NonPrimitive | + ts.TypeFlags.ESSymbolLike; + +function getEnumKind(type: ts.Type): EnumKind { + if (!util.isTypeFlagSet(type, ts.TypeFlags.EnumLike)) { + return EnumKind.NonEnum; + } + + const isStringLiteral = util.isTypeFlagSet(type, ts.TypeFlags.StringLiteral); + const isNumberLiteral = util.isTypeFlagSet(type, ts.TypeFlags.NumberLiteral); + + if (isStringLiteral && !isNumberLiteral) { + return EnumKind.HasStringValues; + } + + if (isNumberLiteral && !isStringLiteral) { + return EnumKind.HasNumberValues; + } + + throw new Error( + 'Failed to derive the type of enum, since it did not have string values or number values.', + ); +} + +/** + * Returns a set containing the single `EnumKind` (if it is not a union), or + * a set containing N `EnumKind` (if it is a union). + */ +function getEnumKinds(type: ts.Type): Set { + return type.isUnion() + ? new Set(tsutils.unionTypeParts(type).map(getEnumKind)) + : new Set([getEnumKind(type)]); +} + +function setHasAnyElementFromSet(set1: Set, set2: Set): boolean { + for (const value of set2.values()) { + if (set1.has(value)) { + return true; + } + } + + return false; +} + +function typeHasIntersection(type: ts.Type): boolean { + return ( + type.isIntersection() || + (type.isUnion() && + tsutils.unionTypeParts(type).every(subType => subType.isIntersection())) + ); +} + +function isNullOrUndefinedOrAnyOrUnknownOrNever(...types: ts.Type[]): boolean { + return types.some(type => + util.isTypeFlagSet( + type, + ts.TypeFlags.Null | + ts.TypeFlags.Undefined | + ts.TypeFlags.Any | + ts.TypeFlags.Unknown | + ts.TypeFlags.Never, + ), + ); +} + +export default util.createRule({ + name: 'no-unsafe-enum-comparison', + meta: { + type: 'suggestion', + docs: { + description: 'Disallow comparing an enum value with a non-enum value', + recommended: 'strict', + requiresTypeChecking: true, + }, + messages: { + mismatchedComparison: + 'The two things in the comparison do not have a shared enum type.', + }, + schema: [], + }, + defaultOptions: [], + create(context) { + const parserServices = util.getParserServices(context); + const typeChecker = parserServices.program.getTypeChecker(); + + /* + * If passed an enum member, returns the type of the parent. Otherwise, + * returns itself. + * + * For example: + * - `Fruit` --> `Fruit` + * - `Fruit.Apple` --> `Fruit` + */ + function getBaseEnumType(type: ts.Type): ts.Type { + const symbol = type.getSymbol(); + if ( + symbol === undefined || + !tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.EnumMember) + ) { + return type; + } + + const { valueDeclaration } = symbol; + if (valueDeclaration === undefined) { + return type; + } + + return typeChecker.getTypeAtLocation(valueDeclaration.parent) ?? type; + } + + /** + * A type can have 0 or more enum types. For example: + * - 123 --> [] + * - {} --> [] + * - Fruit.Apple --> [Fruit] + * - Fruit.Apple | Vegetable.Lettuce --> [Fruit, Vegetable] + * - Fruit.Apple | Vegetable.Lettuce | 123 --> [Fruit, Vegetable] + * - T extends Fruit --> [Fruit] + */ + function getEnumTypes(type: ts.Type): Set { + return new Set( + tsutils + // We resolve the type (or its constituents)... + .unionTypeParts(type) + // ...to any generic constraint... + .map(subType => subType.getConstraint() ?? subType) + // ...and only look at base types of enum types + .filter(subType => + util.isTypeFlagSet(subType, ts.TypeFlags.EnumLiteral), + ) + .map(getBaseEnumType), + ); + } + + function getTypeFromNode(node: TSESTree.Node): ts.Type { + return typeChecker.getTypeAtLocation( + parserServices.esTreeNodeToTSNodeMap.get(node), + ); + } + + function isMismatchedEnumComparison( + operator: string, + leftType: ts.Type, + rightType: ts.Type, + ): boolean { + // Allow comparisons with allowlisted operators. + if (ALLOWED_ENUM_OPERATORS.has(operator)) { + return false; + } + + // Allow comparisons that don't have anything to do with enums. + const leftEnumTypes = getEnumTypes(leftType); + const rightEnumTypes = getEnumTypes(rightType); + if (leftEnumTypes.size === 0 && rightEnumTypes.size === 0) { + return false; + } + + // Allow comparisons to any intersection. Enum intersections would be rare + // in real-life code, so they are out of scope for this rule. + if (typeHasIntersection(leftType) || typeHasIntersection(rightType)) { + return false; + } + + // Allow comparisons to types that can never be an enum (like a function). + // + // (The TypeScript compiler should properly type-check these cases, so the + // lint rule is unneeded.) + if ( + util.isTypeFlagSet(leftType, IMPOSSIBLE_ENUM_TYPES) || + util.isTypeFlagSet(rightType, IMPOSSIBLE_ENUM_TYPES) + ) { + return false; + } + + // Allow exact comparisons to some standard types, like null and + // undefined. + // + // The TypeScript compiler should properly type-check these cases, so the + // lint rule is unneeded. + if (isNullOrUndefinedOrAnyOrUnknownOrNever(leftType, rightType)) { + return false; + } + + // Allow number enums to be compared with strings and string enums to be + // compared with numbers. + // + // (The TypeScript compiler should properly type-check these cases, so the + // lint rule is unneeded.) + const leftEnumKinds = getEnumKinds(leftType); + if ( + leftEnumKinds.has(EnumKind.HasStringValues) && + leftEnumKinds.size === 1 && + util.isTypeFlagSet(rightType, ts.TypeFlags.NumberLike) + ) { + return false; + } + if ( + leftEnumKinds.has(EnumKind.HasNumberValues) && + leftEnumKinds.size === 1 && + util.isTypeFlagSet(rightType, ts.TypeFlags.StringLike) + ) { + return false; + } + + const rightEnumKinds = getEnumKinds(rightType); + if ( + rightEnumKinds.has(EnumKind.HasStringValues) && + rightEnumKinds.size === 1 && + util.isTypeFlagSet(leftType, ts.TypeFlags.NumberLike) + ) { + return false; + } + if ( + rightEnumKinds.has(EnumKind.HasNumberValues) && + rightEnumKinds.size === 1 && + util.isTypeFlagSet(leftType, ts.TypeFlags.StringLike) + ) { + return false; + } + + // Disallow mismatched comparisons, like the following: + // + // ```ts + // if (fruit === 0) {} + // ``` + return setHasAnyElementFromSet(leftEnumTypes, rightEnumTypes); + } + + return { + 'BinaryExpression[operator=/=/]'(node: TSESTree.BinaryExpression): void { + const leftType = getTypeFromNode(node.left); + const rightType = getTypeFromNode(node.right); + + if (isMismatchedEnumComparison(node.operator, leftType, rightType)) { + context.report({ + messageId: 'mismatchedComparison', + node, + }); + } + }, + }; + }, +}); diff --git a/packages/eslint-plugin/src/rules/strict-enums.ts b/packages/eslint-plugin/src/rules/strict-enums.ts deleted file mode 100644 index de975c7be754..000000000000 --- a/packages/eslint-plugin/src/rules/strict-enums.ts +++ /dev/null @@ -1,568 +0,0 @@ -import type { TSESTree } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; -import * as ts from 'typescript'; - -import * as util from '../util'; - -/** - * TypeScript only allows number enums, string enums, or mixed enums with both - * numbers and strings. - * - * Mixed enums are a union of a number enum and a string enum, so there is - * no separate kind for them. - */ -enum EnumKind { - NonEnum, - HasNumberValues, - HasStringValues, -} - -/** These bitwise operators are always considered to be safe comparisons. */ -const ALLOWED_ENUM_OPERATORS = new Set(['|=', '&=', '^=']); - -/** - * This rule can safely ignore other kinds of types (and leave the validation in - * question to the TypeScript compiler). - */ -const IMPOSSIBLE_ENUM_TYPES = - ts.TypeFlags.BooleanLike | - ts.TypeFlags.NonPrimitive | - ts.TypeFlags.ESSymbolLike; - -const ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT = - ts.TypeFlags.Any | - ts.TypeFlags.Unknown | - ts.TypeFlags.Number | - ts.TypeFlags.String; - -export type Options = []; -export type MessageIds = - | 'incorrectIncrement' - | 'mismatchedAssignment' - | 'mismatchedComparison' - | 'mismatchedFunctionArgument'; - -function getEnumKind(type: ts.Type): EnumKind { - if (!util.isTypeFlagSet(type, ts.TypeFlags.EnumLike)) { - return EnumKind.NonEnum; - } - - const isStringLiteral = util.isTypeFlagSet(type, ts.TypeFlags.StringLiteral); - const isNumberLiteral = util.isTypeFlagSet(type, ts.TypeFlags.NumberLiteral); - - if (isStringLiteral && !isNumberLiteral) { - return EnumKind.HasStringValues; - } - - if (isNumberLiteral && !isStringLiteral) { - return EnumKind.HasNumberValues; - } - - throw new Error( - 'Failed to derive the type of enum, since it did not have string values or number values.', - ); -} - -/** - * Returns a set containing the single `EnumKind` (if it is not a union), or - * a set containing N `EnumKind` (if it is a union). - */ -function getEnumKinds(type: ts.Type): Set { - return type.isUnion() - ? new Set(tsutils.unionTypeParts(type).map(getEnumKind)) - : new Set([getEnumKind(type)]); -} - -function setHasAnyElementFromSet(set1: Set, set2: Set): boolean { - for (const value of set2.values()) { - if (set1.has(value)) { - return true; - } - } - - return false; -} - -function typeHasIntersection(type: ts.Type): boolean { - return ( - type.isIntersection() || - (type.isUnion() && - tsutils.unionTypeParts(type).every(subType => subType.isIntersection())) - ); -} - -function isNullOrUndefinedOrAnyOrUnknownOrNever(...types: ts.Type[]): boolean { - return types.some(type => - util.isTypeFlagSet( - type, - ts.TypeFlags.Null | - ts.TypeFlags.Undefined | - ts.TypeFlags.Any | - ts.TypeFlags.Unknown | - ts.TypeFlags.Never, - ), - ); -} - -export default util.createRule({ - name: 'strict-enums', - meta: { - type: 'suggestion', - docs: { - description: 'Disallow the usage of unsafe enum code patterns', - recommended: 'strict', - requiresTypeChecking: true, - }, - messages: { - incorrectIncrement: 'You cannot increment or decrement an enum type.', - mismatchedAssignment: - 'The type of the enum assignment does not match the declared enum type of the variable.', - mismatchedComparison: - 'The two things in the comparison do not have a shared enum type.', - mismatchedFunctionArgument: - 'Argument {{ i }} in the function call does not match the declared enum type of the function signature.', - }, - schema: [], - }, - defaultOptions: [], - create(context) { - const parserServices = util.getParserServices(context); - const typeChecker = parserServices.program.getTypeChecker(); - - /* - * If passed an enum member, returns the type of the parent. Otherwise, - * returns itself. - * - * For example: - * - `Fruit` --> `Fruit` - * - `Fruit.Apple` --> `Fruit` - */ - function getBaseEnumType(type: ts.Type): ts.Type { - const symbol = type.getSymbol(); - if ( - symbol === undefined || - !tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.EnumMember) - ) { - return type; - } - - const { valueDeclaration } = symbol; - if (valueDeclaration === undefined) { - return type; - } - - return typeChecker.getTypeAtLocation(valueDeclaration.parent) ?? type; - } - - /** - * A type can have 0 or more enum types. For example: - * - 123 --> [] - * - {} --> [] - * - Fruit.Apple --> [Fruit] - * - Fruit.Apple | Vegetable.Lettuce --> [Fruit, Vegetable] - * - Fruit.Apple | Vegetable.Lettuce | 123 --> [Fruit, Vegetable] - * - T extends Fruit --> [Fruit] - */ - function getEnumTypes(type: ts.Type): Set { - return new Set( - tsutils - // We resolve the type (or its constituents)... - .unionTypeParts(type) - // ...to any generic constraint... - .map(subType => subType.getConstraint() ?? subType) - // ...and only look at base types of enum types - .filter(subType => - util.isTypeFlagSet(subType, ts.TypeFlags.EnumLiteral), - ) - .map(getBaseEnumType), - ); - } - - function getTypeFromNode(node: TSESTree.Node): ts.Type { - return typeChecker.getTypeAtLocation( - parserServices.esTreeNodeToTSNodeMap.get(node), - ); - } - - function checkCallOrNewExpression( - node: TSESTree.CallExpression | TSESTree.NewExpression, - ): void { - const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); - const signature = typeChecker.getResolvedSignature(tsNode); - if (signature === undefined) { - return; - } - - const declaration = signature.getDeclaration(); - if (declaration === undefined) { - return; - } - - // Iterate through the arguments provided to the call function and cross - // reference their types to the types of the "real" function parameters. - for (let i = 0; i < node.arguments.length; i++) { - const argument = node.arguments[i]; - const argumentType = getTypeFromNode(argument); - let parameterType = signature.getTypeParameterAtPosition(i); - - // If this function parameter is a generic type that extends another - // type, we want to compare the calling argument to the constraint - // instead. - // - // For example: - // - // ```ts - // function useFruit(fruitType: FruitType) {} - // useFruit(0) - // ``` - // - // Here, we want to compare `Fruit.Apple` to `Fruit`, not `FruitType`, - // because `FruitType` would just be equal to 0 in this case (and - // would be unsafe). - const parameter = declaration.parameters[i]; - if (parameter !== undefined) { - const parameterTSNode = typeChecker.getTypeAtLocation(parameter); - const constraint = parameterTSNode.getConstraint(); - if (constraint !== undefined) { - parameterType = constraint; - } - } - - // Disallow mismatched function calls, like the following: - // - // ```ts - // function useFruit(fruit: Fruit) {} - // useFruit(0); - // ``` - if (isMismatchedEnumFunctionArgument(argumentType, parameterType)) { - context.report({ - node: node.arguments[i], - messageId: 'mismatchedFunctionArgument', - data: { i }, - }); - } - } - } - - function isAssigningNonEnumValueToEnumVariable( - leftType: ts.Type, - rightType: ts.Type, - ): boolean { - // First, recursively check for containers like the following: - // - // ```ts - // declare let fruits: Fruit[]; - // fruits = [0, 1]; - // ``` - if ( - util.isTypeReferenceType(leftType) && - util.isTypeReferenceType(rightType) - ) { - const leftTypeArguments = typeChecker.getTypeArguments(leftType); - const rightTypeArguments = typeChecker.getTypeArguments(rightType); - - for ( - let i = 0; - i < Math.min(leftTypeArguments.length, rightTypeArguments.length); - i += 1 - ) { - if ( - isAssigningNonEnumValueToEnumVariable( - leftTypeArguments[i], - rightTypeArguments[i], - ) - ) { - return true; - } - } - - return false; - } - - // If the recipient is not an enum, this is not an enum assignment. - const leftEnumTypes = getEnumTypes(leftType); - if (leftEnumTypes.size === 0) { - return false; - } - - // As a special case, allow assignment of bottom and top types that the - // TypeScript compiler should handle properly. - if (isNullOrUndefinedOrAnyOrUnknownOrNever(rightType)) { - return false; - } - - return setHasAnyElementFromSet(leftEnumTypes, getEnumTypes(rightType)); - } - - function isMismatchedEnumComparison( - operator: string, - leftType: ts.Type, - rightType: ts.Type, - ): boolean { - // Allow comparisons with allowlisted operators. - if (ALLOWED_ENUM_OPERATORS.has(operator)) { - return false; - } - - // Allow comparisons that don't have anything to do with enums. - const leftEnumTypes = getEnumTypes(leftType); - const rightEnumTypes = getEnumTypes(rightType); - if (leftEnumTypes.size === 0 && rightEnumTypes.size === 0) { - return false; - } - - // Allow comparisons to any intersection. Enum intersections would be rare - // in real-life code, so they are out of scope for this rule. - if (typeHasIntersection(leftType) || typeHasIntersection(rightType)) { - return false; - } - - // Allow comparisons to types that can never be an enum (like a function). - // - // (The TypeScript compiler should properly type-check these cases, so the - // lint rule is unneeded.) - if ( - util.isTypeFlagSet(leftType, IMPOSSIBLE_ENUM_TYPES) || - util.isTypeFlagSet(rightType, IMPOSSIBLE_ENUM_TYPES) - ) { - return false; - } - - // Allow exact comparisons to some standard types, like null and - // undefined. - // - // The TypeScript compiler should properly type-check these cases, so the - // lint rule is unneeded. - if (isNullOrUndefinedOrAnyOrUnknownOrNever(leftType, rightType)) { - return false; - } - - // Allow number enums to be compared with strings and string enums to be - // compared with numbers. - // - // (The TypeScript compiler should properly type-check these cases, so the - // lint rule is unneeded.) - const leftEnumKinds = getEnumKinds(leftType); - if ( - leftEnumKinds.has(EnumKind.HasStringValues) && - leftEnumKinds.size === 1 && - util.isTypeFlagSet(rightType, ts.TypeFlags.NumberLike) - ) { - return false; - } - if ( - leftEnumKinds.has(EnumKind.HasNumberValues) && - leftEnumKinds.size === 1 && - util.isTypeFlagSet(rightType, ts.TypeFlags.StringLike) - ) { - return false; - } - - const rightEnumKinds = getEnumKinds(rightType); - if ( - rightEnumKinds.has(EnumKind.HasStringValues) && - rightEnumKinds.size === 1 && - util.isTypeFlagSet(leftType, ts.TypeFlags.NumberLike) - ) { - return false; - } - if ( - rightEnumKinds.has(EnumKind.HasNumberValues) && - rightEnumKinds.size === 1 && - util.isTypeFlagSet(leftType, ts.TypeFlags.StringLike) - ) { - return false; - } - - // Disallow mismatched comparisons, like the following: - // - // ```ts - // if (fruit === 0) {} - // ``` - return setHasAnyElementFromSet(leftEnumTypes, rightEnumTypes); - } - - function isMismatchedEnumFunctionArgument( - argumentType: ts.Type, // From the function call - parameterType: ts.Type, // From the function itself - ): boolean { - // First, recursively check for functions with type containers like the - // following: - // - // ```ts - // function useFruits(fruits: Fruit[]) {} - // useFruits([0, 1]); - // ``` - if (util.isTypeReferenceType(argumentType)) { - const argumentTypeArguments = - typeChecker.getTypeArguments(argumentType); - - const parameterSubTypes = tsutils.unionTypeParts(parameterType); - for (const parameterSubType of parameterSubTypes) { - if (!util.isTypeReferenceType(parameterSubType)) { - continue; - } - const parameterTypeArguments = - typeChecker.getTypeArguments(parameterSubType); - - for (let i = 0; i < argumentTypeArguments.length; i++) { - const argumentTypeArgument = argumentTypeArguments[i]; - const parameterTypeArgument = parameterTypeArguments[i]; - if ( - argumentTypeArgument === undefined || - parameterTypeArgument === undefined - ) { - continue; - } - - if ( - isMismatchedEnumFunctionArgument( - argumentTypeArgument, - parameterTypeArgument, - ) - ) { - return true; - } - } - } - - return false; - } - - // Allow function calls that have nothing to do with enums, like the - // following: - // - // ```ts - // function useNumber(num: number) {} - // useNumber(0); - // ``` - const parameterEnumTypes = getEnumTypes(parameterType); - if (parameterEnumTypes.size === 0) { - return false; - } - - // Allow passing enum values into functions that take in the "any" type - // and similar types that should basically match any enum, like the - // following: - // - // ```ts - // function useNumber(num: number) {} - // useNumber(Fruit.Apple); - // ``` - const parameterSubTypes = tsutils.unionTypeParts(parameterType); - for (const parameterSubType of parameterSubTypes) { - if ( - util.isTypeFlagSet( - parameterSubType, - ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT, - ) - ) { - return false; - } - } - - // Disallow passing number literals or string literals into functions that - // take in an enum, like the following: - // - // ```ts - // function useFruit(fruit: Fruit) {} - // declare const fruit: Fruit.Apple | 1; - // useFruit(fruit) - // ``` - const argumentSubTypes = tsutils.unionTypeParts(argumentType); - for (const argumentSubType of argumentSubTypes) { - if ( - argumentSubType.isLiteral() && - !util.isTypeFlagSet(argumentSubType, ts.TypeFlags.EnumLiteral) - ) { - return true; - } - } - - // Allow function calls that match one of the types in a union, like the - // following: - // - // ```ts - // function useApple(fruitOrNull: Fruit | null) {} - // useApple(null); - // ``` - const argumentSubTypesSet = new Set(argumentSubTypes); - const parameterSubTypesSet = new Set(parameterSubTypes); - if (setHasAnyElementFromSet(argumentSubTypesSet, parameterSubTypesSet)) { - return false; - } - - // Allow function calls that have a base enum that match the function - // type, like the following: - // - // ```ts - // function useFruit(fruit: Fruit) {} - // useFruit(Fruit.Apple); - // ``` - if ( - setHasAnyElementFromSet(getEnumTypes(argumentType), parameterEnumTypes) - ) { - return false; - } - - return true; - } - - return { - AssignmentExpression(node): void { - const leftType = getTypeFromNode(node.left); - const rightType = getTypeFromNode(node.right); - - if (isAssigningNonEnumValueToEnumVariable(leftType, rightType)) { - context.report({ - messageId: 'mismatchedAssignment', - node, - }); - } - }, - - 'BinaryExpression[operator=/=/]'(node: TSESTree.BinaryExpression): void { - const leftType = getTypeFromNode(node.left); - const rightType = getTypeFromNode(node.right); - - if (isMismatchedEnumComparison(node.operator, leftType, rightType)) { - context.report({ - messageId: 'mismatchedComparison', - node, - }); - } - }, - - 'CallExpression, NewExpression': checkCallOrNewExpression, - - UpdateExpression(node): void { - // Disallow using enums with unary operators, like the following: - // - // ```ts - // const fruit = Fruit.Apple; - // fruit++; - // ``` - if (getEnumTypes(getTypeFromNode(node.argument)).size > 0) { - context.report({ - messageId: 'incorrectIncrement', - node, - }); - } - }, - - 'VariableDeclarator[init]'( - node: TSESTree.VariableDeclarator & { init: TSESTree.Expression }, - ): void { - const leftType = getTypeFromNode(node.id); - const rightType = getTypeFromNode(node.init); - - if (isAssigningNonEnumValueToEnumVariable(leftType, rightType)) { - context.report({ - messageId: 'mismatchedAssignment', - node, - }); - } - }, - }; - }, -}); diff --git a/packages/eslint-plugin/tests/rules/no-unsafe-enum-assignment.test.ts b/packages/eslint-plugin/tests/rules/no-unsafe-enum-assignment.test.ts new file mode 100644 index 000000000000..ac49cace1d41 --- /dev/null +++ b/packages/eslint-plugin/tests/rules/no-unsafe-enum-assignment.test.ts @@ -0,0 +1,426 @@ +import rule from '../../src/rules/no-unsafe-enum-assignment'; +import { getFixturesRootDir, RuleTester } from '../RuleTester'; + +const rootDir = getFixturesRootDir(); + +const ruleTester = new RuleTester({ + parserOptions: { + ecmaVersion: 2015, + tsconfigRootDir: rootDir, + project: './tsconfig.json', + }, + parser: '@typescript-eslint/parser', +}); + +ruleTester.run('no-unsafe-enum-assignment', rule, { + valid: [ + ` + let fruit = 0; + fruit++; + `, + ` + let fruit = 1; + fruit--; + `, + ` + let fruit = 0; + ++fruit; + `, + ` + let fruit = 1; + --fruit; + `, + ` + let fruit = 1; + ~fruit; + `, + ` + let fruit = 1; + !fruit; + `, + ` + let fruit = 0; + fruit += 1; + `, + ` + let fruit = 0; + fruit *= 1; + `, + ` + let fruit = 0; + fruit /= 1; + `, + ` + let fruit = 1; + fruit -= 1; + `, + ` + enum Fruit { + Apple, + } + let fruit = Fruit.Apple; + !fruit; + `, + ` + enum Fruit { + Apple, + } + let fruits: Fruit[]; + fruits = [Fruit.Apple]; + `, + ` + enum Fruit { + Apple, + } + let fruit = Fruit.Apple; + fruit = Fruit.Apple; + `, + ` + enum Fruit { + Apple, + } + let fruit: Fruit; + fruit = Fruit.Apple; + `, + ` + enum Fruit { + Apple, + } + let fruit; + fruit = Fruit.Apple; + `, + ` + enum Fruit { + Apple, + Banana, + } + let fruits: Fruit[]; + fruits = [Fruit.Apple, Fruit.Banana]; + `, + ` + enum Fruit { + Apple, + } + declare function useFruit(fruit: Fruit): void; + useFruit(Fruit.Apple); + `, + ` + enum Fruit { + Apple, + Banana = '', + } + declare function useFruit(fruit: Fruit.Apple): void; + useFruit(Fruit.Apple); + `, + ` + enum Fruit { + Apple = 0, + Banana = '', + } + declare function useFruit(fruit: Fruit | any): void; + useFruit(1); + `, + ` + enum Fruit { + Apple = 0, + Banana = '', + } + declare function useFruit(fruit: Fruit | number): void; + useFruit(1); + `, + ` + enum Fruit { + Apple = 0, + Banana = '', + } + declare function useFruit(fruit: Fruit | string): void; + useFruit(1); + `, + ` + enum Fruit { + Apple, + } + declare function useFruit(fruit: Fruit | null): void; + useFruit(Fruit.Apple); + `, + ` + enum Fruit { + Apple, + } + declare function useFruit(fruit: Fruit | string): void; + useFruit(Math.random() > 0.5 ? Fruit.Apple : ''); + `, + ` + enum Fruit { + Apple, + Banana, + } + declare function useFruit(fruit: Fruit): void; + useFruit(Math.random() > 0.5 ? Fruit.Apple : Fruit.Banana); + `, + ` + enum Fruit { + Apple, + } + declare function useFruit(fruit: Fruit | null): void; + useFruit(Math.random() > 0.5 ? Fruit.Apple : null); + `, + ` + enum Fruit { + Apple, + } + declare function useFruit(fruit: Fruit): void; + useFruit({} as any); + `, + ` + enum Fruit { + Apple, + } + declare function useFruit(fruit: Fruit | undefined): void; + useFruit(undefined); + `, + ` + enum Fruit { + Apple, + } + declare function useFruits(fruits: Fruit[]): void; + useFruit([Fruit.Apple]); + `, + ` + enum Fruit { + Apple, + Banana, + } + declare function useFruits(...fruits: Fruit[]): void; + useFruit(Fruit.Apple, Fruit.Banana); + `, + ], + invalid: [ + { + code: ` + enum Fruit { + Apple, + } + let fruit = Fruit.Apple; + fruit++; + `, + errors: [{ data: { operator: '++' }, messageId: 'operation' }], + }, + { + code: ` + enum Fruit { + Apple, + } + let fruit = Fruit.Apple; + fruit--; + `, + errors: [{ data: { operator: '--' }, messageId: 'operation' }], + }, + { + code: ` + enum Fruit { + Apple, + } + let fruit = Fruit.Apple; + ++fruit; + `, + errors: [{ data: { operator: '++' }, messageId: 'operation' }], + }, + { + code: ` + enum Fruit { + Apple, + } + let fruit = Fruit.Apple; + --fruit; + `, + errors: [{ data: { operator: '--' }, messageId: 'operation' }], + }, + { + code: ` + enum Fruit { + Apple, + } + let fruit = Fruit.Apple; + fruit += 1; + `, + + errors: [{ messageId: 'provided' }], + }, + { + code: ` + enum Fruit { + Apple, + } + let fruit = Fruit.Apple; + fruit -= 1; + `, + + errors: [{ messageId: 'provided' }], + }, + { + code: ` + enum Fruit { + Apple, + } + let fruit = Fruit.Apple; + fruit = 1; + `, + errors: [ + { + column: 17, + endColumn: 18, + line: 6, + messageId: 'provided', + }, + ], + }, + { + code: ` + enum Fruit { + Apple, + } + let fruits: Fruit[]; + fruits = [0]; + `, + errors: [ + { + column: 18, + endColumn: 21, + line: 6, + messageId: 'provided', + }, + ], + }, + { + code: ` + enum Fruit { + Apple, + } + let fruits: Fruit[]; + fruits = [0, 1]; + `, + errors: [ + { + column: 18, + endColumn: 24, + line: 6, + messageId: 'provided', + }, + ], + }, + { + code: ` + enum Fruit { + Apple, + } + let fruits: Fruit[]; + fruits = [0, Fruit.Apple]; + `, + errors: [ + { + column: 18, + endColumn: 34, + line: 6, + messageId: 'provided', + }, + ], + }, + { + code: ` + enum Fruit { + Apple, + } + declare function useFruit(fruit: Fruit): void; + useFruit(0); + `, + errors: [ + { + column: 18, + endColumn: 19, + line: 6, + messageId: 'provided', + }, + ], + }, + { + code: ` + enum Fruit { + Apple, + } + declare function useFruit(fruit: FruitType): void; + useFruit(0); + `, + errors: [ + { + column: 18, + endColumn: 19, + line: 6, + messageId: 'provided', + }, + ], + }, + { + code: ` + enum Fruit { + Apple, + } + declare function useFruits(fruits: Fruit[]): void; + useFruits([0]); + `, + errors: [ + { + column: 19, + endColumn: 22, + line: 6, + messageId: 'provided', + }, + ], + }, + { + code: ` + enum Fruit { + Apple, + } + declare function useFruits(fruits: Fruit[]): void; + useFruits([0, Fruit.Apple]); + `, + errors: [ + { + column: 19, + endColumn: 35, + line: 6, + messageId: 'provided', + }, + ], + }, + { + code: ` + enum Fruit { + Apple, + } + declare function useFruits(...fruits: Fruit[]): void; + useFruits(0); + `, + errors: [ + { + column: 19, + endColumn: 20, + line: 6, + messageId: 'provided', + }, + ], + }, + ], +}); + +// recursive types: +// different number of type arguments, each way? (2 tests) + +// assignments: +// number literals and unions thereof +// with Math.random() +// [number][] +// Set +// Map +// Map, Set> diff --git a/packages/eslint-plugin/tests/rules/strict-enums/shared.ts b/packages/eslint-plugin/tests/rules/strict-enums/shared.ts index fa651196ab37..1243d051f246 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/shared.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/shared.ts @@ -12,11 +12,7 @@ export const strictEnumsRuleTester = new RuleTester({ /** A number enum. */ export const fruitEnumDefinition = ` -enum Fruit { - Apple, - Banana, - Pear, -} +enum Fruit { Apple, Banana, Cherry } `; /** A different number enum. */ @@ -24,7 +20,7 @@ export const fruit2EnumDefinition = ` enum Fruit2 { Apple2, Banana2, - Pear2, + Cherry2, } `; diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts deleted file mode 100644 index dd51e49647e1..000000000000 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-assignment.test.ts +++ /dev/null @@ -1,235 +0,0 @@ -import rule from '../../../src/rules/strict-enums'; -import { - fruit2EnumDefinition, - fruitEnumDefinition, - strictEnumsRuleTester, -} from './shared'; - -strictEnumsRuleTester.run('strict-enums-assignment', rule, { - valid: [ - { - code: - fruitEnumDefinition + - ` - let fruit: Fruit; - if (true) { - fruit = Fruit.Apple; - } else { - fruit = Fruit.Banana; - } - `, - }, - { - code: ` -const myArray = [1]; -const [firstElement] = myArray; - `, - }, - { - code: - fruitEnumDefinition + - ` -const fruit = Fruit.Apple; - `, - }, - { - code: - fruitEnumDefinition + - ` -const fruit: Fruit = Fruit.Apple; - `, - }, - { - code: - fruitEnumDefinition + - ` -const apple = Fruit.Apple; -const fruit: Fruit = apple; - `, - }, - { - code: - fruitEnumDefinition + - ` - let fruit = Fruit.Apple; - fruit = Fruit.Banana; - `, - }, - { - code: - fruitEnumDefinition + - ` - const fruit: Fruit | null = Fruit.Apple; - `, - }, - { - code: - fruitEnumDefinition + - ` - const fruit: Fruit | null = null; - `, - }, - { - code: - fruitEnumDefinition + - ` - let fruit: Fruit | null = null; - fruit = Fruit.Apple; - `, - }, - { - code: - fruitEnumDefinition + - ` - let fruit: Fruit | null = Fruit.Apple; - fruit = null; - `, - }, - { - code: ` -enum Foo { - A = 1, - B = 2, - C = 3, - D = 4, -} - -declare const foo: Foo; -declare const fooSubset: Foo.A | Foo.B | Foo.C; -const x: Foo = fooSubset; -const y: Foo.A | Foo.B | Foo.C = fooSubset; -const z: Foo.A | Foo.B | Foo.C | Foo.D = foo; - `, - }, - { - // Intersection types are always allowed - - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` -const foo: Fruit & Fruit2 = Fruit.Apple; - `, - }, - { - code: ` -enum Flag { - Value1 = 1 << 0, - Value2 = 1 << 1, -} -const flags = Flag.Value1 | Flag.Value2; - `, - }, - { - code: - fruitEnumDefinition + - ` - declare let fruits: Fruit[]; - fruits = [Fruit.Apple, Fruit.Banana]; - `, - }, - { - code: - fruitEnumDefinition + - ` - declare let numbers: number[]; - numbers = [Fruit.Apple, Fruit.Banana]; - `, - }, - { - code: - fruitEnumDefinition + - ` - const fruitArray: Fruit[] = []; - `, - }, - { - code: - fruitEnumDefinition + - ` - const fruitFlags = Fruit.Apple | Fruit.Banana; - `, - }, - ], - invalid: [ - { - code: - fruitEnumDefinition + - ` - const fruit: Fruit = 0; - `, - errors: [{ messageId: 'mismatchedAssignment' }], - }, - { - code: - fruitEnumDefinition + - ` - let fruit = Fruit.Apple; - fruit = 1; - `, - errors: [{ messageId: 'mismatchedAssignment' }], - }, - { - code: - fruitEnumDefinition + - ` - const fruit: Fruit = Fruit; - `, - errors: [{ messageId: 'mismatchedAssignment' }], - }, - { - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` - const fruit: Fruit = Fruit2.Apple2; - `, - errors: [{ messageId: 'mismatchedAssignment' }], - }, - { - code: - fruitEnumDefinition + - ` - const fruit: Fruit | null = 0; - `, - errors: [{ messageId: 'mismatchedAssignment' }], - }, - { - code: - fruitEnumDefinition + - ` - let fruit: Fruit | null = null; - fruit = 0; - `, - errors: [{ messageId: 'mismatchedAssignment' }], - }, - { - code: - fruitEnumDefinition + - ` - declare const fruit: Fruit | number; - const fruitCopy: Fruit = fruit; - `, - errors: [{ messageId: 'mismatchedAssignment' }], - }, - { - code: - fruitEnumDefinition + - ` - declare let fruits: Fruit[]; - fruits = [0, 1]; - `, - errors: [{ messageId: 'mismatchedAssignment' }], - }, - { - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` - declare let fruits: Fruit[]; - fruits = [Fruit2.Apple2, Fruit2.Banana2]; - `, - errors: [{ messageId: 'mismatchedAssignment' }], - }, - ], -}); diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts index 1a078593af6b..3b19d35d04d3 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts @@ -1,4 +1,4 @@ -import rule from '../../../src/rules/strict-enums'; +import rule from '../../../src/rules/no-unsafe-enum-comparison'; import { fruit2EnumDefinition, fruitEnumDefinition, diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts index 7af6ce0d0310..10dac23c8341 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts @@ -1,4 +1,4 @@ -import rule from '../../../src/rules/strict-enums'; +import rule from '../../../src/rules/no-unsafe-enum-comparison'; import { fruitEnumDefinition, strictEnumsRuleTester, diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-incrementing.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-incrementing.test.ts deleted file mode 100644 index c2cde406ff73..000000000000 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-incrementing.test.ts +++ /dev/null @@ -1,111 +0,0 @@ -import rule from '../../../src/rules/strict-enums'; -import { fruitEnumDefinition, strictEnumsRuleTester } from './shared'; - -strictEnumsRuleTester.run('strict-enums-incrementing', rule, { - valid: [ - { - code: - fruitEnumDefinition + - ` -let fruit = 0; -fruit++; - `, - }, - { - code: - fruitEnumDefinition + - ` -let fruit = 1; -fruit--; - `, - }, - { - code: - fruitEnumDefinition + - ` -let fruit = 0; -++fruit; - `, - }, - { - code: - fruitEnumDefinition + - ` -let fruit = 1; ---fruit - `, - }, - { - code: - fruitEnumDefinition + - ` -let fruit = 0; -fruit += 1; - `, - }, - { - code: - fruitEnumDefinition + - ` -let fruit = 1; -fruit -= 1; - `, - }, - ], - invalid: [ - { - code: - fruitEnumDefinition + - ` - let fruit = Fruit.Apple; - fruit++; - `, - errors: [{ messageId: 'incorrectIncrement' }], - }, - { - code: - fruitEnumDefinition + - ` - let fruit = Fruit.Banana; - fruit--; - `, - errors: [{ messageId: 'incorrectIncrement' }], - }, - { - code: - fruitEnumDefinition + - ` - let fruit = Fruit.Apple; - ++fruit; - `, - errors: [{ messageId: 'incorrectIncrement' }], - }, - { - code: - fruitEnumDefinition + - ` - let fruit = Fruit.Banana; - --fruit; - `, - errors: [{ messageId: 'incorrectIncrement' }], - }, - { - code: - fruitEnumDefinition + - ` - let fruit = Fruit.Apple; - fruit += 1; - `, - errors: [{ messageId: 'mismatchedAssignment' }], - }, - { - code: - fruitEnumDefinition + - ` - let fruit = Fruit.Banana; - fruit -= 1; - `, - errors: [{ messageId: 'mismatchedAssignment' }], - }, - ], -}); diff --git a/packages/eslint-plugin/typings/typescript.d.ts b/packages/eslint-plugin/typings/typescript.d.ts index 0f0b38a5ba6f..e08a8fb42267 100644 --- a/packages/eslint-plugin/typings/typescript.d.ts +++ b/packages/eslint-plugin/typings/typescript.d.ts @@ -4,6 +4,8 @@ declare module 'typescript' { interface TypeChecker { // internal TS APIs + getContextualTypeForArgumentAtIndex(node: Node, argIndex: number): Type; + /** * @returns `true` if the given type is an array type: * - `Array` From a3e623648c38c1c35967cc02dd3b9ed1fd9a14e6 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 26 Nov 2022 19:02:25 -0500 Subject: [PATCH 82/88] A bit more testing for assignments, as requested --- .../src/rules/no-unsafe-enum-assignment.ts | 22 +- .../src/rules/no-unsafe-enum-comparison.ts | 19 +- .../rules/no-unsafe-enum-assignment.test.ts | 53 + ...t.ts => no-unsafe-enum-comparison.test.ts} | 4 +- .../strict-enums-functions.test.ts | 912 ------------------ 5 files changed, 76 insertions(+), 934 deletions(-) rename packages/eslint-plugin/tests/rules/{strict-enums/strict-enums-comparison.test.ts => no-unsafe-enum-comparison.test.ts} (98%) delete mode 100644 packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts diff --git a/packages/eslint-plugin/src/rules/no-unsafe-enum-assignment.ts b/packages/eslint-plugin/src/rules/no-unsafe-enum-assignment.ts index d75f6ce01fb2..412b12676e33 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-enum-assignment.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-enum-assignment.ts @@ -254,7 +254,7 @@ export default util.createRule({ // declare function useNumber(num: number); // useNumber(Fruit.Apple); // ``` - const parameterSubTypes = tsutils.unionTypeParts(parameterType); + const parameterSubTypes = new Set(tsutils.unionTypeParts(parameterType)); for (const parameterSubType of parameterSubTypes) { if ( util.isTypeFlagSet( @@ -273,13 +273,19 @@ export default util.createRule({ // declare const fruit: Fruit.Apple | 1; // useFruit(fruit) // ``` - return tsutils - .unionTypeParts(argumentType) - .some( - argumentSubType => - argumentSubType.isLiteral() && - !util.isTypeFlagSet(argumentSubType, ts.TypeFlags.EnumLiteral), - ); + return tsutils.unionTypeParts(argumentType).some( + argumentSubType => + argumentSubType.isLiteral() && + !util.isTypeFlagSet(argumentSubType, ts.TypeFlags.EnumLiteral) && + // Permit the argument if it's a number the parameter allows, like: + // + // ```ts + // declare function useFruit(fruit: Fruit | -1); + // useFruit(-1) + // ``` + // that's ok too + !parameterSubTypes.has(argumentSubType), + ); } /** diff --git a/packages/eslint-plugin/src/rules/no-unsafe-enum-comparison.ts b/packages/eslint-plugin/src/rules/no-unsafe-enum-comparison.ts index b2b007086bca..ddb439258ca5 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-enum-comparison.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-enum-comparison.ts @@ -12,9 +12,10 @@ import * as util from '../util'; * no separate kind for them. */ enum EnumKind { - NonEnum, + HasBothValues, HasNumberValues, HasStringValues, + NonEnum, } /** These bitwise operators are always considered to be safe comparisons. */ @@ -37,17 +38,11 @@ function getEnumKind(type: ts.Type): EnumKind { const isStringLiteral = util.isTypeFlagSet(type, ts.TypeFlags.StringLiteral); const isNumberLiteral = util.isTypeFlagSet(type, ts.TypeFlags.NumberLiteral); - if (isStringLiteral && !isNumberLiteral) { - return EnumKind.HasStringValues; - } - - if (isNumberLiteral && !isStringLiteral) { - return EnumKind.HasNumberValues; - } - - throw new Error( - 'Failed to derive the type of enum, since it did not have string values or number values.', - ); + return isNumberLiteral + ? isStringLiteral + ? EnumKind.HasBothValues + : EnumKind.HasNumberValues + : EnumKind.HasStringValues; } /** diff --git a/packages/eslint-plugin/tests/rules/no-unsafe-enum-assignment.test.ts b/packages/eslint-plugin/tests/rules/no-unsafe-enum-assignment.test.ts index ac49cace1d41..c2e0f5c8f770 100644 --- a/packages/eslint-plugin/tests/rules/no-unsafe-enum-assignment.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unsafe-enum-assignment.test.ts @@ -112,6 +112,13 @@ ruleTester.run('no-unsafe-enum-assignment', rule, { declare function useFruit(fruit: Fruit.Apple): void; useFruit(Fruit.Apple); `, + ` + enum Fruit { + Apple, + } + declare function useFruit(fruit: Fruit | -1): void; + useFruit(-1); + `, ` enum Fruit { Apple = 0, @@ -179,6 +186,27 @@ ruleTester.run('no-unsafe-enum-assignment', rule, { declare function useFruit(fruit: Fruit | undefined): void; useFruit(undefined); `, + ` + enum Fruit { + Apple, + } + declare function useFruit(fruit: Fruit, a: number): void; + useFruit(Fruit.Apple, -1); + `, + ` + enum Fruit { + Apple, + } + declare function useFruit(fruit: Fruit, a: number, b: number): void; + useFruit(Fruit.Apple, -1, -1); + `, + ` + enum Fruit { + Apple, + } + declare function useFruit(a: number, fruit: Fruit, b: number): void; + useFruit(-1, Fruit.Apple, -1); + `, ` enum Fruit { Apple, @@ -194,6 +222,14 @@ ruleTester.run('no-unsafe-enum-assignment', rule, { declare function useFruits(...fruits: Fruit[]): void; useFruit(Fruit.Apple, Fruit.Banana); `, + ` + enum Fruit { + Apple, + Banana, + } + declare function useFruits(a: number, ...fruits: Fruit[]): void; + useFruit(1, Fruit.Apple, Fruit.Banana); + `, ], invalid: [ { @@ -411,6 +447,23 @@ ruleTester.run('no-unsafe-enum-assignment', rule, { }, ], }, + { + code: ` + enum Fruit { + Apple, + } + declare function useFruits(a: number, ...fruits: Fruit[]): void; + useFruits(0, Fruit.Apple, 0); + `, + errors: [ + { + column: 35, + endColumn: 36, + line: 6, + messageId: 'provided', + }, + ], + }, ], }); diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts b/packages/eslint-plugin/tests/rules/no-unsafe-enum-comparison.test.ts similarity index 98% rename from packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts rename to packages/eslint-plugin/tests/rules/no-unsafe-enum-comparison.test.ts index 3b19d35d04d3..653788ee8766 100644 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unsafe-enum-comparison.test.ts @@ -1,11 +1,11 @@ -import rule from '../../../src/rules/no-unsafe-enum-comparison'; +import rule from '../../src/rules/no-unsafe-enum-comparison'; import { fruit2EnumDefinition, fruitEnumDefinition, strictEnumsRuleTester, vegetable2EnumDefinition, vegetableEnumDefinition, -} from './shared'; +} from './strict-enums/shared'; strictEnumsRuleTester.run('strict-enums-comparison', rule, { valid: [ diff --git a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts b/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts deleted file mode 100644 index 10dac23c8341..000000000000 --- a/packages/eslint-plugin/tests/rules/strict-enums/strict-enums-functions.test.ts +++ /dev/null @@ -1,912 +0,0 @@ -import rule from '../../../src/rules/no-unsafe-enum-comparison'; -import { - fruitEnumDefinition, - strictEnumsRuleTester, - vegetableEnumDefinition, -} from './shared'; - -/** A function that takes a number enum. */ -const fruitFunctionDefinition = - fruitEnumDefinition + - ` -function useFruit(fruit: Fruit) {} -`; - -strictEnumsRuleTester.run('strict-enums-functions', rule, { - valid: [ - { - code: ` -useFruit(0); - `, - }, - - { - code: - fruitFunctionDefinition + - ` - useFruit(Fruit.Apple); - `, - }, - - { - code: - fruitFunctionDefinition + - ` - declare const fruit: Fruit.Apple; - useFruit(fruit); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple) {} - useFruit(Fruit.Apple); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple) {} - useFruit(Fruit.Banana); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple) {} - declare const fruit: Fruit.Apple; - useFruit(fruit); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple) {} - declare const fruit: Fruit.Banana; - useFruit(fruit); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit = Fruit.Apple) {} - useFruit(Fruit.Apple); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit = Fruit.Apple) {} - const fruit = Fruit.Apple; - useFruit(fruit); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} - useFruit(Fruit.Apple); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} - const fruit = Fruit.Apple; - useFruit(fruit); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit | null) {} - useFruit(Fruit.Apple); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit | null) {} - const fruit = Fruit.Apple; - useFruit(fruit); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit | null) {} - useFruit(null); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit | null) {} - const fruit = null; - useFruit(fruit); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit | null = Fruit.Apple) {} - useFruit(Fruit.Apple); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit | null = Fruit.Apple) {} - const fruit = Fruit.Apple; - useFruit(fruit); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit | null = Fruit.Apple) {} - useFruit(null); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit | null = Fruit.Apple) {} - const fruit = null; - useFruit(fruit); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple | null) {} - useFruit(Fruit.Apple); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple | null) {} - const fruit = Fruit.Apple; - useFruit(fruit); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple | null) {} - useFruit(null); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple | null) {} - const fruit = null; - useFruit(fruit); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} - useFruit(Fruit.Apple); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} - const fruit = Fruit.Apple; - useFruit(fruit); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} - useFruit(null); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} - const fruit = null; - useFruit(fruit); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} - useFruit(Fruit.Apple); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} - const fruit = Fruit.Apple; - useFruit(fruit); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} - useFruit(null); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} - const fruit = null; - useFruit(fruit); - `, - }, - - { - code: - fruitEnumDefinition + - ` - interface BaseNode { - type: Fruit; - } - - interface AppleNode extends BaseNode { - type: Fruit.Apple; - apple: number; - } - - interface BananaNode extends BaseNode { - type: Fruit.Apple; - banana: Number; - } - - type Node = AppleNode | BananaNode; - - const fruitNodesSet = new Set([ - Fruit.Apple, - Fruit.Banana, - ]); - - const appleNode: AppleNode = { - type: Fruit.Apple, - apple: 1, - }; - - fruitNodesSet.has(appleNode.type); - `, - }, - - { - code: - fruitEnumDefinition + - ` - const fruitSet = new Set([ - Fruit.Apple, - Fruit.Banana, - ]); - - fruitSet.has(Fruit.Apple); - `, - }, - - { - code: - fruitFunctionDefinition + - ` - declare const fruitUnion: Fruit.Apple | Fruit.Banana; - useFruit(fruitUnion); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple | Fruit.Banana) {} - declare const fruitUnion: Fruit.Apple | Fruit.Banana; - useFruit(fruitUnion); - `, - }, - - { - code: - fruitFunctionDefinition + - ` - declare const fruitUnion: Fruit.Apple | Fruit.Banana | Fruit.Pear; - useFruit(fruitUnion); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple | Fruit.Banana | Fruit.Pear) {} - declare const fruitUnion: Fruit.Apple | Fruit.Banana | Fruit.Pear; - useFruit(fruitUnion); - `, - }, - - { - code: - fruitFunctionDefinition + - ` - declare const fruit: Fruit; - switch (fruit) { - case Fruit.Apple: - case Fruit.Banana: { - useFruit(fruit); - } - } - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruitType: FruitType) {} - useFruit(Fruit.Apple); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruitType: FruitType) {} - useFruit(0); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruitType: FruitType) {} - useFruit(Fruit.Apple); - `, - }, - - { - code: - fruitEnumDefinition + - ` - class FruitClass { - constructor(type: FruitType) {} - useFruit(type: FruitType) {} - } - const fruitClass = new FruitClass(Fruit.Apple); - fruitClass.useFruit(Fruit.Apple); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useNumbers(numberArray: number[]) {} - useNumbers([0, 1]); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruitArray: Fruit[]) {} - useFruit([Fruit.Apple, Fruit.Banana]); - `, - }, - - { - code: ` -function useNumber(num: number) {} -useNumber(0); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useNumber(num: number) {} - useNumber(Fruit.Apple); - `, - }, - - { - code: - vegetableEnumDefinition + - ` - function useString(str: string) {} - useString('lettuce'); - `, - }, - - { - code: - vegetableEnumDefinition + - ` - function useString(str: string) {} - useString(Vegetable.Lettuce); - `, - }, - - { - code: ` -function useAnything(something: any) {} -useAnything(0); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useAnything(something: any) {} - useAnything(Fruit.Apple); - `, - }, - - { - code: ` -function useUnknown(something: unknown) {} -useUnknown(0); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useUnknown(something: unknown) {} - useUnknown(Fruit.Apple); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} - useFruit(Fruit.Apple); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} - useFruit([Fruit.Apple, Fruit.Banana]); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} - declare const fruit: Fruit | Fruit[]; - useFruit(fruit); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruitOrFruitArray: number | Fruit[]) {} - useFruit(0); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruitOrFruitArray: number | Fruit[]) {} - useFruit([Fruit.Apple, Fruit.Banana]); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(...fruits: Fruit[]) {} - useFruit(Fruit.Apple); - useFruit(Fruit.Apple, Fruit.Banana); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function toEqual(expected: E): void {} - toEqual(Fruit.Apple); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function toEqual(expected: E): void {} - toEqual(Fruit.Apple); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function toEqual(expected: E): void {} - toEqual(Fruit.Apple); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function toEqual(expected: E): void {} - toEqual(Fruit.Apple); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function toEqual(arg1: number, expected: E): void {} - toEqual(0, Fruit.Apple); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function toEqual(arg1: number, expected: E): void {} - toEqual(0, Fruit.Apple); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function toEqual(arg1: number, expected: E): void {} - toEqual(0, Fruit.Apple); - `, - }, - - { - code: - fruitEnumDefinition + - ` - function toEqual(arg1: number, expected: E): void {} - toEqual(0, Fruit.Apple); - `, - }, - - { - code: ` -JSON.stringify({}, (_, value: unknown) => value ?? undefined, 2); - `, - }, - - { - code: ` -function flatten(arr: T[][]): T[] { - return arr.reduce((acc, a) => acc.concat(a), []); -} - `, - }, - ], - invalid: [ - { - code: - fruitFunctionDefinition + - ` - useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple) {} - useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit = Fruit.Apple) {} - useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple = Fruit.Apple) {} - useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit | null) {} - useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit | null = Fruit.Apple) {} - useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple | null) {} - useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple | null = Fruit.Apple) {} - useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple | Fruit.Banana | null) {} - useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - const fruitSet = new Set([ - Fruit.Apple, - Fruit.Banana, - ]); - - fruitSet.has(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple | Fruit.Banana) {} - useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruit: Fruit.Apple | Fruit.Banana | Fruit.Pear) {} - useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruitType: FruitType) {} - useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - class FruitClass { - constructor(type: FruitType) {} - useFruit(type: FruitType) {} - } - const fruitClass = new FruitClass(0); - fruitClass.useFruit(0); - `, - errors: [ - { messageId: 'mismatchedFunctionArgument' }, - { messageId: 'mismatchedFunctionArgument' }, - ], - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruitArray: Fruit[]) {} - useFruit([0, 1]); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruitArray: Fruit[]) {} - useFruit([Fruit.Apple, 1]); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} - useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruitOrFruitArray: Fruit | Fruit[]) {} - useFruit([0, 1]); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(fruitOrFruitArray: number | Fruit[]) {} - useFruit([0, 1]); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(...fruits: Fruit[]) {} - useFruit(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - function useFruit(...fruits: Fruit[]) {} - useFruit(Fruit.Apple, 0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - function toEqual(expected: E): void {} - toEqual(0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - - { - code: - fruitEnumDefinition + - ` - function toEqual(arg1: number, expected: E): void {} - toEqual(0, 0); - `, - errors: [{ messageId: 'mismatchedFunctionArgument' }], - }, - ], -}); From f1071fab84f78c399cedaec67ba6f7518608d5a5 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 26 Nov 2022 20:27:00 -0500 Subject: [PATCH 83/88] Finished testing and sharing --- .../src/rules/enum-utils/shared.ts | 46 ++ .../src/rules/no-unsafe-enum-assignment.ts | 47 +- .../src/rules/no-unsafe-enum-comparison.ts | 285 ++----- .../rules/no-unsafe-enum-assignment.test.ts | 58 +- .../rules/no-unsafe-enum-comparison.test.ts | 733 +++++++++++------- .../tests/rules/strict-enums/shared.ts | 49 -- 6 files changed, 631 insertions(+), 587 deletions(-) create mode 100644 packages/eslint-plugin/src/rules/enum-utils/shared.ts delete mode 100644 packages/eslint-plugin/tests/rules/strict-enums/shared.ts diff --git a/packages/eslint-plugin/src/rules/enum-utils/shared.ts b/packages/eslint-plugin/src/rules/enum-utils/shared.ts new file mode 100644 index 000000000000..23257d5e6116 --- /dev/null +++ b/packages/eslint-plugin/src/rules/enum-utils/shared.ts @@ -0,0 +1,46 @@ +import * as tsutils from 'tsutils'; +import * as ts from 'typescript'; + +import * as util from '../../util'; + +/* + * If passed an enum member, returns the type of the parent. Otherwise, + * returns itself. + * + * For example: + * - `Fruit` --> `Fruit` + * - `Fruit.Apple` --> `Fruit` + */ +export function getBaseEnumType( + typeChecker: ts.TypeChecker, + type: ts.Type, +): ts.Type { + const symbol = type.getSymbol(); + if ( + !symbol?.valueDeclaration?.parent || + !tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.EnumMember) + ) { + return type; + } + + return typeChecker.getTypeAtLocation(symbol.valueDeclaration.parent); +} + +/** + * A type can have 0 or more enum types. For example: + * - 123 --> [] + * - {} --> [] + * - Fruit.Apple --> [Fruit] + * - Fruit.Apple | Vegetable.Lettuce --> [Fruit, Vegetable] + * - Fruit.Apple | Vegetable.Lettuce | 123 --> [Fruit, Vegetable] + * - T extends Fruit --> [Fruit] + */ +export function getEnumTypes( + typeChecker: ts.TypeChecker, + type: ts.Type, +): ts.Type[] { + return tsutils + .unionTypeParts(type) + .filter(subType => util.isTypeFlagSet(subType, ts.TypeFlags.EnumLiteral)) + .map(type => getBaseEnumType(typeChecker, type)); +} diff --git a/packages/eslint-plugin/src/rules/no-unsafe-enum-assignment.ts b/packages/eslint-plugin/src/rules/no-unsafe-enum-assignment.ts index 412b12676e33..c52d60e67b21 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-enum-assignment.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-enum-assignment.ts @@ -3,6 +3,7 @@ import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; +import { getBaseEnumType, getEnumTypes } from './enum-utils/shared'; const ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT = ts.TypeFlags.Unknown | ts.TypeFlags.Number | ts.TypeFlags.String; @@ -28,44 +29,6 @@ export default util.createRule({ const parserServices = util.getParserServices(context); const typeChecker = parserServices.program.getTypeChecker(); - /* - * If passed an enum member, returns the type of the parent. Otherwise, - * returns itself. - * - * For example: - * - `Fruit` --> `Fruit` - * - `Fruit.Apple` --> `Fruit` - */ - function getBaseEnumType(type: ts.Type): ts.Type { - const symbol = type.getSymbol(); - if ( - !symbol?.valueDeclaration?.parent || - !tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.EnumMember) - ) { - return type; - } - - return typeChecker.getTypeAtLocation(symbol.valueDeclaration.parent); - } - - /** - * A type can have 0 or more enum types. For example: - * - 123 --> [] - * - {} --> [] - * - Fruit.Apple --> [Fruit] - * - Fruit.Apple | Vegetable.Lettuce --> [Fruit, Vegetable] - * - Fruit.Apple | Vegetable.Lettuce | 123 --> [Fruit, Vegetable] - * - T extends Fruit --> [Fruit] - */ - function getEnumTypes(type: ts.Type): ts.Type[] { - return tsutils - .unionTypeParts(type) - .filter(subType => - util.isTypeFlagSet(subType, ts.TypeFlags.EnumLiteral), - ) - .map(getBaseEnumType); - } - /** * Similar to `getEnumTypes`, but returns early as soon as it finds one. */ @@ -116,7 +79,9 @@ export default util.createRule({ } // If the recipient is not an enum, we don't care about it. - const recipientEnumTypes = new Set(getEnumTypes(recipientType)); + const recipientEnumTypes = new Set( + getEnumTypes(typeChecker, recipientType), + ); if (recipientEnumTypes.size === 0) { return false; } @@ -126,7 +91,7 @@ export default util.createRule({ // Either every provided type should match the recipient enum... if ( providedUnionTypes.every(providedType => - recipientEnumTypes.has(getBaseEnumType(providedType)), + recipientEnumTypes.has(getBaseEnumType(typeChecker, providedType)), ) ) { return false; @@ -242,7 +207,7 @@ export default util.createRule({ // declare function useNumber(num: number); // useNumber(0); // ``` - const parameterEnumTypes = getEnumTypes(parameterType); + const parameterEnumTypes = getEnumTypes(typeChecker, parameterType); if (parameterEnumTypes.length === 0) { return false; } diff --git a/packages/eslint-plugin/src/rules/no-unsafe-enum-comparison.ts b/packages/eslint-plugin/src/rules/no-unsafe-enum-comparison.ts index ddb439258ca5..06c35f3055a5 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-enum-comparison.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-enum-comparison.ts @@ -3,87 +3,37 @@ import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; +import { getEnumTypes } from './enum-utils/shared'; /** - * TypeScript only allows number enums, string enums, or mixed enums with both - * numbers and strings. - * - * Mixed enums are a union of a number enum and a string enum, so there is - * no separate kind for them. + * @returns Whether the right type is an unsafe comparison against any left type. */ -enum EnumKind { - HasBothValues, - HasNumberValues, - HasStringValues, - NonEnum, -} - -/** These bitwise operators are always considered to be safe comparisons. */ -const ALLOWED_ENUM_OPERATORS = new Set(['|=', '&=', '^=']); - -/** - * This rule can safely ignore other kinds of types (and leave the validation in - * question to the TypeScript compiler). - */ -const IMPOSSIBLE_ENUM_TYPES = - ts.TypeFlags.BooleanLike | - ts.TypeFlags.NonPrimitive | - ts.TypeFlags.ESSymbolLike; - -function getEnumKind(type: ts.Type): EnumKind { - if (!util.isTypeFlagSet(type, ts.TypeFlags.EnumLike)) { - return EnumKind.NonEnum; - } +function typeViolates(leftTypeParts: ts.Type[], right: ts.Type): boolean { + const leftValueKinds = new Set(leftTypeParts.map(getEnumValueType)); - const isStringLiteral = util.isTypeFlagSet(type, ts.TypeFlags.StringLiteral); - const isNumberLiteral = util.isTypeFlagSet(type, ts.TypeFlags.NumberLiteral); - - return isNumberLiteral - ? isStringLiteral - ? EnumKind.HasBothValues - : EnumKind.HasNumberValues - : EnumKind.HasStringValues; -} - -/** - * Returns a set containing the single `EnumKind` (if it is not a union), or - * a set containing N `EnumKind` (if it is a union). - */ -function getEnumKinds(type: ts.Type): Set { - return type.isUnion() - ? new Set(tsutils.unionTypeParts(type).map(getEnumKind)) - : new Set([getEnumKind(type)]); -} - -function setHasAnyElementFromSet(set1: Set, set2: Set): boolean { - for (const value of set2.values()) { - if (set1.has(value)) { - return true; - } - } - - return false; -} - -function typeHasIntersection(type: ts.Type): boolean { return ( - type.isIntersection() || - (type.isUnion() && - tsutils.unionTypeParts(type).every(subType => subType.isIntersection())) + (leftValueKinds.has(ts.TypeFlags.Number) && + tsutils.isTypeFlagSet( + right, + ts.TypeFlags.Number | ts.TypeFlags.NumberLike, + )) || + (leftValueKinds.has(ts.TypeFlags.String) && + tsutils.isTypeFlagSet( + right, + ts.TypeFlags.String | ts.TypeFlags.StringLike, + )) ); } -function isNullOrUndefinedOrAnyOrUnknownOrNever(...types: ts.Type[]): boolean { - return types.some(type => - util.isTypeFlagSet( - type, - ts.TypeFlags.Null | - ts.TypeFlags.Undefined | - ts.TypeFlags.Any | - ts.TypeFlags.Unknown | - ts.TypeFlags.Never, - ), - ); +/** + * @returns What type a type's enum value is (number or string), if either. + */ +function getEnumValueType(type: ts.Type): ts.TypeFlags | undefined { + return util.isTypeFlagSet(type, ts.TypeFlags.EnumLike) + ? util.isTypeFlagSet(type, ts.TypeFlags.NumberLiteral) + ? ts.TypeFlags.Number + : ts.TypeFlags.String + : undefined; } export default util.createRule({ @@ -96,8 +46,8 @@ export default util.createRule({ requiresTypeChecking: true, }, messages: { - mismatchedComparison: - 'The two things in the comparison do not have a shared enum type.', + mismatched: + 'The two values in this comparison do not have a shared enum type.', }, schema: [], }, @@ -106,157 +56,60 @@ export default util.createRule({ const parserServices = util.getParserServices(context); const typeChecker = parserServices.program.getTypeChecker(); - /* - * If passed an enum member, returns the type of the parent. Otherwise, - * returns itself. - * - * For example: - * - `Fruit` --> `Fruit` - * - `Fruit.Apple` --> `Fruit` - */ - function getBaseEnumType(type: ts.Type): ts.Type { - const symbol = type.getSymbol(); - if ( - symbol === undefined || - !tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.EnumMember) - ) { - return type; - } - - const { valueDeclaration } = symbol; - if (valueDeclaration === undefined) { - return type; - } - - return typeChecker.getTypeAtLocation(valueDeclaration.parent) ?? type; - } - - /** - * A type can have 0 or more enum types. For example: - * - 123 --> [] - * - {} --> [] - * - Fruit.Apple --> [Fruit] - * - Fruit.Apple | Vegetable.Lettuce --> [Fruit, Vegetable] - * - Fruit.Apple | Vegetable.Lettuce | 123 --> [Fruit, Vegetable] - * - T extends Fruit --> [Fruit] - */ - function getEnumTypes(type: ts.Type): Set { - return new Set( - tsutils - // We resolve the type (or its constituents)... - .unionTypeParts(type) - // ...to any generic constraint... - .map(subType => subType.getConstraint() ?? subType) - // ...and only look at base types of enum types - .filter(subType => - util.isTypeFlagSet(subType, ts.TypeFlags.EnumLiteral), - ) - .map(getBaseEnumType), - ); - } - function getTypeFromNode(node: TSESTree.Node): ts.Type { return typeChecker.getTypeAtLocation( parserServices.esTreeNodeToTSNodeMap.get(node), ); } - function isMismatchedEnumComparison( - operator: string, - leftType: ts.Type, - rightType: ts.Type, - ): boolean { - // Allow comparisons with allowlisted operators. - if (ALLOWED_ENUM_OPERATORS.has(operator)) { - return false; - } - - // Allow comparisons that don't have anything to do with enums. - const leftEnumTypes = getEnumTypes(leftType); - const rightEnumTypes = getEnumTypes(rightType); - if (leftEnumTypes.size === 0 && rightEnumTypes.size === 0) { - return false; - } - - // Allow comparisons to any intersection. Enum intersections would be rare - // in real-life code, so they are out of scope for this rule. - if (typeHasIntersection(leftType) || typeHasIntersection(rightType)) { - return false; - } - - // Allow comparisons to types that can never be an enum (like a function). - // - // (The TypeScript compiler should properly type-check these cases, so the - // lint rule is unneeded.) - if ( - util.isTypeFlagSet(leftType, IMPOSSIBLE_ENUM_TYPES) || - util.isTypeFlagSet(rightType, IMPOSSIBLE_ENUM_TYPES) - ) { - return false; - } - - // Allow exact comparisons to some standard types, like null and - // undefined. - // - // The TypeScript compiler should properly type-check these cases, so the - // lint rule is unneeded. - if (isNullOrUndefinedOrAnyOrUnknownOrNever(leftType, rightType)) { - return false; - } - - // Allow number enums to be compared with strings and string enums to be - // compared with numbers. - // - // (The TypeScript compiler should properly type-check these cases, so the - // lint rule is unneeded.) - const leftEnumKinds = getEnumKinds(leftType); - if ( - leftEnumKinds.has(EnumKind.HasStringValues) && - leftEnumKinds.size === 1 && - util.isTypeFlagSet(rightType, ts.TypeFlags.NumberLike) - ) { - return false; - } - if ( - leftEnumKinds.has(EnumKind.HasNumberValues) && - leftEnumKinds.size === 1 && - util.isTypeFlagSet(rightType, ts.TypeFlags.StringLike) - ) { - return false; - } - - const rightEnumKinds = getEnumKinds(rightType); - if ( - rightEnumKinds.has(EnumKind.HasStringValues) && - rightEnumKinds.size === 1 && - util.isTypeFlagSet(leftType, ts.TypeFlags.NumberLike) - ) { - return false; - } - if ( - rightEnumKinds.has(EnumKind.HasNumberValues) && - rightEnumKinds.size === 1 && - util.isTypeFlagSet(leftType, ts.TypeFlags.StringLike) - ) { - return false; - } - - // Disallow mismatched comparisons, like the following: - // - // ```ts - // if (fruit === 0) {} - // ``` - return setHasAnyElementFromSet(leftEnumTypes, rightEnumTypes); - } - return { 'BinaryExpression[operator=/=/]'(node: TSESTree.BinaryExpression): void { - const leftType = getTypeFromNode(node.left); - const rightType = getTypeFromNode(node.right); + const left = getTypeFromNode(node.left); + const right = getTypeFromNode(node.right); + + // Allow comparisons that don't have anything to do with enums: + // + // ```ts + // 1 === 2; + // ``` + const leftEnumTypes = getEnumTypes(typeChecker, left); + const rightEnumTypes = new Set(getEnumTypes(typeChecker, right)); + if (leftEnumTypes.length === 0 && rightEnumTypes.size === 0) { + return; + } + + // Allow comparisons that share an enum type: + // + // ```ts + // Fruit.Apple === Fruit.Banana; + // ``` + for (const leftEnumType of leftEnumTypes) { + if (rightEnumTypes.has(leftEnumType)) { + return; + } + } + + const leftTypeParts = tsutils.unionTypeParts(left); + const rightTypeParts = tsutils.unionTypeParts(right); + + // If a type exists in both sides, we consider this comparison safe: + // + // ```ts + // declare const fruit: Fruit.Apple | 0; + // fruit === 0; + // ``` + for (const leftTypePart of leftTypeParts) { + if (rightTypeParts.includes(leftTypePart)) { + return; + } + } - if (isMismatchedEnumComparison(node.operator, leftType, rightType)) { + if ( + typeViolates(leftTypeParts, right) || + typeViolates(rightTypeParts, left) + ) { context.report({ - messageId: 'mismatchedComparison', + messageId: 'mismatched', node, }); } diff --git a/packages/eslint-plugin/tests/rules/no-unsafe-enum-assignment.test.ts b/packages/eslint-plugin/tests/rules/no-unsafe-enum-assignment.test.ts index c2e0f5c8f770..1edfab151cb7 100644 --- a/packages/eslint-plugin/tests/rules/no-unsafe-enum-assignment.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unsafe-enum-assignment.test.ts @@ -294,6 +294,36 @@ ruleTester.run('no-unsafe-enum-assignment', rule, { errors: [{ messageId: 'provided' }], }, + { + code: ` + enum Fruit { + Apple, + } + let fruit = Fruit.Apple; + fruit |= 1; + `, + errors: [{ messageId: 'provided' }], + }, + { + code: ` + enum Fruit { + Apple, + } + let fruit = Fruit.Apple; + fruit &= 1; + `, + errors: [{ messageId: 'provided' }], + }, + { + code: ` + enum Fruit { + Apple, + } + let fruit = Fruit.Apple; + fruit ^= 1; + `, + errors: [{ messageId: 'provided' }], + }, { code: ` enum Fruit { @@ -464,16 +494,22 @@ ruleTester.run('no-unsafe-enum-assignment', rule, { }, ], }, + { + code: ` + enum Fruit { + Apple, + } + const values = new Set(); + values.add(0); + `, + errors: [ + { + column: 20, + endColumn: 21, + line: 6, + messageId: 'provided', + }, + ], + }, ], }); - -// recursive types: -// different number of type arguments, each way? (2 tests) - -// assignments: -// number literals and unions thereof -// with Math.random() -// [number][] -// Set -// Map -// Map, Set> diff --git a/packages/eslint-plugin/tests/rules/no-unsafe-enum-comparison.test.ts b/packages/eslint-plugin/tests/rules/no-unsafe-enum-comparison.test.ts index 653788ee8766..a38eb123254a 100644 --- a/packages/eslint-plugin/tests/rules/no-unsafe-enum-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unsafe-enum-comparison.test.ts @@ -1,338 +1,531 @@ import rule from '../../src/rules/no-unsafe-enum-comparison'; -import { - fruit2EnumDefinition, - fruitEnumDefinition, - strictEnumsRuleTester, - vegetable2EnumDefinition, - vegetableEnumDefinition, -} from './strict-enums/shared'; +import { getFixturesRootDir, RuleTester } from '../RuleTester'; -strictEnumsRuleTester.run('strict-enums-comparison', rule, { +const rootDir = getFixturesRootDir(); + +const ruleTester = new RuleTester({ + parserOptions: { + ecmaVersion: 2015, + tsconfigRootDir: rootDir, + project: './tsconfig.json', + }, + parser: '@typescript-eslint/parser', +}); + +ruleTester.run('strict-enums-comparison', rule, { valid: [ + "'a' == 'b';", + "'a' === 'b';", + '1 == 2;', + '1 === 2;', + ` + enum Fruit { + Apple, + } + Fruit.Apple === ({} as any); + `, + ` + enum Fruit { + Apple, + } + Fruit.Apple === undefined; + `, + ` + enum Fruit { + Apple, + } + Fruit.Apple === null; + `, + ` + enum Fruit { + Apple, + } + declare const fruit: Fruit | -1; + fruit === -1; + `, + ` + enum Fruit { + Apple, + } + declare const fruit: Fruit | number; + fruit === -1; + `, + ` + enum Fruit { + Apple, + } + declare const fruit: Fruit | 'apple'; + fruit === 'apple'; + `, + ` + enum Fruit { + Apple, + } + declare const fruit: Fruit | string; + fruit === 'apple'; + `, + ` + enum Fruit { + Apple = 'apple', + } + declare const fruit: Fruit | 'apple'; + fruit === 'apple'; + `, + ` + enum Fruit { + Apple = 'apple', + } + declare const fruit: Fruit | string; + fruit === 'apple'; + `, + ` + enum Fruit { + Apple = 'apple', + } + declare const fruit: Fruit | 0; + fruit === 0; + `, + ` + enum Fruit { + Apple = 'apple', + } + declare const fruit: Fruit | number; + fruit === 0; + `, + ` + enum Fruit { + Apple, + } + declare const fruit: Fruit | 'apple'; + fruit === Math.random() > 0.5 ? 'apple' : Fruit.Apple; + `, + ` + enum Fruit { + Apple = 'apple', + } + declare const fruit: Fruit | 'apple'; + fruit === Math.random() > 0.5 ? 'apple' : Fruit.Apple; + `, + ` + enum Fruit { + Apple = 'apple', + } + declare const fruit: Fruit | string; + fruit === Math.random() > 0.5 ? 'apple' : Fruit.Apple; + `, + ` + enum Fruit { + Apple = 'apple', + } + declare const fruit: Fruit | 0; + fruit === Math.random() > 0.5 ? 0 : Fruit.Apple; + `, + ` + enum Fruit { + Apple = 'apple', + } + declare const fruit: Fruit | number; + fruit === Math.random() > 0.5 ? 0 : Fruit.Apple; + `, + ` + enum Fruit { + Apple, + Banana, + } + Fruit.Apple === Fruit.Banana; + `, + ` + enum Fruit { + Apple = 0, + Banana = 1, + } + Fruit.Apple === Fruit.Banana; + `, + ` + enum Fruit { + Apple = 'apple', + Banana = 'banana', + } + Fruit.Apple === Fruit.Banana; + `, + ` + enum Fruit { + Apple, + Banana, + } + const fruit = Fruit.Apple; + fruit === Fruit.Banana; + `, + ` + enum Vegetable { + Asparagus = 'asparagus', + Beet = 'beet', + Celery = 'celery', + } + const vegetable = Vegetable.Asparagus; + vegetable === Vegetable.Beet; + `, + ` + enum Fruit { + Apple, + Banana, + Cherry, + } + const fruit1 = Fruit.Apple; + const fruit2 = Fruit.Banana; + fruit1 === fruit2; + `, + ` + enum Vegetable { + Asparagus = 'asparagus', + Beet = 'beet', + Celery = 'celery', + } + const vegetable1 = Vegetable.Asparagus; + const vegetable2 = Vegetable.Beet; + vegetable1 === vegetable2; + `, + ` + enum Fruit { + Apple, + Banana, + Cherry, + } + enum Fruit2 { + Apple2, + Banana2, + Cherry2, + } + declare const left: number | Fruit; + declare const right: number | Fruit2; + left === right; + `, + ` + enum Vegetable { + Asparagus = 'asparagus', + Beet = 'beet', + Celery = 'celery', + } + enum Vegetable2 { + Asparagus2 = 'asparagus2', + Beet2 = 'beet2', + Celery2 = 'celery2', + } + declare const left: string | Vegetable; + declare const right: string | Vegetable2; + left === right; + `, + ` + enum Vegetable { + Asparagus = 'asparagus', + Beet = 'beet', + Celery = 'celery', + } + type WeirdString = string & { __someBrand: void }; + declare const weirdString: WeirdString; + Vegetable.Asparagus === weirdString; + `, + ` + enum Vegetable { + Asparagus = 'asparagus', + Beet = 'beet', + Celery = 'celery', + } + const foo = {}; + const vegetable = Vegetable.Asparagus; + vegetable in foo; + `, + ` + enum Fruit { + Apple, + Banana, + Cherry, + } + declare const fruitOrBoolean: Fruit | boolean; + fruitOrBoolean === true; + `, + ` + enum Str { + A = 'a', + } + enum Num { + B = 1, + } + enum Mixed { + A = 'a', + B = 1, + } + + declare const str: Str; + declare const strOrString: Str | string; + + declare const num: Num; + declare const numOrNumber: Num | number; + + declare const mixed: Mixed; + declare const mixedOrStringOrNumber: Mixed | string | number; + + function someFunction() {} + + // following are all ignored due to the presence of "| string" or "| number" + strOrString === 'a'; + numOrNumber === 1; + mixedOrStringOrNumber === 'a'; + mixedOrStringOrNumber === 1; + + // following are all ignored because the value can never be an enum value + str === 1; + num === 'a'; + str === {}; + num === {}; + mixed === {}; + str === true; + num === true; + mixed === true; + str === someFunction; + num === someFunction; + mixed === someFunction; + `, + ], + invalid: [ { - code: - fruitEnumDefinition + - ` - 1 === 2; - `, - }, - { - code: - fruitEnumDefinition + - ` - declare thing: any; - Fruit.Apple === thing; + code: ` + enum Fruit { + Apple, + } + Fruit.Apple == 1; `, + errors: [{ messageId: 'mismatched' }], }, { - code: - fruitEnumDefinition + - ` - Fruit.Apple === undefined; + code: ` + enum Fruit { + Apple, + } + Fruit.Apple === 1; `, + errors: [{ messageId: 'mismatched' }], }, { - code: - fruitEnumDefinition + - ` - Fruit.Apple === null; + code: ` + enum Fruit { + Apple, + } + Fruit.Apple != 1; `, + errors: [{ messageId: 'mismatched' }], }, { - code: - fruitEnumDefinition + - ` - Fruit.Apple === Fruit.Banana; + code: ` + enum Fruit { + Apple, + } + Fruit.Apple !== 1; `, + errors: [{ messageId: 'mismatched' }], }, { - code: - fruitEnumDefinition + - ` - const fruit = Fruit.Apple; - fruit === Fruit.Banana; + code: ` + enum Fruit { + Apple = 0, + Banana = 'banana', + } + Fruit.Apple === 0; `, + errors: [{ messageId: 'mismatched' }], }, { - code: - vegetableEnumDefinition + - ` - const vegetable = Vegetable.Lettuce; - vegetable === Vegetable.Carrot; + code: ` + enum Fruit { + Apple = 0, + Banana = 'banana', + } + Fruit.Banana === ''; `, + errors: [{ messageId: 'mismatched' }], }, { - code: - fruitEnumDefinition + - ` - const fruit1 = Fruit.Apple; - const fruit2 = Fruit.Banana; - fruit1 === fruit2; + code: ` + enum Vegetable { + Asparagus = 'asparagus', + Beet = 'beet', + Celery = 'celery', + } + Vegetable.Asparagus === 'beet'; `, + errors: [{ messageId: 'mismatched' }], }, { - code: - vegetableEnumDefinition + - ` - const vegetable1 = Vegetable.Lettuce; - const vegetable2 = Vegetable.Carrot; - vegetable1 === vegetable2; + code: ` + enum Fruit { + Apple, + Banana, + Cherry, + } + 1 === Fruit.Apple; `, + errors: [{ messageId: 'mismatched' }], }, { - code: - fruitEnumDefinition + - ` - class FruitClass { - constructor(type: FruitType) { - if (type === Fruit.Apple) {} - } - } + code: ` + enum Vegetable { + Asparagus = 'asparagus', + Beet = 'beet', + Celery = 'celery', + } + 'beet' === Vegetable.Asparagus; `, + errors: [{ messageId: 'mismatched' }], }, { - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` - declare const left: number | Fruit; - declare const right: number | Fruit2; - left === right; - `, - }, - { - code: - vegetableEnumDefinition + - vegetable2EnumDefinition + - ` - declare const left: string | Vegetable; - declare const right: string | Vegetable2; - left === right; - `, - }, - { - code: - vegetableEnumDefinition + - ` - type WeirdString = string & { __someBrand: void; }; - declare weirdString: WeirdString; - Vegetable.Lettuce === weirdString; + code: ` + enum Fruit { + Apple, + Banana, + Cherry, + } + const fruit = Fruit.Apple; + fruit === 1; `, + errors: [{ messageId: 'mismatched' }], }, { - code: - vegetableEnumDefinition + - ` - enum InternalSymbolName { - Foo = "foo", - Bar = "bar", - } - type __String = - | (string & { __escapedIdentifier: void; }) - | (void & { __escapedIdentifier: void; }) - | InternalSymbolName; - declare const weirdString: __String; - weirdString === 'someArbitraryValue'; + code: ` + enum Vegetable { + Asparagus = 'asparagus', + Beet = 'beet', + Celery = 'celery', + } + const vegetable = Vegetable.Asparagus; + vegetable === 'beet'; `, + errors: [{ messageId: 'mismatched' }], }, { - code: - vegetableEnumDefinition + - ` - const foo = {}; - const vegetable = Vegetable.Lettuce; - vegetable in foo; + code: ` + enum Fruit { + Apple, + Banana, + Cherry, + } + const fruit = Fruit.Apple; + 1 === fruit; `, - }, - { - code: - fruitEnumDefinition + - ` - declare const fruitOrBoolean: Fruit | boolean; - fruitOrBoolean === true; - `, + errors: [{ messageId: 'mismatched' }], }, { code: ` -enum Str { - A = 'a', -} -enum Num { - B = 1, -} -enum Mixed { - A = 'a', - B = 1, -} - -declare const str: Str; -declare const strOrString: Str | string; - -declare const num: Num; -declare const numOrNumber: Num | number; - -declare const mixed: Mixed; -declare const mixedOrStringOrNumber: Mixed | string | number; - -function someFunction() {} - -// following are all ignored due to the presence of "| string" or "| number" -strOrString === 'a'; -numOrNumber === 1; -mixedOrStringOrNumber === 'a'; -mixedOrStringOrNumber === 1; - -// following are all ignored because the value can never be an enum value -str === 1; -num === 'a'; -str === {}; -num === {}; -mixed === {}; -str === true; -num === true; -mixed === true; -str === someFunction; -num === someFunction; -mixed === someFunction; + enum Vegetable { + Asparagus = 'asparagus', + Beet = 'beet', + Celery = 'celery', + } + const vegetable = Vegetable.Asparagus; + 'beet' === vegetable; `, - }, - ], - invalid: [ - { - code: - fruitEnumDefinition + - ` - Fruit.Apple === 1; - `, - errors: [{ messageId: 'mismatchedComparison' }], - }, - { - code: - vegetableEnumDefinition + - ` - Vegetable.Lettuce === 'carrot'; - `, - errors: [{ messageId: 'mismatchedComparison' }], - }, - { - code: - fruitEnumDefinition + - ` - 1 === Fruit.Apple; - `, - errors: [{ messageId: 'mismatchedComparison' }], - }, - { - code: - vegetableEnumDefinition + - ` - 'carrot' === Vegetable.Lettuce; - `, - errors: [{ messageId: 'mismatchedComparison' }], - }, - { - code: - fruitEnumDefinition + - ` - const fruit = Fruit.Apple; - fruit === 1; - `, - errors: [{ messageId: 'mismatchedComparison' }], + errors: [{ messageId: 'mismatched' }], }, { code: - vegetableEnumDefinition + - ` - const vegetable = Vegetable.Lettuce; - vegetable === 'carrot'; - `, - errors: [{ messageId: 'mismatchedComparison' }], - }, - { - code: - fruitEnumDefinition + - ` - const fruit = Fruit.Apple; - 1 === fruit; - `, - errors: [{ messageId: 'mismatchedComparison' }], - }, - { - code: - vegetableEnumDefinition + - ` - const vegetable = Vegetable.Lettuce; - 'carrot' === vegetable; - `, - errors: [{ messageId: 'mismatchedComparison' }], - }, - { - code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` + 'enum Fruit { Apple, Banana, Cherry }' + + `enum Fruit2 { + Apple2, + Banana2, + Cherry2, +} Fruit.Apple === Fruit2.Apple2; `, - errors: [{ messageId: 'mismatchedComparison' }], + errors: [{ messageId: 'mismatched' }], }, { - code: - vegetableEnumDefinition + - vegetable2EnumDefinition + - ` - Vegetable.Lettuce === Vegetable2.Lettuce2; - `, - errors: [{ messageId: 'mismatchedComparison' }], + code: ` + enum Vegetable { + Asparagus = 'asparagus', + Beet = 'beet', + Celery = 'celery', + } + enum Vegetable2 { + Asparagus2 = 'asparagus2', + Beet2 = 'beet2', + Celery2 = 'celery2', + } + Vegetable.Asparagus === Vegetable2.Asparagus2; + `, + errors: [{ messageId: 'mismatched' }], }, { code: - fruitEnumDefinition + - fruit2EnumDefinition + - ` + 'enum Fruit { Apple, Banana, Cherry }' + + `enum Fruit2 { + Apple2, + Banana2, + Cherry2, +} const fruit = Fruit.Apple; fruit === Fruit2.Apple2; `, - errors: [{ messageId: 'mismatchedComparison' }], + errors: [{ messageId: 'mismatched' }], }, { - code: - vegetableEnumDefinition + - vegetable2EnumDefinition + - ` - const vegetable = Vegetable.Lettuce; - vegetable === Vegetable2.Lettuce2; - `, - errors: [{ messageId: 'mismatchedComparison' }], + code: ` + enum Vegetable { + Asparagus = 'asparagus', + Beet = 'beet', + Celery = 'celery', + } + enum Vegetable2 { + Asparagus2 = 'asparagus2', + Beet2 = 'beet2', + Celery2 = 'celery2', + } + const vegetable = Vegetable.Asparagus; + vegetable === Vegetable2.Asparagus2; + `, + errors: [{ messageId: 'mismatched' }], }, { code: ` -enum Str { - A = 'a', -} -enum Num { - B = 1, -} -enum Mixed { - A = 'a', - B = 1, -} + enum Str { + A = 'a', + } + enum Num { + B = 1, + } + enum Mixed { + A = 'a', + B = 1, + } -declare const str: Str; -declare const num: Num; -declare const mixed: Mixed; + declare const str: Str; + declare const num: Num; + declare const mixed: Mixed; -// following are all errors because the value might be an enum value -str === 'a'; -num === 1; -mixed === 'a'; -mixed === 1; + // following are all errors because the value might be an enum value + str === 'a'; + num === 1; + mixed === 'a'; + mixed === 1; `, errors: [ - { messageId: 'mismatchedComparison' }, - { messageId: 'mismatchedComparison' }, - { messageId: 'mismatchedComparison' }, - { messageId: 'mismatchedComparison' }, + { messageId: 'mismatched' }, + { messageId: 'mismatched' }, + { messageId: 'mismatched' }, + { messageId: 'mismatched' }, ], }, + { + code: ` + enum Fruit { + Apple = 'apple', + } + type __String = + | (string & { __escapedIdentifier: void }) + | (void & { __escapedIdentifier: void }) + | Fruit; + declare const weirdString: __String; + weirdString === 'someArbitraryValue'; + `, + errors: [{ messageId: 'mismatched' }], + }, ], }); diff --git a/packages/eslint-plugin/tests/rules/strict-enums/shared.ts b/packages/eslint-plugin/tests/rules/strict-enums/shared.ts deleted file mode 100644 index 1243d051f246..000000000000 --- a/packages/eslint-plugin/tests/rules/strict-enums/shared.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { getFixturesRootDir, RuleTester } from '../../RuleTester'; - -const rootDir = getFixturesRootDir(); -export const strictEnumsRuleTester = new RuleTester({ - parserOptions: { - ecmaVersion: 2015, - tsconfigRootDir: rootDir, - project: './tsconfig.json', - }, - parser: '@typescript-eslint/parser', -}); - -/** A number enum. */ -export const fruitEnumDefinition = ` -enum Fruit { Apple, Banana, Cherry } -`; - -/** A different number enum. */ -export const fruit2EnumDefinition = ` -enum Fruit2 { - Apple2, - Banana2, - Cherry2, -} -`; - -/** - * A string enum. - * - * String enums are almost exclusively used for comparison tests, since the - * TypeScript compiler does a good job of ensuring safety for string enum - * variable assignment and usage in functions. - */ -export const vegetableEnumDefinition = ` - enum Vegetable { - Lettuce = 'lettuce', - Carrot = 'carrot', - Celery = 'celery', - } - `; - -/** A different string enum. */ -export const vegetable2EnumDefinition = ` -enum Vegetable2 { - Lettuce2 = 'lettuce2', - Carrot2 = 'carrot2', - Celery2 = 'celery2', -} -`; From 680293a88a9da11cd9c11911ce5032dfc9ac5641 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 26 Nov 2022 20:38:41 -0500 Subject: [PATCH 84/88] Added comparison operators --- .../docs/rules/no-unsafe-enum-comparison.md | 35 ++++++++++++++----- .../src/rules/no-unsafe-enum-comparison.ts | 4 ++- .../rules/no-unsafe-enum-comparison.test.ts | 22 ++++++++++++ 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/no-unsafe-enum-comparison.md b/packages/eslint-plugin/docs/rules/no-unsafe-enum-comparison.md index df254d9b6c41..9712db992a30 100644 --- a/packages/eslint-plugin/docs/rules/no-unsafe-enum-comparison.md +++ b/packages/eslint-plugin/docs/rules/no-unsafe-enum-comparison.md @@ -26,26 +26,45 @@ This rule flags when an enum typed value is compared to a non-enum `number`. ### ❌ Incorrect ```ts +enum Fruit { + Apple, +} + let fruit = Fruit.Apple; fruit === 999; ``` +```ts +enum Vegetable { + Asparagus = 'asparagus', +} + +let vegetable = Vegetable.Asparagus; +vegetable === 'asparagus'; +``` + ### ✅ Correct ```ts +enum Fruit { + Apple, +} + let fruit = Fruit.Apple; fruit === Fruit.Banana; ``` - - -## To Do: Add Option For Comparison Operators - -Since it is a common pattern, this rule allows using greater than or less than to compare numeric enums, like this: - ```ts -if (fruit > Fruit.Banana) { +enum Vegetable { + Asparagus = 'asparagus', } + +let vegetable = Vegetable.Asparagus; +vegetable === Vegetable.Asparagus; ``` -This pattern allows you to select a subset of enums. However, it can lead to bugs when enum values are arbitrarily changed, because the subset will also change. The TypeScript compiler cannot warn you about this, so you should use this pattern with care. + + +## When Not to Use It + +If you don't mind number and/or literal string constants being compared against enums, you likely don't need this rule. diff --git a/packages/eslint-plugin/src/rules/no-unsafe-enum-comparison.ts b/packages/eslint-plugin/src/rules/no-unsafe-enum-comparison.ts index 06c35f3055a5..ac7a64727bcb 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-enum-comparison.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-enum-comparison.ts @@ -63,7 +63,9 @@ export default util.createRule({ } return { - 'BinaryExpression[operator=/=/]'(node: TSESTree.BinaryExpression): void { + 'BinaryExpression[operator=/=|<|>/]'( + node: TSESTree.BinaryExpression, + ): void { const left = getTypeFromNode(node.left); const right = getTypeFromNode(node.right); diff --git a/packages/eslint-plugin/tests/rules/no-unsafe-enum-comparison.test.ts b/packages/eslint-plugin/tests/rules/no-unsafe-enum-comparison.test.ts index a38eb123254a..5e84c983076c 100644 --- a/packages/eslint-plugin/tests/rules/no-unsafe-enum-comparison.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unsafe-enum-comparison.test.ts @@ -14,8 +14,12 @@ const ruleTester = new RuleTester({ ruleTester.run('strict-enums-comparison', rule, { valid: [ + "'a' > 'b';", + "'a' < 'b';", "'a' == 'b';", "'a' === 'b';", + '1 > 2;', + '1 < 2;', '1 == 2;', '1 === 2;', ` @@ -288,6 +292,24 @@ ruleTester.run('strict-enums-comparison', rule, { `, ], invalid: [ + { + code: ` + enum Fruit { + Apple, + } + Fruit.Apple < 1; + `, + errors: [{ messageId: 'mismatched' }], + }, + { + code: ` + enum Fruit { + Apple, + } + Fruit.Apple > 1; + `, + errors: [{ messageId: 'mismatched' }], + }, { code: ` enum Fruit { From 14cceea4faba8e562d912bb9edf2f041ee4cb1b6 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sun, 27 Nov 2022 10:43:29 -0500 Subject: [PATCH 85/88] Added back no-unsafe-enum-comparison --- .../docs/rules/no-unsafe-enum-assignment.md | 62 --- packages/eslint-plugin/src/configs/all.ts | 1 - packages/eslint-plugin/src/configs/strict.ts | 1 - packages/eslint-plugin/src/rules/index.ts | 2 - .../src/rules/no-unsafe-enum-assignment.ts | 336 ------------ .../rules/no-unsafe-enum-assignment.test.ts | 515 ------------------ 6 files changed, 917 deletions(-) delete mode 100644 packages/eslint-plugin/docs/rules/no-unsafe-enum-assignment.md delete mode 100644 packages/eslint-plugin/src/rules/no-unsafe-enum-assignment.ts delete mode 100644 packages/eslint-plugin/tests/rules/no-unsafe-enum-assignment.test.ts diff --git a/packages/eslint-plugin/docs/rules/no-unsafe-enum-assignment.md b/packages/eslint-plugin/docs/rules/no-unsafe-enum-assignment.md deleted file mode 100644 index 030b9ec29359..000000000000 --- a/packages/eslint-plugin/docs/rules/no-unsafe-enum-assignment.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -description: 'Disallow providing non-enum values to enum typed locations.' ---- - -> 🛑 This file is source code, not the primary documentation location! 🛑 -> -> See **https://typescript-eslint.io/rules/no-unsafe-enum-assignment** for documentation. - -The TypeScript compiler can be surprisingly lenient when working with enums. -For example, it will allow you to assign any `number` value to a variable containing a numeric enum: - -```ts -enum Fruit { - Apple, - Banana, -} - -let fruit = Fruit.Apple; -fruit = 999; // No error -``` - -This rule flags when a `number` value is provided in a location that expects an enum type. - - - -### ❌ Incorrect - -```ts -let fruit = Fruit.Apple; -fruit++; -``` - -```ts -const fruit: Fruit = 0; -``` - -```ts -function useFruit(fruit: Fruit) {} -useFruit(0); -``` - -### ✅ Correct - -```ts -let fruit = Fruit.Apple; -fruit = Fruit.Banana; -``` - -```ts -const fruit: Fruit = Fruit.Apple; -``` - -```ts -function useFruit(fruit: Fruit) {} -useFruit(Fruit.Apple); -``` - - - -## When Not to Use It - -If you use enums as shorthands for numbers and don't mind potentially unsafe `number`-typed values assigned to them, you likely don't need this rule. diff --git a/packages/eslint-plugin/src/configs/all.ts b/packages/eslint-plugin/src/configs/all.ts index 65b5299003ed..b93c737ec3f5 100644 --- a/packages/eslint-plugin/src/configs/all.ts +++ b/packages/eslint-plugin/src/configs/all.ts @@ -109,7 +109,6 @@ export = { '@typescript-eslint/no-unsafe-assignment': 'error', '@typescript-eslint/no-unsafe-call': 'error', '@typescript-eslint/no-unsafe-declaration-merging': 'error', - '@typescript-eslint/no-unsafe-enum-assignment': 'error', '@typescript-eslint/no-unsafe-enum-comparison': 'error', '@typescript-eslint/no-unsafe-member-access': 'error', '@typescript-eslint/no-unsafe-return': 'error', diff --git a/packages/eslint-plugin/src/configs/strict.ts b/packages/eslint-plugin/src/configs/strict.ts index cec3d261e139..6de2963b545e 100644 --- a/packages/eslint-plugin/src/configs/strict.ts +++ b/packages/eslint-plugin/src/configs/strict.ts @@ -28,7 +28,6 @@ export = { '@typescript-eslint/no-unnecessary-condition': 'warn', '@typescript-eslint/no-unnecessary-type-arguments': 'warn', '@typescript-eslint/no-unsafe-declaration-merging': 'warn', - '@typescript-eslint/no-unsafe-enum-assignment': 'warn', '@typescript-eslint/no-unsafe-enum-comparison': 'warn', 'no-useless-constructor': 'off', '@typescript-eslint/no-useless-constructor': 'warn', diff --git a/packages/eslint-plugin/src/rules/index.ts b/packages/eslint-plugin/src/rules/index.ts index ca68fd258efc..aba2fde07170 100644 --- a/packages/eslint-plugin/src/rules/index.ts +++ b/packages/eslint-plugin/src/rules/index.ts @@ -79,7 +79,6 @@ import noUnsafeArgument from './no-unsafe-argument'; import noUnsafeAssignment from './no-unsafe-assignment'; import noUnsafeCall from './no-unsafe-call'; import noUnsafeDeclarationMerging from './no-unsafe-declaration-merging'; -import noUnsafeEnumAssignment from './no-unsafe-enum-assignment'; import noUnsafeEnumComparison from './no-unsafe-enum-comparison'; import noUnsafeMemberAccess from './no-unsafe-member-access'; import noUnsafeReturn from './no-unsafe-return'; @@ -212,7 +211,6 @@ export default { 'no-unsafe-assignment': noUnsafeAssignment, 'no-unsafe-call': noUnsafeCall, 'no-unsafe-declaration-merging': noUnsafeDeclarationMerging, - 'no-unsafe-enum-assignment': noUnsafeEnumAssignment, 'no-unsafe-enum-comparison': noUnsafeEnumComparison, 'no-unsafe-member-access': noUnsafeMemberAccess, 'no-unsafe-return': noUnsafeReturn, diff --git a/packages/eslint-plugin/src/rules/no-unsafe-enum-assignment.ts b/packages/eslint-plugin/src/rules/no-unsafe-enum-assignment.ts deleted file mode 100644 index c52d60e67b21..000000000000 --- a/packages/eslint-plugin/src/rules/no-unsafe-enum-assignment.ts +++ /dev/null @@ -1,336 +0,0 @@ -import type { TSESTree } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; -import * as ts from 'typescript'; - -import * as util from '../util'; -import { getBaseEnumType, getEnumTypes } from './enum-utils/shared'; - -const ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT = - ts.TypeFlags.Unknown | ts.TypeFlags.Number | ts.TypeFlags.String; - -export default util.createRule({ - name: 'no-unsafe-enum-assignment', - meta: { - type: 'suggestion', - docs: { - description: 'Disallow providing non-enum values to enum typed locations', - recommended: 'strict', - requiresTypeChecking: true, - }, - messages: { - operation: - 'This {{ operator }} may change the enum value to one not present in its enum type.', - provided: 'Unsafe non enum type provided to an enum value.', - }, - schema: [], - }, - defaultOptions: [], - create(context) { - const parserServices = util.getParserServices(context); - const typeChecker = parserServices.program.getTypeChecker(); - - /** - * Similar to `getEnumTypes`, but returns early as soon as it finds one. - */ - function hasEnumType(type: ts.Type): boolean { - return tsutils - .unionTypeParts(type) - .some(subType => util.isTypeFlagSet(subType, ts.TypeFlags.EnumLiteral)); - } - - function getTypeFromNode(node: TSESTree.Node): ts.Type { - return typeChecker.getTypeAtLocation( - parserServices.esTreeNodeToTSNodeMap.get(node), - ); - } - - /** - * @returns Whether the recipient type is an enum and the provided type - * unsafely provides it a number. - */ - function isProvidedTypeUnsafe( - providedType: ts.Type, - recipientType: ts.Type, - ): boolean { - // This short-circuits most logic: if the types are the same, we're happy. - if (providedType === recipientType) { - return false; - } - - // `any` types can't be reasoned with - if ( - tsutils.isTypeFlagSet(recipientType, ts.TypeFlags.Any) || - tsutils.isTypeFlagSet(providedType, ts.TypeFlags.Any) - ) { - return false; - } - - // If the two types are containers, check each matching type recursively. - // - // ```ts - // declare let fruits: Fruit[]; - // fruits = [0, 1]; - // ``` - if ( - util.isTypeReferenceType(recipientType) && - util.isTypeReferenceType(providedType) - ) { - return isProvidedReferenceValueMismatched(providedType, recipientType); - } - - // If the recipient is not an enum, we don't care about it. - const recipientEnumTypes = new Set( - getEnumTypes(typeChecker, recipientType), - ); - if (recipientEnumTypes.size === 0) { - return false; - } - - const providedUnionTypes = tsutils.unionTypeParts(providedType); - - // Either every provided type should match the recipient enum... - if ( - providedUnionTypes.every(providedType => - recipientEnumTypes.has(getBaseEnumType(typeChecker, providedType)), - ) - ) { - return false; - } - - // ...or none of them can be an enum at all - return !providedUnionTypes.every(tsutils.isEnumType); - } - - /** - * Finds the first mismatched type reference: meaning, a non-enum type in - * the provided type compared to an enum type in the recipient type. - */ - function isProvidedReferenceValueMismatched( - providedType: ts.TypeReference, - recipientType: ts.TypeReference, - ): boolean { - const providedTypeArguments = typeChecker.getTypeArguments(providedType); - const recipientTypeArguments = - typeChecker.getTypeArguments(recipientType); - - for ( - let i = 0; - i < - Math.min(recipientTypeArguments.length, providedTypeArguments.length); - i += 1 - ) { - if ( - isProvidedTypeUnsafe( - providedTypeArguments[i], - recipientTypeArguments[i], - ) - ) { - return true; - } - } - - return false; - } - - /** - * @returns The type of the parameter to the node, accounting for generic - * type parameters. - */ - function getParameterType( - node: TSESTree.CallExpression | TSESTree.NewExpression, - signature: ts.Signature, - index: number, - ): ts.Type { - // If possible, try to find the original parameter to retrieve any generic - // type parameter. For example: - // - // ```ts - // declare function useFruit(fruitType: FruitType); - // useFruit(0) - // ``` - const parameter = signature.getDeclaration()?.parameters[index]; - if (parameter !== undefined) { - const parameterType = typeChecker.getTypeAtLocation(parameter); - const constraint = parameterType.getConstraint(); - if (constraint !== undefined) { - return constraint; - } - } - - // Failing that, defer to whatever TypeScript sees as the contextual type. - return typeChecker.getContextualTypeForArgumentAtIndex( - parserServices.esTreeNodeToTSNodeMap.get(node), - index, - ); - } - - function isMismatchedEnumFunctionArgument( - argumentType: ts.Type, - parameterType: ts.Type, - ): boolean { - // First, recursively check for functions with type containers like: - // - // ```ts - // declare function useFruits(fruits: Fruit[]); - // useFruits([0, 1]); - // ``` - if (util.isTypeReferenceType(argumentType)) { - const argumentTypeArguments = - typeChecker.getTypeArguments(argumentType); - - const parameterSubTypes = tsutils.unionTypeParts(parameterType); - for (const parameterSubType of parameterSubTypes) { - if (!util.isTypeReferenceType(parameterSubType)) { - continue; - } - const parameterTypeArguments = - typeChecker.getTypeArguments(parameterSubType); - - for (let i = 0; i < argumentTypeArguments.length; i++) { - if ( - isMismatchedEnumFunctionArgument( - argumentTypeArguments[i], - parameterTypeArguments[i], - ) - ) { - return true; - } - } - } - - return false; - } - - // Allow function calls that have nothing to do with enums, like: - // - // ```ts - // declare function useNumber(num: number); - // useNumber(0); - // ``` - const parameterEnumTypes = getEnumTypes(typeChecker, parameterType); - if (parameterEnumTypes.length === 0) { - return false; - } - - // Allow passing enum values into functions that take in the "any" type - // and similar types that should basically match any enum, like: - // - // ```ts - // declare function useNumber(num: number); - // useNumber(Fruit.Apple); - // ``` - const parameterSubTypes = new Set(tsutils.unionTypeParts(parameterType)); - for (const parameterSubType of parameterSubTypes) { - if ( - util.isTypeFlagSet( - parameterSubType, - ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT, - ) - ) { - return false; - } - } - - // Disallow passing number literals into enum parameters, like: - // - // ```ts - // declare function useFruit(fruit: Fruit); - // declare const fruit: Fruit.Apple | 1; - // useFruit(fruit) - // ``` - return tsutils.unionTypeParts(argumentType).some( - argumentSubType => - argumentSubType.isLiteral() && - !util.isTypeFlagSet(argumentSubType, ts.TypeFlags.EnumLiteral) && - // Permit the argument if it's a number the parameter allows, like: - // - // ```ts - // declare function useFruit(fruit: Fruit | -1); - // useFruit(-1) - // ``` - // that's ok too - !parameterSubTypes.has(argumentSubType), - ); - } - - /** - * Checks whether a provided node mismatches - * - * @param provided - * @param recipient - */ - function compareProvidedNode( - provided: TSESTree.Node, - recipient: TSESTree.Node, - ): void { - const providedType = getTypeFromNode(provided); - const recipientType = getTypeFromNode(recipient); - - if (isProvidedTypeUnsafe(providedType, recipientType)) { - context.report({ - messageId: 'provided', - node: provided, - }); - } - } - - return { - AssignmentExpression(node): void { - compareProvidedNode(node.right, node.left); - }, - - 'CallExpression, NewExpression'( - node: TSESTree.CallExpression | TSESTree.NewExpression, - ): void { - const signature = typeChecker.getResolvedSignature( - parserServices.esTreeNodeToTSNodeMap.get(node), - undefined, - node.arguments.length, - )!; - - // Iterate through the arguments provided to the call function and cross - // reference their types to the types of the "real" function parameters. - for (let i = 0; i < node.arguments.length; i++) { - // any-typed arguments can be ignored altogether - const argumentType = getTypeFromNode(node.arguments[i]); - if (tsutils.isTypeFlagSet(argumentType, ts.TypeFlags.Any)) { - continue; - } - - const parameterType = getParameterType(node, signature, i); - - // Disallow mismatched function calls, like: - // - // ```ts - // declare function useFruit(fruit: Fruit); - // useFruit(0); - // ``` - if (isMismatchedEnumFunctionArgument(argumentType, parameterType)) { - context.report({ - messageId: 'provided', - node: node.arguments[i], - }); - } - } - }, - - UpdateExpression(node): void { - if (hasEnumType(getTypeFromNode(node.argument))) { - context.report({ - data: { - operator: node.operator, - }, - messageId: 'operation', - node, - }); - } - }, - - 'VariableDeclarator[init]'( - node: TSESTree.VariableDeclarator & { init: TSESTree.Expression }, - ): void { - compareProvidedNode(node.init, node.id); - }, - }; - }, -}); diff --git a/packages/eslint-plugin/tests/rules/no-unsafe-enum-assignment.test.ts b/packages/eslint-plugin/tests/rules/no-unsafe-enum-assignment.test.ts deleted file mode 100644 index 1edfab151cb7..000000000000 --- a/packages/eslint-plugin/tests/rules/no-unsafe-enum-assignment.test.ts +++ /dev/null @@ -1,515 +0,0 @@ -import rule from '../../src/rules/no-unsafe-enum-assignment'; -import { getFixturesRootDir, RuleTester } from '../RuleTester'; - -const rootDir = getFixturesRootDir(); - -const ruleTester = new RuleTester({ - parserOptions: { - ecmaVersion: 2015, - tsconfigRootDir: rootDir, - project: './tsconfig.json', - }, - parser: '@typescript-eslint/parser', -}); - -ruleTester.run('no-unsafe-enum-assignment', rule, { - valid: [ - ` - let fruit = 0; - fruit++; - `, - ` - let fruit = 1; - fruit--; - `, - ` - let fruit = 0; - ++fruit; - `, - ` - let fruit = 1; - --fruit; - `, - ` - let fruit = 1; - ~fruit; - `, - ` - let fruit = 1; - !fruit; - `, - ` - let fruit = 0; - fruit += 1; - `, - ` - let fruit = 0; - fruit *= 1; - `, - ` - let fruit = 0; - fruit /= 1; - `, - ` - let fruit = 1; - fruit -= 1; - `, - ` - enum Fruit { - Apple, - } - let fruit = Fruit.Apple; - !fruit; - `, - ` - enum Fruit { - Apple, - } - let fruits: Fruit[]; - fruits = [Fruit.Apple]; - `, - ` - enum Fruit { - Apple, - } - let fruit = Fruit.Apple; - fruit = Fruit.Apple; - `, - ` - enum Fruit { - Apple, - } - let fruit: Fruit; - fruit = Fruit.Apple; - `, - ` - enum Fruit { - Apple, - } - let fruit; - fruit = Fruit.Apple; - `, - ` - enum Fruit { - Apple, - Banana, - } - let fruits: Fruit[]; - fruits = [Fruit.Apple, Fruit.Banana]; - `, - ` - enum Fruit { - Apple, - } - declare function useFruit(fruit: Fruit): void; - useFruit(Fruit.Apple); - `, - ` - enum Fruit { - Apple, - Banana = '', - } - declare function useFruit(fruit: Fruit.Apple): void; - useFruit(Fruit.Apple); - `, - ` - enum Fruit { - Apple, - } - declare function useFruit(fruit: Fruit | -1): void; - useFruit(-1); - `, - ` - enum Fruit { - Apple = 0, - Banana = '', - } - declare function useFruit(fruit: Fruit | any): void; - useFruit(1); - `, - ` - enum Fruit { - Apple = 0, - Banana = '', - } - declare function useFruit(fruit: Fruit | number): void; - useFruit(1); - `, - ` - enum Fruit { - Apple = 0, - Banana = '', - } - declare function useFruit(fruit: Fruit | string): void; - useFruit(1); - `, - ` - enum Fruit { - Apple, - } - declare function useFruit(fruit: Fruit | null): void; - useFruit(Fruit.Apple); - `, - ` - enum Fruit { - Apple, - } - declare function useFruit(fruit: Fruit | string): void; - useFruit(Math.random() > 0.5 ? Fruit.Apple : ''); - `, - ` - enum Fruit { - Apple, - Banana, - } - declare function useFruit(fruit: Fruit): void; - useFruit(Math.random() > 0.5 ? Fruit.Apple : Fruit.Banana); - `, - ` - enum Fruit { - Apple, - } - declare function useFruit(fruit: Fruit | null): void; - useFruit(Math.random() > 0.5 ? Fruit.Apple : null); - `, - ` - enum Fruit { - Apple, - } - declare function useFruit(fruit: Fruit): void; - useFruit({} as any); - `, - ` - enum Fruit { - Apple, - } - declare function useFruit(fruit: Fruit | undefined): void; - useFruit(undefined); - `, - ` - enum Fruit { - Apple, - } - declare function useFruit(fruit: Fruit, a: number): void; - useFruit(Fruit.Apple, -1); - `, - ` - enum Fruit { - Apple, - } - declare function useFruit(fruit: Fruit, a: number, b: number): void; - useFruit(Fruit.Apple, -1, -1); - `, - ` - enum Fruit { - Apple, - } - declare function useFruit(a: number, fruit: Fruit, b: number): void; - useFruit(-1, Fruit.Apple, -1); - `, - ` - enum Fruit { - Apple, - } - declare function useFruits(fruits: Fruit[]): void; - useFruit([Fruit.Apple]); - `, - ` - enum Fruit { - Apple, - Banana, - } - declare function useFruits(...fruits: Fruit[]): void; - useFruit(Fruit.Apple, Fruit.Banana); - `, - ` - enum Fruit { - Apple, - Banana, - } - declare function useFruits(a: number, ...fruits: Fruit[]): void; - useFruit(1, Fruit.Apple, Fruit.Banana); - `, - ], - invalid: [ - { - code: ` - enum Fruit { - Apple, - } - let fruit = Fruit.Apple; - fruit++; - `, - errors: [{ data: { operator: '++' }, messageId: 'operation' }], - }, - { - code: ` - enum Fruit { - Apple, - } - let fruit = Fruit.Apple; - fruit--; - `, - errors: [{ data: { operator: '--' }, messageId: 'operation' }], - }, - { - code: ` - enum Fruit { - Apple, - } - let fruit = Fruit.Apple; - ++fruit; - `, - errors: [{ data: { operator: '++' }, messageId: 'operation' }], - }, - { - code: ` - enum Fruit { - Apple, - } - let fruit = Fruit.Apple; - --fruit; - `, - errors: [{ data: { operator: '--' }, messageId: 'operation' }], - }, - { - code: ` - enum Fruit { - Apple, - } - let fruit = Fruit.Apple; - fruit += 1; - `, - - errors: [{ messageId: 'provided' }], - }, - { - code: ` - enum Fruit { - Apple, - } - let fruit = Fruit.Apple; - fruit -= 1; - `, - - errors: [{ messageId: 'provided' }], - }, - { - code: ` - enum Fruit { - Apple, - } - let fruit = Fruit.Apple; - fruit |= 1; - `, - errors: [{ messageId: 'provided' }], - }, - { - code: ` - enum Fruit { - Apple, - } - let fruit = Fruit.Apple; - fruit &= 1; - `, - errors: [{ messageId: 'provided' }], - }, - { - code: ` - enum Fruit { - Apple, - } - let fruit = Fruit.Apple; - fruit ^= 1; - `, - errors: [{ messageId: 'provided' }], - }, - { - code: ` - enum Fruit { - Apple, - } - let fruit = Fruit.Apple; - fruit = 1; - `, - errors: [ - { - column: 17, - endColumn: 18, - line: 6, - messageId: 'provided', - }, - ], - }, - { - code: ` - enum Fruit { - Apple, - } - let fruits: Fruit[]; - fruits = [0]; - `, - errors: [ - { - column: 18, - endColumn: 21, - line: 6, - messageId: 'provided', - }, - ], - }, - { - code: ` - enum Fruit { - Apple, - } - let fruits: Fruit[]; - fruits = [0, 1]; - `, - errors: [ - { - column: 18, - endColumn: 24, - line: 6, - messageId: 'provided', - }, - ], - }, - { - code: ` - enum Fruit { - Apple, - } - let fruits: Fruit[]; - fruits = [0, Fruit.Apple]; - `, - errors: [ - { - column: 18, - endColumn: 34, - line: 6, - messageId: 'provided', - }, - ], - }, - { - code: ` - enum Fruit { - Apple, - } - declare function useFruit(fruit: Fruit): void; - useFruit(0); - `, - errors: [ - { - column: 18, - endColumn: 19, - line: 6, - messageId: 'provided', - }, - ], - }, - { - code: ` - enum Fruit { - Apple, - } - declare function useFruit(fruit: FruitType): void; - useFruit(0); - `, - errors: [ - { - column: 18, - endColumn: 19, - line: 6, - messageId: 'provided', - }, - ], - }, - { - code: ` - enum Fruit { - Apple, - } - declare function useFruits(fruits: Fruit[]): void; - useFruits([0]); - `, - errors: [ - { - column: 19, - endColumn: 22, - line: 6, - messageId: 'provided', - }, - ], - }, - { - code: ` - enum Fruit { - Apple, - } - declare function useFruits(fruits: Fruit[]): void; - useFruits([0, Fruit.Apple]); - `, - errors: [ - { - column: 19, - endColumn: 35, - line: 6, - messageId: 'provided', - }, - ], - }, - { - code: ` - enum Fruit { - Apple, - } - declare function useFruits(...fruits: Fruit[]): void; - useFruits(0); - `, - errors: [ - { - column: 19, - endColumn: 20, - line: 6, - messageId: 'provided', - }, - ], - }, - { - code: ` - enum Fruit { - Apple, - } - declare function useFruits(a: number, ...fruits: Fruit[]): void; - useFruits(0, Fruit.Apple, 0); - `, - errors: [ - { - column: 35, - endColumn: 36, - line: 6, - messageId: 'provided', - }, - ], - }, - { - code: ` - enum Fruit { - Apple, - } - const values = new Set(); - values.add(0); - `, - errors: [ - { - column: 20, - endColumn: 21, - line: 6, - messageId: 'provided', - }, - ], - }, - ], -}); From bc65e3c217e69a48e73fee82e731e2ebd227115f Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sun, 27 Nov 2022 10:46:32 -0500 Subject: [PATCH 86/88] Remove unrelated changes --- packages/eslint-plugin/src/rules/no-redeclare.ts | 3 +-- packages/eslint-plugin/src/rules/no-use-before-define.ts | 2 +- packages/eslint-plugin/src/rules/unbound-method.ts | 2 +- packages/eslint-plugin/src/util/collectUnusedVariables.ts | 7 ++----- packages/scope-manager/src/ScopeManager.ts | 6 +----- packages/scope-manager/src/referencer/VisitorBase.ts | 2 +- packages/scope-manager/src/scope/ScopeBase.ts | 2 +- packages/typescript-estree/src/convert-comments.ts | 2 +- 8 files changed, 9 insertions(+), 17 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-redeclare.ts b/packages/eslint-plugin/src/rules/no-redeclare.ts index 1eb2baa6de8d..2b10c97c8e76 100644 --- a/packages/eslint-plugin/src/rules/no-redeclare.ts +++ b/packages/eslint-plugin/src/rules/no-redeclare.ts @@ -1,4 +1,3 @@ -import { ScopeType } from '@typescript-eslint/scope-manager'; import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; @@ -257,7 +256,7 @@ export default util.createRule({ // Node.js or ES modules has a special scope. if ( - scope.type === ScopeType.global && + scope.type === 'global' && scope.childScopes[0] && // The special scope's block is the Program node. scope.block === scope.childScopes[0].block 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 ead8df0a6496..5153ed47fcd8 100644 --- a/packages/eslint-plugin/src/rules/no-use-before-define.ts +++ b/packages/eslint-plugin/src/rules/no-use-before-define.ts @@ -64,7 +64,7 @@ function isOuterEnum( reference: TSESLint.Scope.Reference, ): boolean { return ( - variable.defs[0].type === DefinitionType.TSEnumName && + variable.defs[0].type == DefinitionType.TSEnumName && variable.scope.variableScope !== reference.from.variableScope ); } diff --git a/packages/eslint-plugin/src/rules/unbound-method.ts b/packages/eslint-plugin/src/rules/unbound-method.ts index 33d041dbc270..c95a7fd35e1a 100644 --- a/packages/eslint-plugin/src/rules/unbound-method.ts +++ b/packages/eslint-plugin/src/rules/unbound-method.ts @@ -277,7 +277,7 @@ function checkMethod( const firstParam = decl.parameters[0]; const firstParamIsThis = firstParam?.name.kind === ts.SyntaxKind.Identifier && - firstParam?.name.escapedText === ts.InternalSymbolName.This; + firstParam?.name.escapedText === 'this'; const thisArgIsVoid = firstParamIsThis && firstParam?.type?.kind === ts.SyntaxKind.VoidKeyword; diff --git a/packages/eslint-plugin/src/util/collectUnusedVariables.ts b/packages/eslint-plugin/src/util/collectUnusedVariables.ts index 5ffe503eb1a1..ba3beb6861df 100644 --- a/packages/eslint-plugin/src/util/collectUnusedVariables.ts +++ b/packages/eslint-plugin/src/util/collectUnusedVariables.ts @@ -1,7 +1,4 @@ -import { - ImplicitLibVariable, - ScopeType, -} from '@typescript-eslint/scope-manager'; +import { ImplicitLibVariable } from '@typescript-eslint/scope-manager'; import { Visitor } from '@typescript-eslint/scope-manager/dist/referencer/Visitor'; import type { TSESTree } from '@typescript-eslint/utils'; import { @@ -101,7 +98,7 @@ class UnusedVarsVisitor< const scope = this.#scopeManager.acquire(node, inner); if (scope) { - if (scope.type === ScopeType.functionExpressionName) { + if (scope.type === 'function-expression-name') { return scope.childScopes[0] as T; } return scope as T; diff --git a/packages/scope-manager/src/ScopeManager.ts b/packages/scope-manager/src/ScopeManager.ts index 586db1123f45..5368cca1dc3b 100644 --- a/packages/scope-manager/src/ScopeManager.ts +++ b/packages/scope-manager/src/ScopeManager.ts @@ -14,7 +14,6 @@ import { GlobalScope, MappedTypeScope, ModuleScope, - ScopeType, SwitchScope, TSEnumScope, TSModuleScope, @@ -107,10 +106,7 @@ class ScopeManager { */ public acquire(node: TSESTree.Node, inner = false): Scope | null { function predicate(testScope: Scope): boolean { - if ( - testScope.type === ScopeType.function && - testScope.functionExpressionScope - ) { + if (testScope.type === 'function' && testScope.functionExpressionScope) { return false; } return true; diff --git a/packages/scope-manager/src/referencer/VisitorBase.ts b/packages/scope-manager/src/referencer/VisitorBase.ts index 04880d5ec7e7..5a7a8bbebe02 100644 --- a/packages/scope-manager/src/referencer/VisitorBase.ts +++ b/packages/scope-manager/src/referencer/VisitorBase.ts @@ -35,7 +35,7 @@ abstract class VisitorBase { node: T | null | undefined, excludeArr: (keyof T)[] = [], ): void { - if (node == null || node.type === null) { + if (node == null || node.type == null) { return; } diff --git a/packages/scope-manager/src/scope/ScopeBase.ts b/packages/scope-manager/src/scope/ScopeBase.ts index 6d7e3422900f..ae26d129cb56 100644 --- a/packages/scope-manager/src/scope/ScopeBase.ts +++ b/packages/scope-manager/src/scope/ScopeBase.ts @@ -363,7 +363,7 @@ abstract class ScopeBase< if (this.shouldStaticallyClose()) { closeRef = this.#staticCloseRef; - } else if (this.type !== ScopeType.global) { + } else if (this.type !== 'global') { closeRef = this.#dynamicCloseRef; } else { closeRef = this.#globalCloseRef; diff --git a/packages/typescript-estree/src/convert-comments.ts b/packages/typescript-estree/src/convert-comments.ts index d4dd9f124a79..ea02be412768 100644 --- a/packages/typescript-estree/src/convert-comments.ts +++ b/packages/typescript-estree/src/convert-comments.ts @@ -22,7 +22,7 @@ export function convertComments( ast, (_, comment) => { const type = - comment.kind === ts.SyntaxKind.SingleLineCommentTrivia + comment.kind == ts.SyntaxKind.SingleLineCommentTrivia ? AST_TOKEN_TYPES.Line : AST_TOKEN_TYPES.Block; const range: TSESTree.Range = [comment.pos, comment.end]; From 68ad65c176a4379d7a5883eda4c076eff450f88e Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sun, 11 Dec 2022 14:20:56 -0500 Subject: [PATCH 87/88] Reduce coverage --- .../eslint-plugin/src/rules/enum-utils/shared.ts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/packages/eslint-plugin/src/rules/enum-utils/shared.ts b/packages/eslint-plugin/src/rules/enum-utils/shared.ts index 23257d5e6116..6a3349143aa6 100644 --- a/packages/eslint-plugin/src/rules/enum-utils/shared.ts +++ b/packages/eslint-plugin/src/rules/enum-utils/shared.ts @@ -11,19 +11,13 @@ import * as util from '../../util'; * - `Fruit` --> `Fruit` * - `Fruit.Apple` --> `Fruit` */ -export function getBaseEnumType( - typeChecker: ts.TypeChecker, - type: ts.Type, -): ts.Type { - const symbol = type.getSymbol(); - if ( - !symbol?.valueDeclaration?.parent || - !tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.EnumMember) - ) { +function getBaseEnumType(typeChecker: ts.TypeChecker, type: ts.Type): ts.Type { + const symbol = type.getSymbol()!; + if (!tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.EnumMember)) { return type; } - return typeChecker.getTypeAtLocation(symbol.valueDeclaration.parent); + return typeChecker.getTypeAtLocation(symbol.valueDeclaration!.parent); } /** From 559c0ab5b06c9a5a13f7913401fb4bfba5a4ae7e Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Wed, 5 Apr 2023 13:58:23 -0400 Subject: [PATCH 88/88] Touched up docs --- .../docs/rules/no-unsafe-enum-comparison.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/no-unsafe-enum-comparison.md b/packages/eslint-plugin/docs/rules/no-unsafe-enum-comparison.md index 9712db992a30..6931d46d1b36 100644 --- a/packages/eslint-plugin/docs/rules/no-unsafe-enum-comparison.md +++ b/packages/eslint-plugin/docs/rules/no-unsafe-enum-comparison.md @@ -15,7 +15,8 @@ enum Fruit { Banana, } -let fruit = Fruit.Apple; +declare let fruit: Fruit; + fruit === 999; // No error ``` @@ -30,7 +31,8 @@ enum Fruit { Apple, } -let fruit = Fruit.Apple; +declare let fruit: Fruit; + fruit === 999; ``` @@ -39,7 +41,8 @@ enum Vegetable { Asparagus = 'asparagus', } -let vegetable = Vegetable.Asparagus; +declare let vegetable: Vegetable; + vegetable === 'asparagus'; ``` @@ -50,7 +53,8 @@ enum Fruit { Apple, } -let fruit = Fruit.Apple; +declare let fruit: Fruit; + fruit === Fruit.Banana; ``` @@ -59,7 +63,8 @@ enum Vegetable { Asparagus = 'asparagus', } -let vegetable = Vegetable.Asparagus; +declare let vegetable: Vegetable; + vegetable === Vegetable.Asparagus; ```