diff --git a/.eslintrc.js b/.eslintrc.js index 0423f907..93a919dc 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -14,17 +14,6 @@ module.exports = { rules: { // Base 'max-lines-per-function': 'off', - 'no-restricted-imports': [ - 'error', - { - patterns: [ - { - group: ['@typescript-eslint/utils/dist/*'], - message: 'Import from `@typescript-eslint/utils` instead.', - }, - ], - }, - ], // Import 'import/order': [ @@ -51,12 +40,12 @@ module.exports = { files: ['**/*.ts?(x)'], parser: '@typescript-eslint/parser', parserOptions: { + project: './tsconfig.eslint.json', tsconfigRootDir: __dirname, - project: ['./tsconfig.eslint.json'], }, extends: [ 'plugin:@typescript-eslint/recommended', - 'plugin:@typescript-eslint/recommended-requiring-type-checking', + 'plugin:@typescript-eslint/recommended-type-checked', 'plugin:import/typescript', ], rules: { diff --git a/.github/workflows/verifications.yml b/.github/workflows/verifications.yml index 0d5b16b2..09238588 100644 --- a/.github/workflows/verifications.yml +++ b/.github/workflows/verifications.yml @@ -35,22 +35,8 @@ jobs: strategy: fail-fast: false matrix: - node: [12.22.0, 12, 14.17.0, 14, 16, 17, 18, 19, 20, 22] - eslint: [7.5, 7, 8, 9] - exclude: - # eslint@9 doesn't support < Node v18 - - node: 17 - eslint: 9 - - node: 16 - eslint: 9 - - node: 14 - eslint: 9 - - node: 14.17.0 - eslint: 9 - - node: 12 - eslint: 9 - - node: 12.22.0 - eslint: 9 + node: [18.18.0, 18, 20.9.0, 20, 21.1.0, 21, 22, 23] + eslint: [8.57.0, 8, 9] steps: - name: Checkout uses: actions/checkout@v4 diff --git a/README.md b/README.md index 0fa46197..12761bc1 100644 --- a/README.md +++ b/README.md @@ -22,19 +22,19 @@ [![PRs Welcome][pr-badge]][pr-url] [![All Contributors][all-contributors-badge]](#contributors-) -## Installation +## Prerequisites -You'll first need to install [ESLint](https://eslint.org): +To use this plugin, you must have [Node.js](https://nodejs.org/en/) (`^18.18.0`, `^20.9.0`, or `>=21.1.0`) installed. -```shell -$ npm install --save-dev eslint -# or -$ yarn add --dev eslint -``` +## Installation + +You'll first need to [install ESLint](https://eslint.org/docs/latest/use/getting-started). Next, install `eslint-plugin-testing-library`: ```shell +$ pnpm add --save-dev eslint-plugin-testing-library +# or $ npm install --save-dev eslint-plugin-testing-library # or $ yarn add --dev eslint-plugin-testing-library @@ -49,6 +49,7 @@ You can find detailed guides for migrating `eslint-plugin-testing-library` in th - [Migration guide for v4](docs/migration-guides/v4.md) - [Migration guide for v5](docs/migration-guides/v5.md) - [Migration guide for v6](docs/migration-guides/v6.md) +- [Migration guide for v7](docs/migration-guides/v7.md) ## Usage diff --git a/docs/migration-guides/v7.md b/docs/migration-guides/v7.md new file mode 100644 index 00000000..f46957a9 --- /dev/null +++ b/docs/migration-guides/v7.md @@ -0,0 +1,14 @@ +# Guide: migrating to v7 + +If you are not on v6 yet, we recommend first following the [v6 migration guide](docs/migration-guides/v6.md). + +## Overview + +- **(Breaking)** Supported versions of Node.js have been updated to `^18.18.0`, `^20.9.0`, or `>=21.1.0`, matching ESLint. +- **(Breaking)** Supported versions of ESLint have been updated to `^8.57.0`, or `^9.0.0`. +- Full support for ESLint v9 (v8 still compatible) and typescript-eslint v8 + +## Steps to upgrade + +1. Make sure you are using a supported version of Node.js, and upgrade if not. +2. Make sure you are using a supported version of ESLint, and upgrade if not. diff --git a/lib/configs/index.ts b/lib/configs/index.ts index 15bcc709..eb441b29 100644 --- a/lib/configs/index.ts +++ b/lib/configs/index.ts @@ -1,6 +1,6 @@ import { join } from 'path'; -import { type TSESLint } from '@typescript-eslint/utils'; +import type { TSESLint } from '@typescript-eslint/utils'; import { importDefault, @@ -8,12 +8,10 @@ import { SupportedTestingFramework, } from '../utils'; -export type LinterConfigRules = Pick, 'rules'>; - const configsDir = __dirname; const getConfigForFramework = (framework: SupportedTestingFramework) => - importDefault(join(configsDir, framework)); + importDefault(join(configsDir, framework)); export default SUPPORTED_TESTING_FRAMEWORKS.reduce( (allConfigs, framework) => ({ @@ -21,4 +19,4 @@ export default SUPPORTED_TESTING_FRAMEWORKS.reduce( [framework]: getConfigForFramework(framework), }), {} -) as Record; +) as Record; diff --git a/lib/create-testing-library-rule/detect-testing-library-utils.ts b/lib/create-testing-library-rule/detect-testing-library-utils.ts index af263a9d..001dc532 100644 --- a/lib/create-testing-library-rule/detect-testing-library-utils.ts +++ b/lib/create-testing-library-rule/detect-testing-library-utils.ts @@ -25,17 +25,19 @@ import { PRESENCE_MATCHERS, } from '../utils'; -const SETTING_OPTION_OFF = 'off' as const; +const SETTING_OPTION_OFF = 'off'; export type TestingLibrarySettings = { - 'testing-library/utils-module'?: string | typeof SETTING_OPTION_OFF; + 'testing-library/utils-module'?: + | typeof SETTING_OPTION_OFF + | (string & NonNullable); 'testing-library/custom-renders'?: string[] | typeof SETTING_OPTION_OFF; 'testing-library/custom-queries'?: string[] | typeof SETTING_OPTION_OFF; }; export type TestingLibraryContext< - TOptions extends readonly unknown[], TMessageIds extends string, + TOptions extends readonly unknown[], > = Readonly< TSESLint.RuleContext & { settings: TestingLibrarySettings; @@ -43,14 +45,13 @@ export type TestingLibraryContext< >; export type EnhancedRuleCreate< - TOptions extends readonly unknown[], TMessageIds extends string, - TRuleListener extends TSESLint.RuleListener = TSESLint.RuleListener, + TOptions extends readonly unknown[], > = ( - context: TestingLibraryContext, + context: TestingLibraryContext, optionsWithDefault: Readonly, detectionHelpers: Readonly -) => TRuleListener; +) => TSESLint.RuleListener; // Helpers methods type GetTestingLibraryImportNodeFn = () => ImportModuleNode | null; @@ -154,15 +155,14 @@ export type DetectionOptions = { * Enhances a given rule `create` with helpers to detect Testing Library utils. */ export function detectTestingLibraryUtils< - TOptions extends readonly unknown[], TMessageIds extends string, - TRuleListener extends TSESLint.RuleListener = TSESLint.RuleListener, + TOptions extends readonly unknown[], >( - ruleCreate: EnhancedRuleCreate, + ruleCreate: EnhancedRuleCreate, { skipRuleReportingCheck = false }: Partial = {} ) { return ( - context: TestingLibraryContext, + context: TestingLibraryContext, optionsWithDefault: Readonly ): TSESLint.RuleListener => { const importedTestingLibraryNodes: ImportModuleNode[] = []; @@ -212,6 +212,7 @@ export function detectTestingLibraryUtils< const originalNodeName = isImportSpecifier(importedUtilSpecifier) && + ASTUtils.isIdentifier(importedUtilSpecifier.imported) && importedUtilSpecifier.local.name !== importedUtilSpecifier.imported.name ? importedUtilSpecifier.imported.name : undefined; diff --git a/lib/create-testing-library-rule/index.ts b/lib/create-testing-library-rule/index.ts index c87f6415..82e28403 100644 --- a/lib/create-testing-library-rule/index.ts +++ b/lib/create-testing-library-rule/index.ts @@ -1,6 +1,6 @@ -import { ESLintUtils, TSESLint } from '@typescript-eslint/utils'; +import { ESLintUtils } from '@typescript-eslint/utils'; -import { getDocsUrl, TestingLibraryRuleMeta } from '../utils'; +import { getDocsUrl, TestingLibraryPluginDocs } from '../utils'; import { DetectionOptions, @@ -8,37 +8,30 @@ import { EnhancedRuleCreate, } from './detect-testing-library-utils'; -export function createTestingLibraryRule< +export const createTestingLibraryRule = < TOptions extends readonly unknown[], TMessageIds extends string, - TRuleListener extends TSESLint.RuleListener = TSESLint.RuleListener, >({ create, detectionOptions = {}, - meta, ...remainingConfig -}: Readonly<{ - name: string; - meta: TestingLibraryRuleMeta; - defaultOptions: Readonly; - detectionOptions?: Partial; - create: EnhancedRuleCreate; -}>): TSESLint.RuleModule { - // eslint-disable-next-line new-cap - return ESLintUtils.RuleCreator(getDocsUrl)({ +}: Readonly< + Omit< + ESLintUtils.RuleWithMetaAndName< + TOptions, + TMessageIds, + TestingLibraryPluginDocs + >, + 'create' + > & { + create: EnhancedRuleCreate; + detectionOptions?: Partial; + } +>) => + ESLintUtils.RuleCreator>(getDocsUrl)({ ...remainingConfig, - create: detectTestingLibraryUtils( + create: detectTestingLibraryUtils( create, detectionOptions ), - meta: { - ...meta, - docs: { - ...meta.docs, - // We're using our own recommendedConfig meta to tell our build tools - // if the rule is recommended on a config basis - recommended: false, - }, - }, }); -} diff --git a/lib/index.ts b/lib/index.ts index bfcdfb12..bb6f4db6 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -8,7 +8,7 @@ import { SupportedTestingFramework } from './utils'; const { name: packageName, version: packageVersion, - // eslint-disable-next-line @typescript-eslint/no-var-requires + // eslint-disable-next-line @typescript-eslint/no-require-imports } = require('../package.json') as { name: string; version: string }; const plugin = { @@ -20,7 +20,7 @@ const plugin = { // we don't have types for flat config yet configs: {} as Record< SupportedTestingFramework | `flat/${SupportedTestingFramework}`, - Pick, 'rules'> + TSESLint.SharedConfig.RulesRecord >, rules, }; @@ -35,9 +35,9 @@ plugin.configs = { rules: config.rules, }, ]) - ) as Record< + ) as unknown as Record< `flat/${SupportedTestingFramework}`, - Pick, 'rules'> & { plugins: unknown } + TSESLint.SharedConfig.RulesRecord & { plugins: unknown } >), }; diff --git a/lib/node-utils/index.ts b/lib/node-utils/index.ts index 9e9e9b04..85714c48 100644 --- a/lib/node-utils/index.ts +++ b/lib/node-utils/index.ts @@ -1,8 +1,8 @@ +import { FunctionScope, ScopeType } from '@typescript-eslint/scope-manager'; import { AST_NODE_TYPES, ASTUtils, TSESLint, - TSESLintScope, TSESTree, } from '@typescript-eslint/utils'; @@ -188,7 +188,7 @@ export function isPromiseAllSettled(node: TSESTree.CallExpression): boolean { } /** - * Determines whether a given node belongs to handled Promise.all or Promise.allSettled + * Determines whether a given node belongs to handled `Promise.all` or `Promise.allSettled` * array expression. */ export function isPromisesArrayResolved(node: TSESTree.Node): boolean { @@ -295,7 +295,7 @@ export function getVariableReferences( return []; } -interface InnermostFunctionScope extends TSESLintScope.FunctionScope { +interface InnermostFunctionScope extends FunctionScope { block: | TSESTree.ArrowFunctionExpression | TSESTree.FunctionDeclaration @@ -312,7 +312,7 @@ export function getInnermostFunctionScope( ); if ( - innermostScope.type === 'function' && + innermostScope.type === ScopeType.function && ASTUtils.isFunction(innermostScope.block) ) { return innermostScope as unknown as InnermostFunctionScope; @@ -665,6 +665,7 @@ export function findImportSpecifier( const namedExport = node.specifiers.find((n) => { return ( isImportSpecifier(n) && + ASTUtils.isIdentifier(n.imported) && [n.imported.name, n.local.name].includes(specifierName) ); }); diff --git a/lib/rules/await-async-events.ts b/lib/rules/await-async-events.ts index 219c45bf..7d4d81e2 100644 --- a/lib/rules/await-async-events.ts +++ b/lib/rules/await-async-events.ts @@ -55,15 +55,15 @@ export default createTestingLibraryRule({ default: USER_EVENT_NAME, oneOf: [ { + enum: EVENTS_SIMULATORS.concat(), type: 'string', - enum: EVENTS_SIMULATORS, }, { - type: 'array', items: { type: 'string', - enum: EVENTS_SIMULATORS, + enum: EVENTS_SIMULATORS.concat(), }, + type: 'array', }, ], }, diff --git a/lib/rules/index.ts b/lib/rules/index.ts index 7a340ac0..94dc6754 100644 --- a/lib/rules/index.ts +++ b/lib/rules/index.ts @@ -1,15 +1,7 @@ import { readdirSync } from 'fs'; import { join, parse } from 'path'; -import { TSESLint } from '@typescript-eslint/utils'; - -import { importDefault, TestingLibraryRuleMeta } from '../utils'; - -type RuleModule = TSESLint.RuleModule & { - meta: TestingLibraryRuleMeta & { - recommended: false; - }; -}; +import { importDefault, TestingLibraryPluginRuleModule } from '../utils'; const rulesDir = __dirname; const excludedFiles = ['index']; @@ -17,10 +9,12 @@ const excludedFiles = ['index']; export default readdirSync(rulesDir) .map((rule) => parse(rule).name) .filter((ruleName) => !excludedFiles.includes(ruleName)) - .reduce>( + .reduce>>( (allRules, ruleName) => ({ ...allRules, - [ruleName]: importDefault(join(rulesDir, ruleName)), + [ruleName]: importDefault< + TestingLibraryPluginRuleModule + >(join(rulesDir, ruleName)), }), {} ); diff --git a/lib/rules/no-await-sync-events.ts b/lib/rules/no-await-sync-events.ts index 0a18b195..534c3340 100644 --- a/lib/rules/no-await-sync-events.ts +++ b/lib/rules/no-await-sync-events.ts @@ -9,9 +9,9 @@ import { isProperty, } from '../node-utils'; -const USER_EVENT_ASYNC_EXCEPTIONS: string[] = ['type', 'keyboard']; -const FIRE_EVENT_OPTION = 'fire-event' as const; -const USER_EVENT_OPTION = 'user-event' as const; +const USER_EVENT_ASYNC_EXCEPTIONS = ['type', 'keyboard']; +const FIRE_EVENT_OPTION = 'fire-event'; +const USER_EVENT_OPTION = 'user-event'; const VALID_EVENT_MODULES = [FIRE_EVENT_OPTION, USER_EVENT_OPTION]; const DEFAULT_EVENT_MODULES = [FIRE_EVENT_OPTION]; diff --git a/lib/rules/no-debugging-utils.ts b/lib/rules/no-debugging-utils.ts index 3978fbde..cccc69d0 100644 --- a/lib/rules/no-debugging-utils.ts +++ b/lib/rules/no-debugging-utils.ts @@ -53,7 +53,7 @@ export default createTestingLibraryRule({ utilsToCheckFor: { type: 'object', properties: DEBUG_UTILS.reduce< - Record + Record >( (obj, name) => ({ [name]: { type: 'boolean' }, diff --git a/lib/rules/no-dom-import.ts b/lib/rules/no-dom-import.ts index a095e013..b35e7203 100644 --- a/lib/rules/no-dom-import.ts +++ b/lib/rules/no-dom-import.ts @@ -13,7 +13,7 @@ const DOM_TESTING_LIBRARY_MODULES = [ ]; const CORRECT_MODULE_NAME_BY_FRAMEWORK: Record< - 'angular' | 'marko' | string, + 'angular' | 'marko' | (string & NonNullable), string | undefined > = { angular: '@testing-library/angular', // ATL is *always* called `@testing-library/angular` diff --git a/lib/rules/no-manual-cleanup.ts b/lib/rules/no-manual-cleanup.ts index ee65ee71..184f23ed 100644 --- a/lib/rules/no-manual-cleanup.ts +++ b/lib/rules/no-manual-cleanup.ts @@ -75,6 +75,7 @@ export default createTestingLibraryRule({ const cleanupSpecifier = moduleNode.specifiers.find( (specifier) => isImportSpecifier(specifier) && + ASTUtils.isIdentifier(specifier.imported) && specifier.imported.name === 'cleanup' ); diff --git a/lib/rules/no-render-in-lifecycle.ts b/lib/rules/no-render-in-lifecycle.ts index 2e5e52c1..27771c52 100644 --- a/lib/rules/no-render-in-lifecycle.ts +++ b/lib/rules/no-render-in-lifecycle.ts @@ -68,6 +68,7 @@ export default createTestingLibraryRule({ properties: { allowTestingFrameworkSetupHook: { enum: TESTING_FRAMEWORK_SETUP_HOOKS, + type: 'string', }, }, }, diff --git a/lib/rules/prefer-explicit-assert.ts b/lib/rules/prefer-explicit-assert.ts index 4b0d57ea..82cfaafa 100644 --- a/lib/rules/prefer-explicit-assert.ts +++ b/lib/rules/prefer-explicit-assert.ts @@ -21,10 +21,11 @@ type Options = [ const isAtTopLevel = (node: TSESTree.Node) => (!!node.parent?.parent && - node.parent.parent.type === 'ExpressionStatement') || - (node.parent?.parent?.type === 'AwaitExpression' && + node.parent.parent.type === TSESTree.AST_NODE_TYPES.ExpressionStatement) || + (node.parent?.parent?.type === TSESTree.AST_NODE_TYPES.AwaitExpression && !!node.parent.parent.parent && - node.parent.parent.parent.type === 'ExpressionStatement'); + node.parent.parent.parent.type === + TSESTree.AST_NODE_TYPES.ExpressionStatement); const isVariableDeclaration = (node: TSESTree.Node) => { if ( diff --git a/lib/rules/prefer-query-by-disappearance.ts b/lib/rules/prefer-query-by-disappearance.ts index f19b3796..19aa670a 100644 --- a/lib/rules/prefer-query-by-disappearance.ts +++ b/lib/rules/prefer-query-by-disappearance.ts @@ -53,10 +53,10 @@ export default createTestingLibraryRule({ /** * Checks if node is reportable (starts with "get" or "find") and if it is, reports it with `context.report()`. * - * @param {TSESTree.LeftHandSideExpression} node - Node to be tested + * @param {TSESTree.Expression} node - Node to be tested * @returns {Boolean} Boolean indicating if expression was reported */ - function reportExpression(node: TSESTree.LeftHandSideExpression): boolean { + function reportExpression(node: TSESTree.Expression): boolean { const argumentProperty = isMemberExpression(node) ? getPropertyIdentifierNode(node.property) : getPropertyIdentifierNode(node); diff --git a/lib/utils/compat.ts b/lib/utils/compat.ts index 2216dd8d..0ad5e68c 100644 --- a/lib/utils/compat.ts +++ b/lib/utils/compat.ts @@ -1,50 +1,4 @@ -import { type TSESLint, type TSESTree } from '@typescript-eslint/utils'; - -declare module '@typescript-eslint/utils/dist/ts-eslint/Rule' { - export interface RuleContext< - // eslint-disable-next-line @typescript-eslint/no-unused-vars - TMessageIds extends string, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - TOptions extends readonly unknown[], - > { - /** - * The filename associated with the source. - */ - filename: string; - - /** - * A SourceCode object that you can use to work with the source that - * was passed to ESLint. - */ - sourceCode: Readonly; - } -} - -declare module '@typescript-eslint/utils/dist/ts-eslint/SourceCode' { - export interface SourceCode { - /** - * Returns the scope of the given node. - * This information can be used track references to variables. - * @since 8.37.0 - */ - getScope(node: TSESTree.Node): TSESLint.Scope.Scope; - /** - * Returns an array of the ancestors of the given node, starting at - * the root of the AST and continuing through the direct parent of the current node. - * This array does not include the currently-traversed node itself. - * @since 8.38.0 - */ - getAncestors(node: TSESTree.Node): TSESTree.Node[]; - /** - * Returns a list of variables declared by the given node. - * This information can be used to track references to variables. - * @since 8.38.0 - */ - getDeclaredVariables( - node: TSESTree.Node - ): readonly TSESLint.Scope.Variable[]; - } -} +import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; /* istanbul ignore next */ export const getFilename = ( diff --git a/lib/utils/file-import.ts b/lib/utils/file-import.ts index 6bfeae0f..c4198089 100644 --- a/lib/utils/file-import.ts +++ b/lib/utils/file-import.ts @@ -5,5 +5,5 @@ const interopRequireDefault = (obj: any): { default: T } => obj?.__esModule ? obj : { default: obj }; export const importDefault = (moduleName: string): T => - // eslint-disable-next-line @typescript-eslint/no-var-requires + // eslint-disable-next-line @typescript-eslint/no-require-imports interopRequireDefault(require(moduleName)).default; diff --git a/lib/utils/types.ts b/lib/utils/types.ts index 1dd6d9d3..6b42fbde 100644 --- a/lib/utils/types.ts +++ b/lib/utils/types.ts @@ -1,29 +1,30 @@ -import { type TSESLint } from '@typescript-eslint/utils'; +import { TSESLint } from '@typescript-eslint/utils'; +type Recommended = 'error' | 'warn' | false; type RecommendedConfig = - | TSESLint.RuleMetaDataDocs['recommended'] - | [TSESLint.RuleMetaDataDocs['recommended'], ...TOptions]; + | Recommended + | [Recommended, ...TOptions]; -// These 2 types are copied from @typescript-eslint/utils' CreateRuleMeta -// and modified to our needs -export type TestingLibraryRuleMetaDocs = - Omit & { - /** - * The recommendation level for the rule on a framework basis. - * Used by the build tools to generate the framework config. - * Set to false to not include it the config - */ - recommendedConfig: Record< - SupportedTestingFramework, - RecommendedConfig - >; - }; -export type TestingLibraryRuleMeta< +export type TestingLibraryPluginDocs = { + /** + * The recommendation level for the rule on a framework basis. + * Used by the build tools to generate the framework config. + * Set to `false` to not include it the config + */ + recommendedConfig: Record< + SupportedTestingFramework, + RecommendedConfig + >; +}; + +export type TestingLibraryPluginRuleModule< TMessageIds extends string, TOptions extends readonly unknown[], -> = Omit, 'docs'> & { - docs: TestingLibraryRuleMetaDocs; -}; +> = TSESLint.RuleModuleWithMetaDocs< + TMessageIds, + TOptions, + TestingLibraryPluginDocs +>; export const SUPPORTED_TESTING_FRAMEWORKS = [ 'dom', diff --git a/lint-staged.config.js b/lint-staged.config.js index bbbe515d..cb757928 100644 --- a/lint-staged.config.js +++ b/lint-staged.config.js @@ -1,4 +1,4 @@ -//eslint-disable-next-line @typescript-eslint/no-var-requires +//eslint-disable-next-line @typescript-eslint/no-require-imports const { ESLint } = require('eslint'); const removeIgnoredFiles = async (files) => { diff --git a/package-lock.json b/package-lock.json index eb037dbb..e9fccd9c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,8 @@ "version": "0.0.0-semantically-released", "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^5.62.0" + "@typescript-eslint/scope-manager": "^8.15.0", + "@typescript-eslint/utils": "^8.15.0" }, "devDependencies": { "@babel/core": "^7.25.8", @@ -21,15 +22,16 @@ "@swc/jest": "^0.2.36", "@types/jest": "^27.5.2", "@types/node": "^22.8.6", - "@typescript-eslint/eslint-plugin": "^5.62.0", - "@typescript-eslint/parser": "^5.62.0", + "@typescript-eslint/eslint-plugin": "^8.15.0", + "@typescript-eslint/parser": "^8.15.0", + "@typescript-eslint/rule-tester": "^8.15.0", "del-cli": "^5.1.0", "eslint": "^8.57.1", "eslint-config-prettier": "^9.1.0", "eslint-doc-generator": "^1.7.1", "eslint-import-resolver-typescript": "^3.6.3", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jest": "^27.9.0", + "eslint-plugin-jest": "^28.8.3", "eslint-plugin-jest-formatting": "^3.1.0", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^6.6.0", @@ -47,11 +49,11 @@ "typescript": "5.0.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0", - "npm": ">=6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0", + "npm": ">=9.8.1" }, "peerDependencies": { - "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" + "eslint": "^8.57.0 || ^9.0.0" } }, "node_modules/@ampproject/remapping": { @@ -3562,7 +3564,8 @@ "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true }, "node_modules/@types/json5": { "version": "0.0.29", @@ -3606,7 +3609,8 @@ "node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true }, "node_modules/@types/stack-utils": { "version": "2.0.3", @@ -3636,32 +3640,32 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", - "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.15.0.tgz", + "integrity": "sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==", "dev": true, + "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/type-utils": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/type-utils": "8.15.0", + "@typescript-eslint/utils": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -3670,25 +3674,27 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", - "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.15.0.tgz", + "integrity": "sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "debug": "^4.3.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -3696,16 +3702,66 @@ } } }, + "node_modules/@typescript-eslint/rule-tester": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/rule-tester/-/rule-tester-8.15.0.tgz", + "integrity": "sha512-G9lQX5jX64wrP5nI1nAEBj48dgyYFH8f0pjruQD9byK0Ln2cOyZPMt51rnzsm5ru8Nc7exV5SYyRppEhzaqSfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/utils": "8.15.0", + "ajv": "^6.12.6", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "4.6.2", + "semver": "^7.6.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/@typescript-eslint/rule-tester/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@typescript-eslint/rule-tester/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.15.0.tgz", + "integrity": "sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==", + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -3713,25 +3769,26 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", - "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.15.0.tgz", + "integrity": "sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "5.62.0", - "@typescript-eslint/utils": "5.62.0", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/utils": "8.15.0", "debug": "^4.3.4", - "tsutils": "^3.21.0" + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "*" + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -3740,11 +3797,12 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.15.0.tgz", + "integrity": "sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==", + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -3752,20 +3810,22 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.15.0.tgz", + "integrity": "sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==", + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "debug": "^4.3.4", - "globby": "^11.1.0", + "fast-glob": "^3.3.2", "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -3777,41 +3837,68 @@ } } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.15.0.tgz", + "integrity": "sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==", + "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.15.0.tgz", + "integrity": "sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==", + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" + "@typescript-eslint/types": "8.15.0", + "eslint-visitor-keys": "^4.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -3819,11 +3906,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -4050,6 +4138,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, "engines": { "node": ">=8" } @@ -5439,6 +5528,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, "dependencies": { "path-type": "^4.0.0" }, @@ -5791,6 +5881,111 @@ "eslint": ">= 7" } }, + "node_modules/eslint-doc-generator/node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-doc-generator/node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-doc-generator/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-doc-generator/node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-doc-generator/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/eslint-doc-generator/node_modules/dot-prop": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-7.2.0.tgz", @@ -5818,6 +6013,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint-doc-generator/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/eslint-import-resolver-node": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", @@ -5983,19 +6191,20 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", - "integrity": "sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==", + "version": "28.8.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.3.tgz", + "integrity": "sha512-HIQ3t9hASLKm2IhIOqnu+ifw7uLZkIlR7RYNv7fMcEi/p0CIiJmfriStQS2LDkgtY4nyLbIZAD+JL347Yc2ETQ==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^5.10.0" + "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^16.10.0 || ^18.12.0 || >=20.0.0" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0 || ^7.0.0", - "eslint": "^7.0.0 || ^8.0.0", + "@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0 || ^8.0.0", + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0", "jest": "*" }, "peerDependenciesMeta": { @@ -6183,6 +6392,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -6468,6 +6678,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, "engines": { "node": ">=4.0" } @@ -7162,6 +7373,7 @@ "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -7181,6 +7393,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, "engines": { "node": ">=8" } @@ -12123,12 +12336,6 @@ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -15173,6 +15380,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, "engines": { "node": ">=8" } @@ -16982,6 +17190,18 @@ "node": ">=8" } }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -17068,6 +17288,8 @@ "version": "3.21.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "license": "MIT", "dependencies": { "tslib": "^1.8.1" }, @@ -17081,7 +17303,9 @@ "node_modules/tsutils/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" }, "node_modules/type-check": { "version": "0.4.0", @@ -20262,7 +20486,8 @@ "@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true }, "@types/json5": { "version": "0.0.29", @@ -20306,7 +20531,8 @@ "@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true }, "@types/stack-utils": { "version": "2.0.3", @@ -20336,103 +20562,152 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", - "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.15.0.tgz", + "integrity": "sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==", "dev": true, "requires": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/type-utils": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/type-utils": "8.15.0", + "@typescript-eslint/utils": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/parser": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", - "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.15.0.tgz", + "integrity": "sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "debug": "^4.3.4" } }, + "@typescript-eslint/rule-tester": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/rule-tester/-/rule-tester-8.15.0.tgz", + "integrity": "sha512-G9lQX5jX64wrP5nI1nAEBj48dgyYFH8f0pjruQD9byK0Ln2cOyZPMt51rnzsm5ru8Nc7exV5SYyRppEhzaqSfg==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/utils": "8.15.0", + "ajv": "^6.12.6", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "4.6.2", + "semver": "^7.6.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + } + } + }, "@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.15.0.tgz", + "integrity": "sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==", "requires": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0" } }, "@typescript-eslint/type-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", - "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.15.0.tgz", + "integrity": "sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.62.0", - "@typescript-eslint/utils": "5.62.0", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/utils": "8.15.0", "debug": "^4.3.4", - "tsutils": "^3.21.0" + "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==" + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.15.0.tgz", + "integrity": "sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==" }, "@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.15.0.tgz", + "integrity": "sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==", "requires": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "debug": "^4.3.4", - "globby": "^11.1.0", + "fast-glob": "^3.3.2", "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "requires": { + "brace-expansion": "^2.0.1" + } + } } }, "@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.15.0.tgz", + "integrity": "sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==", "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0" } }, "@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.15.0.tgz", + "integrity": "sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==", "requires": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" + "@typescript-eslint/types": "8.15.0", + "eslint-visitor-keys": "^4.2.0" }, "dependencies": { "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==" } } }, @@ -20597,7 +20872,8 @@ "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true }, "array.prototype.findlastindex": { "version": "1.2.5", @@ -21557,6 +21833,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, "requires": { "path-type": "^4.0.0" } @@ -21937,6 +22214,63 @@ "type-fest": "^3.0.0" }, "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + } + }, + "@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + } + }, "dot-prop": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-7.2.0.tgz", @@ -21953,6 +22287,12 @@ "dev": true } } + }, + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true } } }, @@ -22078,12 +22418,12 @@ } }, "eslint-plugin-jest": { - "version": "27.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", - "integrity": "sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==", + "version": "28.8.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.3.tgz", + "integrity": "sha512-HIQ3t9hASLKm2IhIOqnu+ifw7uLZkIlR7RYNv7fMcEi/p0CIiJmfriStQS2LDkgtY4nyLbIZAD+JL347Yc2ETQ==", "dev": true, "requires": { - "@typescript-eslint/utils": "^5.10.0" + "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "eslint-plugin-jest-formatting": { @@ -22204,6 +22544,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, "requires": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -22288,7 +22629,8 @@ "estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true }, "esutils": { "version": "2.0.3", @@ -22804,6 +23146,7 @@ "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, "requires": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -22816,7 +23159,8 @@ "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true } } }, @@ -26442,12 +26786,6 @@ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" }, - "natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -28567,7 +28905,8 @@ "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true }, "picocolors": { "version": "1.1.1", @@ -29909,6 +30248,12 @@ "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true }, + "ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "requires": {} + }, "ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -29969,6 +30314,7 @@ "version": "3.21.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, "requires": { "tslib": "^1.8.1" }, @@ -29976,7 +30322,8 @@ "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true } } }, diff --git a/package.json b/package.json index 30ae54f8..ba109d78 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,8 @@ "type-check": "tsc --noEmit" }, "dependencies": { - "@typescript-eslint/utils": "^5.62.0" + "@typescript-eslint/scope-manager": "^8.15.0", + "@typescript-eslint/utils": "^8.15.0" }, "devDependencies": { "@babel/core": "^7.25.8", @@ -65,15 +66,16 @@ "@swc/jest": "^0.2.36", "@types/jest": "^27.5.2", "@types/node": "^22.8.6", - "@typescript-eslint/eslint-plugin": "^5.62.0", - "@typescript-eslint/parser": "^5.62.0", + "@typescript-eslint/eslint-plugin": "^8.15.0", + "@typescript-eslint/parser": "^8.15.0", + "@typescript-eslint/rule-tester": "^8.15.0", "del-cli": "^5.1.0", "eslint": "^8.57.1", "eslint-config-prettier": "^9.1.0", "eslint-doc-generator": "^1.7.1", "eslint-import-resolver-typescript": "^3.6.3", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jest": "^27.9.0", + "eslint-plugin-jest": "^28.8.3", "eslint-plugin-jest-formatting": "^3.1.0", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^6.6.0", @@ -91,10 +93,10 @@ "typescript": "5.0.4" }, "peerDependencies": { - "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" + "eslint": "^8.57.0 || ^9.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0", - "npm": ">=6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0", + "npm": ">=9.8.1" } } diff --git a/tests/eslint-remote-tester.config.js b/tests/eslint-remote-tester.config.js index 730b5579..f7c63992 100644 --- a/tests/eslint-remote-tester.config.js +++ b/tests/eslint-remote-tester.config.js @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable @typescript-eslint/no-require-imports */ /* eslint-disable import/no-extraneous-dependencies */ const { rules } = require('eslint-plugin-testing-library'); const { diff --git a/tests/index.test.ts b/tests/index.test.ts index 68cfb521..d6dc83eb 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -72,7 +72,7 @@ it('should export configs that refer to actual rules', () => { expect(rule.startsWith(ruleNamePrefix)).toBe(true); expect(ruleNames).toContain(ruleName); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-require-imports expect(() => require(`../lib/rules/${ruleName}`)).not.toThrow(); }); }); diff --git a/tests/lib/FlatCompatRuleTester.ts b/tests/lib/FlatCompatRuleTester.ts deleted file mode 100644 index b3ef5943..00000000 --- a/tests/lib/FlatCompatRuleTester.ts +++ /dev/null @@ -1,191 +0,0 @@ -import { TSESLint } from '@typescript-eslint/utils'; -import { version as eslintVersion } from 'eslint/package.json'; -import * as semver from 'semver'; - -export const usingFlatConfig = semver.major(eslintVersion) >= 9; - -declare module '@typescript-eslint/utils/dist/ts-eslint' { - // eslint-disable-next-line @typescript-eslint/no-namespace - export namespace FlatConfig { - export interface LinterOptions { - /** - * A Boolean value indicating if inline configuration is allowed. - */ - noInlineConfig?: boolean; - /** - * A severity string indicating if and how unused disable and enable - * directives should be tracked and reported. For legacy compatibility, `true` - * is equivalent to `"warn"` and `false` is equivalent to `"off"`. - * @default "off" - */ - reportUnusedDisableDirectives?: - | TSESLint.Linter.Severity - | TSESLint.Linter.SeverityString - | boolean; - } - - export interface Config { - /** - * An string to identify the configuration object. Used in error messages and inspection tools. - */ - name?: string; - /** - * An array of glob patterns indicating the files that the configuration object should apply to. - * If not specified, the configuration object applies to all files matched by any other configuration object. - */ - files?: (string | string[])[]; - /** - * An array of glob patterns indicating the files that the configuration object should not apply to. - * If not specified, the configuration object applies to all files matched by files. - */ - ignores?: string[]; - /** - * An object containing settings related to how JavaScript is configured for linting. - */ - languageOptions?: LanguageOptions; - /** - * An object containing settings related to the linting process. - */ - linterOptions?: LinterOptions; - /** - * An object containing a name-value mapping of plugin names to plugin objects. - * When `files` is specified, these plugins are only available to the matching files. - */ - plugins?: unknown; - /** - * Either an object containing `preprocess()` and `postprocess()` methods or - * a string indicating the name of a processor inside of a plugin - * (i.e., `"pluginName/processorName"`). - */ - processor?: string | TSESLint.Linter.Processor; - /** - * An object containing the configured rules. - * When `files` or `ignores` are specified, these rule configurations are only available to the matching files. - */ - rules?: TSESLint.Linter.RulesRecord; - /** - * An object containing name-value pairs of information that should be available to all rules. - */ - settings?: TSESLint.SharedConfigurationSettings; - } - - export type ParserOptions = TSESLint.Linter.ParserOptions; - - export interface LanguageOptions { - /** - * The version of ECMAScript to support. - * May be any year (i.e., `2022`) or version (i.e., `5`). - * Set to `"latest"` for the most recent supported version. - * @default "latest" - */ - ecmaVersion?: Required['ecmaVersion']; - /** - * An object specifying additional objects that should be added to the global scope during linting. - */ - globals?: - | Record - | undefined; - /** - * An object containing a `parse()` method or a `parseForESLint()` method. - * @default - * ``` - * // https://github.com/eslint/espree - * require('espree') - * ``` - */ - parser?: unknown; - /** - * An object specifying additional options that are passed directly to the parser. - * The available options are parser-dependent. - */ - parserOptions?: ParserOptions | undefined; - /** - * The type of JavaScript source code. - * Possible values are `"script"` for traditional script files, `"module"` for ECMAScript modules (ESM), and `"commonjs"` for CommonJS files. - * @default - * ``` - * // for `.js` and `.mjs` files - * "module" - * // for `.cjs` files - * "commonjs" - * ``` - */ - sourceType?: Required['sourceType']; - } - } -} - -export class FlatCompatRuleTester extends TSESLint.RuleTester { - public constructor(testerConfig?: TSESLint.RuleTesterConfig) { - super(FlatCompatRuleTester._flatCompat(testerConfig)); - } - - public override run< - TMessageIds extends string, - TOptions extends readonly unknown[], - >( - ruleName: string, - rule: TSESLint.RuleModule, - tests: TSESLint.RunTests - ) { - super.run(ruleName, rule, { - valid: tests.valid.map((t) => FlatCompatRuleTester._flatCompat(t)), - invalid: tests.invalid.map((t) => FlatCompatRuleTester._flatCompat(t)), - }); - } - - /* istanbul ignore next */ - private static _flatCompat< - T extends - | undefined - | TSESLint.RuleTesterConfig - | string - | TSESLint.ValidTestCase - | TSESLint.InvalidTestCase, - >(config: T): T { - if (!config || !usingFlatConfig || typeof config === 'string') { - return config; - } - - const obj: TSESLint.FlatConfig.Config & { - languageOptions: TSESLint.FlatConfig.LanguageOptions & { - parserOptions: TSESLint.FlatConfig.ParserOptions; - }; - } = { - languageOptions: { parserOptions: {} }, - }; - - for (const [key, value] of Object.entries(config)) { - if (key === 'parser') { - obj.languageOptions.parser = require(value as string); - - continue; - } - - if (key === 'parserOptions') { - for (const [option, val] of Object.entries( - value as { [s: string]: unknown } - )) { - if (option === 'ecmaVersion' || option === 'sourceType') { - // @ts-expect-error: TS thinks the value could the opposite type of whatever option is - obj.languageOptions[option] = - val as TSESLint.FlatConfig.LanguageOptions[ - | 'ecmaVersion' - | 'sourceType']; - - continue; - } - - obj.languageOptions.parserOptions[option] = val; - } - - continue; - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - obj[key as keyof typeof obj] = value; - } - - return obj as unknown as T; - } -} diff --git a/tests/lib/test-utils.ts b/tests/lib/test-utils.ts index aed679c7..c65ac6c1 100644 --- a/tests/lib/test-utils.ts +++ b/tests/lib/test-utils.ts @@ -1,21 +1,18 @@ -import { resolve } from 'path'; +import tsESLintParser from '@typescript-eslint/parser'; +import { RuleTester, RunTests } from '@typescript-eslint/rule-tester'; -import { TSESLint } from '@typescript-eslint/utils'; - -import { FlatCompatRuleTester } from './FlatCompatRuleTester'; +import { TestingLibraryPluginRuleModule } from '../../lib/utils'; const DEFAULT_TEST_CASE_CONFIG = { filename: 'MyComponent.test.js', }; -class TestingLibraryRuleTester extends FlatCompatRuleTester { - run>( +class TestingLibraryRuleTester extends RuleTester { + run( ruleName: string, - rule: TSESLint.RuleModule, - tests: TSESLint.RunTests + rule: TestingLibraryPluginRuleModule, + { invalid, valid }: RunTests ): void { - const { valid, invalid } = tests; - const finalValid = valid.map((testCase) => { if (typeof testCase === 'string') { return { @@ -35,18 +32,14 @@ class TestingLibraryRuleTester extends FlatCompatRuleTester { } } -export const createRuleTester = ( - parserOptions: Partial = {} -): TSESLint.RuleTester => { - return new TestingLibraryRuleTester({ - parser: resolve('./node_modules/@typescript-eslint/parser'), - parserOptions: { - ecmaVersion: 2018, - sourceType: 'module', - ecmaFeatures: { - jsx: true, +export const createRuleTester = () => + new TestingLibraryRuleTester({ + languageOptions: { + parser: tsESLintParser, + parserOptions: { + ecmaFeatures: { + jsx: true, + }, }, - ...parserOptions, }, }); -}; diff --git a/tools/generate-configs/index.ts b/tools/generate-configs/index.ts index ac439674..db460548 100644 --- a/tools/generate-configs/index.ts +++ b/tools/generate-configs/index.ts @@ -4,24 +4,18 @@ import rules from '../../lib/rules'; import { SUPPORTED_TESTING_FRAMEWORKS, SupportedTestingFramework, + TestingLibraryPluginRuleModule, } from '../../lib/utils'; -import { LinterConfig, writeConfig } from './utils'; +import { writeConfig } from './utils'; const RULE_NAME_PREFIX = 'testing-library/'; const getRecommendedRulesForTestingFramework = ( framework: SupportedTestingFramework ): Record => - Object.entries(rules) - .filter( - ([ - _, - { - meta: { docs }, - }, - ]) => Boolean(docs.recommendedConfig[framework]) - ) + Object.entries>(rules) + .filter(([_, { meta }]) => Boolean(meta.docs.recommendedConfig[framework])) .reduce((allRules, [ruleName, { meta }]) => { const name = `${RULE_NAME_PREFIX}${ruleName}`; const recommendation = meta.docs.recommendedConfig[framework]; @@ -34,7 +28,7 @@ const getRecommendedRulesForTestingFramework = ( (async () => { for (const framework of SUPPORTED_TESTING_FRAMEWORKS) { - const specificFrameworkConfig: LinterConfig = { + const specificFrameworkConfig: TSESLint.Linter.ConfigType = { plugins: ['testing-library'], rules: getRecommendedRulesForTestingFramework(framework), }; diff --git a/tools/generate-configs/utils.ts b/tools/generate-configs/utils.ts index 9e979151..b6f36a39 100644 --- a/tools/generate-configs/utils.ts +++ b/tools/generate-configs/utils.ts @@ -6,8 +6,6 @@ import { format, resolveConfig } from 'prettier'; const prettierConfig = resolveConfig(__dirname); -export type LinterConfig = TSESLint.Linter.Config; - const addAutoGeneratedComment = (code: string) => [ '// THIS CODE WAS AUTOMATICALLY GENERATED', @@ -21,7 +19,7 @@ const addAutoGeneratedComment = (code: string) => * Helper function writes configuration. */ export const writeConfig = async ( - config: LinterConfig, + config: TSESLint.Linter.ConfigType, configName: string ): Promise => { // note: we use `export =` because ESLint will import these configs via a commonjs import