diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 000000000000..8fd30be957db --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,514 @@ +//@ts-check +import babelParser from '@babel/eslint-parser' +import babelPlugin from '@babel/eslint-plugin' +import { FlatCompat } from '@eslint/eslintrc' +import eslintJs from '@eslint/js' +import tsParser from '@typescript-eslint/parser' +import { EslintEnvProcessor } from 'eslint-plugin-eslint-env' +import * as importPlugin from 'eslint-plugin-import' +import jestDomPlugin from 'eslint-plugin-jest-dom' +import jsxA11Y from 'eslint-plugin-jsx-a11y' +import reactPlugin from 'eslint-plugin-react' +import unusedImportsPlugin from 'eslint-plugin-unused-imports' +import globals from 'globals' +import tsEslint from 'typescript-eslint' + +import redwoodjsPlugin from '@redwoodjs/eslint-plugin' +import { findUp } from '@redwoodjs/project-config' +import { buildSharedConfig } from './eslint.config.shared.mjs' + +// Framework Babel config is monorepo root ./babel.config.js +// `yarn lint` runs for each workspace, which needs findUp for path to root +const findBabelConfig = (cwd = process.cwd()) => { + const configPath = findUp('babel.config.js', cwd) + if (!configPath) { + throw new Error(`Eslint-parser could not find a "babel.config.js" file`) + } + return configPath +} + +const compat = new FlatCompat() + +export default tsEslint.config( + { + ignores: [ + '**/node_modules', + '**/dist', + '**/fixtures', + 'packages/babel-config/src/plugins/__tests__/__fixtures__/**/*', + 'packages/babel-config/src/__tests__/__fixtures__/**/*', + 'packages/codemods/**/__testfixtures__/**/*', + 'packages/cli/**/__testfixtures__/**/*', + 'packages/storage/src/__tests__/prisma-client/*', + ], + }, + eslintJs.configs.recommended, + reactPlugin.configs.flat.recommended, + jestDomPlugin.configs['flat/recommended'], + + // TODO: Plugins that are missing flat config support + ...compat.extends('plugin:react-hooks/recommended'), + ...compat.plugins('react-hooks'), + { + plugins: { + 'unused-imports': unusedImportsPlugin, + '@babel': babelPlugin, + import: importPlugin, + 'jsx-a11y': jsxA11Y, + react: reactPlugin, + '@redwoodjs': redwoodjsPlugin, + }, + + // Handle eslint-env comments in flat config + processor: new EslintEnvProcessor(), + + linterOptions: { + // Prevents unused eslint-disable comments + reportUnusedDisableDirectives: true, + }, + + languageOptions: { + globals: { + // We use the most modern environment available. Then we rely on Babel to + // transpile it to something that can run on all node versions we support + ...globals.es2022, + }, + parser: babelParser, + ecmaVersion: 'latest', + sourceType: 'module', + + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + + babelOptions: { + configFile: findBabelConfig(), + }, + }, + }, + + settings: { + react: { + version: 'detect', + }, + // For the import/order rule. Configures how it tells if an import is "internal" or not. + // An "internal" import is basically just one that's aliased. + // + // See... + // - https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md#groups-array + // - https://github.com/import-js/eslint-plugin-import/blob/main/README.md#importinternal-regex + 'import/internal-regex': '^src/', + }, + + rules: { + curly: 'error', + 'unused-imports/no-unused-imports': 'error', + '@redwoodjs/process-env-computed': 'error', + 'no-console': 'off', + 'no-extra-semi': 'off', + 'prefer-object-spread': 'warn', + 'prefer-spread': 'warn', + + 'no-unused-expressions': [ + 'error', + { + allowShortCircuit: true, + allowTernary: true, + }, + ], + + 'no-useless-escape': 'off', + + camelcase: [ + 'warn', + { + properties: 'never', + }, + ], + + 'no-new': 'warn', + + 'new-cap': [ + 'error', + { + newIsCap: true, + capIsNew: false, + }, + ], + + 'no-unused-vars': [ + 'error', + { + varsIgnorePattern: '^_', + argsIgnorePattern: '^_', + }, + ], + + // React rules + 'react/prop-types': 'off', + 'react/display-name': 'off', + 'react-hooks/exhaustive-deps': 'warn', + + 'import/order': [ + 'error', + { + 'newlines-between': 'always', + // We set this to an empty array to override the default value, which is `['builtin', 'external', 'object']`. + // Judging by the number of issues on the repo, this option seems to be notoriously tricky to understand. + // From what I can tell, if the value of this is `['builtin']` that means it won't sort builtins. + // But we have a rule for builtins below (react), so that's not what we want. + // + // See... + // - https://github.com/import-js/eslint-plugin-import/pull/1570 + // - https://github.com/import-js/eslint-plugin-import/issues/1565 + pathGroupsExcludedImportTypes: [], + // Only doing this to add internal. The order here maters. + // See https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md#groups-array + groups: [ + 'builtin', + 'external', + 'internal', + 'parent', + 'sibling', + 'index', + ], + + pathGroups: [ + { + pattern: 'react', + group: 'builtin', + position: 'after', + }, + { + pattern: '@redwoodjs/**', + group: 'external', + position: 'after', + }, + { + // Matches... + // - src/directives/**/*.{js,ts} + // - src/services/**/*.{js,ts} + // - src/graphql/**/*.sdl.{js,ts} + // + // Uses https://github.com/isaacs/minimatch under the hood + // See https://github.com/isaacs/node-glob#glob-primer for syntax + pattern: 'src/*/**/*.?(sdl.){js,ts}', + + patternOptions: { + nobrace: true, + noglobstar: true, + }, + + group: 'internal', + position: 'before', + }, + ], + + alphabetize: { + order: 'asc', + caseInsensitive: true, + }, + }, + ], + }, + }, + // We disable react-hooks/rules-of-hooks for packages which do not deal with React code + { + files: [ + 'packages/api-server/**/*.ts', + 'packages/graphql-server/**/*.ts', + 'packages/realtime/**/*.ts', + ], + + rules: { + 'react-hooks/rules-of-hooks': 'off', + }, + }, + // TypeScript specific linting + { + files: ['**/*.ts', '**/*.mts', '**/*.tsx'], + extends: [ + ...tsEslint.configs.recommendedTypeChecked, + ...tsEslint.configs.stylisticTypeChecked, + ], + languageOptions: { + parser: tsParser, + ecmaVersion: 5, + sourceType: 'script', + + parserOptions: { + project: './tsconfig.eslint.json', + tsconfigRootDir: import.meta.dirname, + }, + }, + + rules: { + // This is disabled for now because of our legacy usage of `require`. It should be enabled in the future. + '@typescript-eslint/no-require-imports': 'off', + // This is disabled for now because of our vast usage of `any`. It should be enabled in the future. + '@typescript-eslint/no-explicit-any': 'off', + + // We allow exceptions to the no-unused-vars rule for variables that start with an underscore + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + varsIgnorePattern: '^_', + argsIgnorePattern: '^_', + }, + ], + + // We want consistent `import type {} from '...'` + '@typescript-eslint/consistent-type-imports': 'error', + + // We want consistent curly brackets + curly: 'error', + + // Stylistic rules we have disabled + '@typescript-eslint/consistent-indexed-object-style': 'off', + '@typescript-eslint/consistent-type-definitions': 'off', + '@typescript-eslint/no-empty-function': 'off', + '@typescript-eslint/prefer-function-type': 'off', + camelcase: 'off', + + // TODO(jgmw): Work through these and either keep disabled or fix and re-enable + '@typescript-eslint/no-unsafe-call': 'off', + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/require-await': 'off', + '@typescript-eslint/prefer-nullish-coalescing': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/dot-notation': 'off', + '@typescript-eslint/no-unsafe-argument': 'off', + '@typescript-eslint/no-unsafe-return': 'off', + '@typescript-eslint/prefer-promise-reject-errors': 'off', + '@typescript-eslint/no-redundant-type-constituents': 'off', + '@typescript-eslint/restrict-plus-operands': 'off', + '@typescript-eslint/no-misused-promises': 'off', + '@typescript-eslint/no-floating-promises': 'off', + '@typescript-eslint/prefer-regexp-exec': 'off', + '@typescript-eslint/restrict-template-expressions': 'off', + '@typescript-eslint/non-nullable-type-assertion-style': 'off', + '@typescript-eslint/no-base-to-string': 'off', + '@typescript-eslint/unbound-method': 'off', + }, + }, + { + files: ['**/*.test.*', '**/__mocks__/**'], + + languageOptions: { + globals: { + ...globals.node, + ...globals.commonjs, + ...globals.jest, + }, + }, + }, + // TODO: Remove legacy + // Set the correct environment js config files + { + files: ['**/.eslintrc.js', '**/.babelrc.js'], + + languageOptions: { + globals: { + ...globals.node, + ...globals.commonjs, + }, + }, + }, + { + files: ['**/eslint.config.mjs'], + + languageOptions: { + globals: { + ...globals.node, + ...globals.es2022, + }, + }, + }, + // Set the correct environment for Jest config files + { + files: ['**/jest.config.js', '**/jest.setup.js'], + + languageOptions: { + globals: { + ...globals.node, + ...globals.commonjs, + ...globals.jest, + }, + }, + }, + // Browser Context + // + // We prevent "window" from being used, and instead require "global". + // This is because prerender runs in the NodeJS context it's undefined. + { + files: [ + 'packages/auth/src/**', + 'packages/forms/src/**', + 'packages/prerender/src/browserUtils/**', + 'packages/router/src/**', + 'packages/web/src/**', + ], + + languageOptions: { + sourceType: 'module', + globals: { + ...globals.browser, + window: 'off', // Developers should use `global` instead of window. Since window is undefined in NodeJS. + }, + }, + }, + // Prevent @redwoodjs/internal imports in runtime (web+api) packages + { + files: [ + 'packages/auth/src/**', + 'packages/forms/src/**', + 'packages/prerender/src/browserUtils/**', + 'packages/router/src/**', + 'packages/web/src/**', + 'packages/api/src/**', + 'packages/graphql-server/src/**', + 'packages/record/src/**', + 'packages/project-config/src/**', + ], + + rules: { + 'no-restricted-imports': [ + 'error', + { + patterns: [ + { + group: ['@redwoodjs/internal', '@redwoodjs/internal/*'], + message: + 'Do not import "@redwoodjs/internal" or subpackages in runtime modules, because it leads to MASSIVE bundle sizes', + }, + { + group: ['@redwoodjs/structure', '@redwoodjs/structure/*'], + message: + 'Do not import "@redwoodjs/structure" or subpackages in runtime modules, because it leads to MASSIVE bundle sizes', + }, + ], + }, + ], + }, + }, + // Entry.js rules + { + files: ['packages/web/src/entry/index.jsx'], + + languageOptions: { + globals: { + ...globals.browser, + React: 'readonly', + }, + }, + }, + // NodeJS Context + { + files: [ + 'packages/api/src/**', + 'packages/api-server/src/**', + 'packages/cli/src/**', + 'packages/create-redwood-app/src/*.js', + 'packages/internal/src/**', + 'packages/prerender/src/**', + 'packages/structure/src/**', + 'packages/testing/src/**', + 'packages/testing/config/**', + 'packages/eslint-config/*.js', + 'packages/record/src/**', + 'packages/telemetry/src/**', + 'packages/vite/bins/**', + ], + + languageOptions: { + globals: { + ...globals.node, + }, + }, + }, + // Prevent bad imports in Node packages - cli and api packages + { + files: [ + 'packages/api/src/**', + 'packages/api-server/src/**', + 'packages/cli/src/**', + 'packages/internal/src/**', + 'packages/prerender/src/**', + 'packages/structure/src/**', + 'packages/testing/src/**', + 'packages/testing/config/**', + 'packages/eslint-config/*.js', + 'packages/record/src/**', + 'packages/telemetry/src/**', + ], + + rules: { + 'no-restricted-imports': [ + // for import x from ('@redwoodjs/internal') + 'error', + { + name: '@redwoodjs/internal', + message: + 'To prevent bloat in CLI, do not import "@redwoodjs/internal" directly. Instead import like @redwoodjs/internal/dist/, or await import', + }, + ], + + 'no-restricted-modules': [ + // for require('@redwoodjs/internal') + 'error', + { + name: '@redwoodjs/internal', + message: + 'To prevent bloat in CLI, do not require "@redwoodjs/internal" directly. Instead require like @redwoodjs/internal/dist/', + }, + ], + }, + }, + // Allow computed member access on process.env in NodeJS contexts and tests + { + files: ['packages/testing/**', 'packages/vite/src/index.ts'], + + rules: { + '@redwoodjs/process-env-computed': 'off', + }, + }, + { + files: ['packages/project-config/**'], + ignores: ['**/__tests__/**', '**/*.test.ts?(x)', '**/*.spec.ts?(x)'], + + rules: { + 'import/no-extraneous-dependencies': [ + 'error', + { + devDependencies: false, + optionalDependencies: false, + peerDependencies: true, + }, + ], + }, + }, + // Migrating projects that are used with "eslintConfig" + ...buildSharedConfig( + '**/__fixtures/*/**/', + 'packages/create-redwood-app/templates/*/**/', + ), + // Issues that appeared while migrating to flat config + // TODO: Fix related issues + { + files: ['**/*.mjs'], + rules: { + 'no-irregular-whitespace': 'off', + }, + }, + { + ignores: ['**/*.template'], + }, + { + rules: { + '@typescript-eslint/await-thenable': 'off', + 'react/react-in-jsx-scope': 'off', + }, + }, +) diff --git a/eslint.config.shared.mjs b/eslint.config.shared.mjs new file mode 100644 index 000000000000..c298ed73f1db --- /dev/null +++ b/eslint.config.shared.mjs @@ -0,0 +1,316 @@ +//@ts-check +import babelParser from '@babel/eslint-parser' +import babelPlugin from '@babel/eslint-plugin' +import { FlatCompat } from '@eslint/eslintrc' +import eslintJs from '@eslint/js' +import * as importPlugin from 'eslint-plugin-import' +import jestDomPlugin from 'eslint-plugin-jest-dom' +import jsxA11Y from 'eslint-plugin-jsx-a11y' +import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended' +import reactPlugin from 'eslint-plugin-react' +import unusedImportsPlugin from 'eslint-plugin-unused-imports' +import globals from 'globals' +import tsEslint from 'typescript-eslint' + +import redwoodjsPlugin from '@redwoodjs/eslint-plugin' + +const compat = new FlatCompat() + +// Migrating packages/eslint-config config to flat config +const sharedConfig = tsEslint.config( + { + ignores: ['**/node_modules', '**/dist'], + }, + eslintJs.configs.recommended, + reactPlugin.configs.flat.recommended, + eslintPluginPrettierRecommended, + jestDomPlugin.configs['flat/recommended'], + + ...compat.plugins('react-hooks'), + { + plugins: { + 'unused-imports': unusedImportsPlugin, + '@babel': babelPlugin, + import: importPlugin, + 'jsx-a11y': jsxA11Y, + react: reactPlugin, + '@redwoodjs': redwoodjsPlugin, + }, + + linterOptions: { + // Prevents unused eslint-disable comments + reportUnusedDisableDirectives: true, + }, + + languageOptions: { + parser: babelParser, + ecmaVersion: 'latest', + sourceType: 'module', + }, + + settings: { + react: { + version: 'detect', + }, + // For the import/order rule. Configures how it tells if an import is "internal" or not. + // An "internal" import is basically just one that's aliased. + // + // See... + // - https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md#groups-array + // - https://github.com/import-js/eslint-plugin-import/blob/main/README.md#importinternal-regex + 'import/internal-regex': '^src/', + }, + + rules: { + '@redwoodjs/process-env-computed': 'error', + 'prettier/prettier': 'warn', + 'no-console': 'off', + 'prefer-object-spread': 'warn', + 'prefer-spread': 'warn', + 'no-unused-expressions': [ + 'error', + { allowShortCircuit: true, allowTernary: true }, + ], + 'no-useless-escape': 'off', + camelcase: ['warn', { properties: 'never' }], + 'no-new': 'warn', + 'new-cap': ['error', { newIsCap: true, capIsNew: false }], + 'no-unused-vars': [ + 'error', + { varsIgnorePattern: '^_', argsIgnorePattern: '^_' }, + ], + // React rules + 'react/prop-types': 'off', + 'react/display-name': 'off', + 'react-hooks/exhaustive-deps': 'warn', + 'import/order': [ + 'error', + { + 'newlines-between': 'always', + // We set this to an empty array to override the default value, which is `['builtin', 'external', 'object']`. + // Judging by the number of issues on the repo, this option seems to be notoriously tricky to understand. + // From what I can tell, if the value of this is `['builtin']` that means it won't sort builtins. + // But we have a rule for builtins below (react), so that's not what we want. + // + // See... + // - https://github.com/import-js/eslint-plugin-import/pull/1570 + // - https://github.com/import-js/eslint-plugin-import/issues/1565 + pathGroupsExcludedImportTypes: [], + // Only doing this to add internal. The order here maters. + // See https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md#groups-array + groups: [ + 'builtin', + 'external', + 'internal', + 'parent', + 'sibling', + 'index', + ], + pathGroups: [ + { + pattern: 'react', + group: 'builtin', + position: 'after', + }, + { + pattern: '@redwoodjs/**', + group: 'external', + position: 'after', + }, + { + // Matches... + // - src/directives/**/*.{js,ts} + // - src/services/**/*.{js,ts} + // - src/graphql/**/*.sdl.{js,ts} + // + // Uses https://github.com/isaacs/minimatch under the hood + // See https://github.com/isaacs/node-glob#glob-primer for syntax + pattern: 'src/*/**/*.?(sdl.){js,ts}', + patternOptions: { + nobrace: true, + noglobstar: true, + }, + group: 'internal', + position: 'before', + }, + ], + alphabetize: { + order: 'asc', + caseInsensitive: true, + }, + }, + ], + 'no-restricted-imports': [ + 'error', + { + patterns: [ + { + group: ['$api/*'], + message: + 'Importing from $api is only supported in *.routeHooks.{js,ts} files', + }, + ], + }, + ], + }, + }, + { + files: ['*.tsx', '*.js', '*.jsx'], + ignores: ['api/src/**'], + rules: { + 'react-hooks/rules-of-hooks': 'error', + }, + }, + { + files: ['*.ts', '*.tsx'], + extends: [...tsEslint.configs.recommended, eslintPluginPrettierRecommended], + languageOptions: { + parser: tsEslint.parser, + }, + rules: { + // TODO: look into enabling these eventually + '@typescript-eslint/no-empty-function': 'off', + '@typescript-eslint/prefer-function-type': 'off', + + // Specific 'recommended' rules we alter + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-require-imports': 'off', + '@typescript-eslint/no-empty-object-type': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { varsIgnorePattern: '^_', argsIgnorePattern: '^_' }, + ], + }, + }, + { + files: ['**/*.test.*', '**/__mocks__/**'], + + languageOptions: { + globals: { + ...globals.node, + ...globals.commonjs, + ...globals.jest, + }, + }, + }, + { + files: [ + '.babelrc.js', + 'babel.config.js', + '.eslintrc.js', + '*.config.js', + 'jest.setup.js', + ], + + languageOptions: { + globals: { + ...globals.node, + ...globals.commonjs, + ...globals.jest, + }, + }, + }, + { + files: [ + 'web/src/**/*.routeHooks.{js,ts}', + 'web/src/entry.server.{jsx,tsx}', + ], + rules: { 'no-restricted-imports': 'off' }, + }, + // Migrating packages/eslint-config/index.js to flat config + { + files: ['web/src/Routes.js', 'web/src/Routes.jsx', 'web/src/Routes.tsx'], + rules: { + 'no-undef': 'off', + 'jsx-a11y/aria-role': [ + 2, + { + ignoreNonDOM: true, + }, + ], + '@redwoodjs/unsupported-route-components': 'error', + }, + }, + // `api` side + { + files: ['api/src/**'], + languageOptions: { + globals: { + ...globals.node, + ...globals.es2015, + gql: 'readonly', + context: 'readonly', + }, + }, + }, + { + files: ['api/src/services/**/*.ts'], + plugins: { + '@redwoodjs': redwoodjsPlugin, + }, + rules: { + '@redwoodjs/service-type-annotations': 'off', + }, + }, + { + files: ['api/db/seed.js', 'scripts/**'], + languageOptions: { + globals: { + ...globals.node, + ...globals.commonjs, + Promise: 'readonly', + }, + }, + }, + // `web` side + { + files: ['web/src/**'], + languageOptions: { + globals: { + ...globals.browser, + ...globals.es2015, + ...globals['shared-node-browser'], + React: 'readonly', + gql: 'readonly', + process: 'readonly', + require: 'readonly', + }, + }, + }, + // Test, stories, scenarios, and mock files + { + files: [ + '*.test.*', + '**/__mocks__/**', + '*.scenarios.*', + '*.stories.*', + '*.mock.*', + ], + languageOptions: { + globals: { + mockGraphQLQuery: 'readonly', + mockGraphQLMutation: 'readonly', + mockCurrentUser: 'readonly', + scenario: 'readonly', + defineScenario: 'readonly', + }, + }, + }, +) + +export const buildSharedConfig = (...paths) => { + return sharedConfig.map((config) => { + if (config.files) { + config.files = paths.flatMap((path) => config.files?.map((f) => path + f)) + } else if (!config.ignores) { + config.files = paths.map((path) => path + '**/*') + } + + if (config.ignores) { + config.ignores = paths.flatMap( + (path) => config.ignores?.map((f) => path + f) || [], + ) + } + return config + }) +} diff --git a/package.json b/package.json index a6f4155dcf7f..fe417e472b92 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "lint": "concurrently -c auto npm:lint:fw npm:lint:crwrsca", "lint:crwrsca": "yarn --cwd packages/create-redwood-rsc-app run lint", "lint:fix": "yarn lint --fix", - "lint:fw": "cross-env RWJS_CWD=packages/create-redwood-app/templates/ts eslint --config .eslintrc.js --ignore-pattern Routes.jsx --ignore-pattern create-redwood-rsc-app packages", + "lint:fw": "cross-env RWJS_CWD=packages/create-redwood-app/templates/ts ESLINT_USE_FLAT_CONFIG=true eslint --config eslint.config.mjs --ignore-pattern Routes.jsx --ignore-pattern **/create-redwood-rsc-app/ packages", "project:copy": "node ./tasks/framework-tools/frameworkFilesToProject.mjs", "project:deps": "node ./tasks/framework-tools/frameworkDepsToProject.mjs", "project:sync": "node ./tasks/framework-tools/frameworkSyncToProject.mjs", @@ -61,6 +61,8 @@ "@actions/glob": "0.5.0", "@babel/cli": "7.25.6", "@babel/core": "^7.22.20", + "@babel/eslint-parser": "^7.25.7", + "@babel/eslint-plugin": "^7.25.7", "@babel/generator": "7.25.6", "@babel/node": "7.25.0", "@babel/plugin-proposal-decorators": "7.24.7", @@ -74,6 +76,7 @@ "@babel/preset-react": "^7.22.15", "@babel/preset-typescript": "^7.22.15", "@babel/runtime-corejs3": "7.25.6", + "@eslint/compat": "^1.2.0", "@faker-js/faker": "8.4.1", "@npmcli/arborist": "7.5.4", "@playwright/test": "1.47.2", @@ -81,13 +84,14 @@ "@testing-library/react": "14.3.1", "@testing-library/user-event": "14.5.2", "@types/babel__generator": "7.6.8", + "@types/eslint-plugin-jsx-a11y": "^6", "@types/fs-extra": "11.0.4", "@types/jest": "29.5.13", "@types/jscodeshift": "0.11.11", "@types/ncp": "2.0.8", "@types/prompts": "2.4.9", - "@typescript-eslint/eslint-plugin": "8.5.0", - "@typescript-eslint/parser": "8.5.0", + "@typescript-eslint/eslint-plugin": "8.8.0", + "@typescript-eslint/parser": "8.8.0", "@yarnpkg/types": "4.0.0", "all-contributors-cli": "6.26.1", "babel-jest": "^29.7.0", @@ -103,12 +107,18 @@ "dependency-cruiser": "16.4.2", "dotenv": "16.4.5", "eslint": "8.57.1", + "eslint-plugin-eslint-env": "^0.5.0", + "eslint-plugin-import": "2.30.0", + "eslint-plugin-jest-dom": "5.4.0", + "eslint-plugin-jsx-a11y": "6.10.0", + "eslint-plugin-prettier": "5.2.1", "eslint-plugin-react": "7.36.1", "eslint-plugin-react-hooks": "4.6.0", "eslint-plugin-unused-imports": "3.2.0", "execa": "5.1.1", "fast-glob": "3.3.2", "fs-extra": "11.2.0", + "globals": "^15.10.0", "human-id": "^4.1.1", "jest": "29.7.0", "jscodeshift": "17.0.0", @@ -130,6 +140,7 @@ "tstyche": "2.1.1", "tsx": "4.19.1", "typescript": "5.6.2", + "typescript-eslint": "^8.8.0", "vitest": "2.0.5", "yargs": "17.7.2", "zx": "8.1.8" diff --git a/yarn.lock b/yarn.lock index 045268f1110d..4d371c6a6ee8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -512,6 +512,20 @@ __metadata: languageName: node linkType: hard +"@babel/eslint-parser@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/eslint-parser@npm:7.25.7" + dependencies: + "@nicolo-ribaudo/eslint-scope-5-internals": "npm:5.1.1-v1" + eslint-visitor-keys: "npm:^2.1.0" + semver: "npm:^6.3.1" + peerDependencies: + "@babel/core": ^7.11.0 + eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 + checksum: 10c0/7609eda37e727b0ea70fc9f6175f13adf6d912d18f52430dd3acb88c403173a5b403a8f5a31158253b03fa2a4d7347475cc0d41cc3e9628386bd9cc12a139591 + languageName: node + linkType: hard + "@babel/eslint-plugin@npm:7.25.1": version: 7.25.1 resolution: "@babel/eslint-plugin@npm:7.25.1" @@ -524,6 +538,18 @@ __metadata: languageName: node linkType: hard +"@babel/eslint-plugin@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/eslint-plugin@npm:7.25.7" + dependencies: + eslint-rule-composer: "npm:^0.3.0" + peerDependencies: + "@babel/eslint-parser": ^7.11.0 + eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 + checksum: 10c0/dada6831e9c1b8c5933cf6cd551b7d626298bb6829c52e4dbc20d0ac6d63553fbdbe18541d162d0f62ab2121a8159ec361b9c82c95ca5ad672cd08439a95cd47 + languageName: node + linkType: hard + "@babel/generator@npm:7.25.6, @babel/generator@npm:^7.14.0, @babel/generator@npm:^7.18.13, @babel/generator@npm:^7.23.0, @babel/generator@npm:^7.23.6, @babel/generator@npm:^7.25.0, @babel/generator@npm:^7.25.6, @babel/generator@npm:^7.7.2": version: 7.25.6 resolution: "@babel/generator@npm:7.25.6" @@ -3237,6 +3263,18 @@ __metadata: languageName: node linkType: hard +"@eslint/compat@npm:^1.2.0": + version: 1.2.0 + resolution: "@eslint/compat@npm:1.2.0" + peerDependencies: + eslint: ^9.10.0 + peerDependenciesMeta: + eslint: + optional: true + checksum: 10c0/ad79bf1ef14462f829288c4e2ca8eeffdf576fa923d3f8a07e752e821bdbe5fd79360fe6254e9ddfe7eada2e4e3d22a7ee09f5d21763e67bc4fbc331efb3c3e9 + languageName: node + linkType: hard + "@eslint/eslintrc@npm:^2.1.4": version: 2.1.4 resolution: "@eslint/eslintrc@npm:2.1.4" @@ -10861,6 +10899,25 @@ __metadata: languageName: node linkType: hard +"@types/eslint-plugin-jsx-a11y@npm:^6": + version: 6.9.0 + resolution: "@types/eslint-plugin-jsx-a11y@npm:6.9.0" + dependencies: + "@types/eslint": "npm:*" + checksum: 10c0/50e5f9a70e50218abae57cf9b8dc60a55e3fe1721a5912f96b26c6030b8c198694342d897a5425691601b27506589558f6ebcc93b80f602d5851936e95c8d84c + languageName: node + linkType: hard + +"@types/eslint@npm:*": + version: 9.6.1 + resolution: "@types/eslint@npm:9.6.1" + dependencies: + "@types/estree": "npm:*" + "@types/json-schema": "npm:*" + checksum: 10c0/69ba24fee600d1e4c5abe0df086c1a4d798abf13792d8cfab912d76817fe1a894359a1518557d21237fbaf6eda93c5ab9309143dee4c59ef54336d1b3570420e + languageName: node + linkType: hard + "@types/eslint@npm:8.56.12": version: 8.56.12 resolution: "@types/eslint@npm:8.56.12" @@ -11595,6 +11652,29 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/eslint-plugin@npm:8.8.0": + version: 8.8.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.8.0" + dependencies: + "@eslint-community/regexpp": "npm:^4.10.0" + "@typescript-eslint/scope-manager": "npm:8.8.0" + "@typescript-eslint/type-utils": "npm:8.8.0" + "@typescript-eslint/utils": "npm:8.8.0" + "@typescript-eslint/visitor-keys": "npm:8.8.0" + graphemer: "npm:^1.4.0" + ignore: "npm:^5.3.1" + natural-compare: "npm:^1.4.0" + ts-api-utils: "npm:^1.3.0" + peerDependencies: + "@typescript-eslint/parser": ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/98ac37587eda02a713710f0a62ca979833482024968f1d1735881718abe102a6b49707db4f1dac0d7c731d1cbf8111d829c5125348d4829ab6fad7a7b3b344e4 + languageName: node + linkType: hard + "@typescript-eslint/parser@npm:8.5.0": version: 8.5.0 resolution: "@typescript-eslint/parser@npm:8.5.0" @@ -11613,6 +11693,24 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/parser@npm:8.8.0": + version: 8.8.0 + resolution: "@typescript-eslint/parser@npm:8.8.0" + dependencies: + "@typescript-eslint/scope-manager": "npm:8.8.0" + "@typescript-eslint/types": "npm:8.8.0" + "@typescript-eslint/typescript-estree": "npm:8.8.0" + "@typescript-eslint/visitor-keys": "npm:8.8.0" + debug: "npm:^4.3.4" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/cf72a644b89c62cd55b09fa1d22b51a2c726714aac344a797f0c2ad80bfbabcb7567000fadd4ea8188aa1d923675bebdca06acc1d28ac1b8360bf28a36b46f3a + languageName: node + linkType: hard + "@typescript-eslint/rule-tester@npm:8.5.0": version: 8.5.0 resolution: "@typescript-eslint/rule-tester@npm:8.5.0" @@ -11639,6 +11737,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/scope-manager@npm:8.8.0": + version: 8.8.0 + resolution: "@typescript-eslint/scope-manager@npm:8.8.0" + dependencies: + "@typescript-eslint/types": "npm:8.8.0" + "@typescript-eslint/visitor-keys": "npm:8.8.0" + checksum: 10c0/29ddf589ff0e465dbbf3eb87b79a29face4ec5a6cb617bbaafbac6ae8340d376b5b405bca762ee1c7a40cbdf7912a32734f9119f6864df048c7a0b2de21bdd3d + languageName: node + linkType: hard + "@typescript-eslint/type-utils@npm:8.5.0": version: 8.5.0 resolution: "@typescript-eslint/type-utils@npm:8.5.0" @@ -11654,6 +11762,21 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/type-utils@npm:8.8.0": + version: 8.8.0 + resolution: "@typescript-eslint/type-utils@npm:8.8.0" + dependencies: + "@typescript-eslint/typescript-estree": "npm:8.8.0" + "@typescript-eslint/utils": "npm:8.8.0" + debug: "npm:^4.3.4" + ts-api-utils: "npm:^1.3.0" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/d6ee11f4686fb54daea1f436f73b96eb31a95f6e535abc0534abf5794e7597669a92d12300969c8afee0fc1912dbc1591664f7e37f0da5935016cc981b2921a8 + languageName: node + linkType: hard + "@typescript-eslint/types@npm:8.5.0": version: 8.5.0 resolution: "@typescript-eslint/types@npm:8.5.0" @@ -11661,6 +11784,13 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/types@npm:8.8.0": + version: 8.8.0 + resolution: "@typescript-eslint/types@npm:8.8.0" + checksum: 10c0/cd168fafcaf77641b023c4405ea3a8c30fbad1737abb5aec9fce67fe2ae20224b624b5a2e3e84900ba81dc7dd33343add3653763703a225326cc81356b182d09 + languageName: node + linkType: hard + "@typescript-eslint/typescript-estree@npm:8.5.0": version: 8.5.0 resolution: "@typescript-eslint/typescript-estree@npm:8.5.0" @@ -11680,6 +11810,25 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/typescript-estree@npm:8.8.0": + version: 8.8.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.8.0" + dependencies: + "@typescript-eslint/types": "npm:8.8.0" + "@typescript-eslint/visitor-keys": "npm:8.8.0" + debug: "npm:^4.3.4" + fast-glob: "npm:^3.3.2" + is-glob: "npm:^4.0.3" + minimatch: "npm:^9.0.4" + semver: "npm:^7.6.0" + ts-api-utils: "npm:^1.3.0" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/9b9e849f6b2d4e250840ef8e05f55a97d6598adaf48c1e6df83084b94c30feca6a3e7916ee1c235178188d0db6364a877cbf8fe218c36d5f8d5acb50767f3273 + languageName: node + linkType: hard + "@typescript-eslint/utils@npm:8.5.0": version: 8.5.0 resolution: "@typescript-eslint/utils@npm:8.5.0" @@ -11694,6 +11843,20 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/utils@npm:8.8.0": + version: 8.8.0 + resolution: "@typescript-eslint/utils@npm:8.8.0" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.4.0" + "@typescript-eslint/scope-manager": "npm:8.8.0" + "@typescript-eslint/types": "npm:8.8.0" + "@typescript-eslint/typescript-estree": "npm:8.8.0" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + checksum: 10c0/fcf2dfd4a2d9491aa096a29c2c1fdd891ca3c13933d20cfea44e51b3d10a397e7ed9a9cd71ac9a29e8c4706264ae00c25a29394e2a6bda3291be298062901f2c + languageName: node + linkType: hard + "@typescript-eslint/visitor-keys@npm:8.5.0": version: 8.5.0 resolution: "@typescript-eslint/visitor-keys@npm:8.5.0" @@ -11704,6 +11867,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/visitor-keys@npm:8.8.0": + version: 8.8.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.8.0" + dependencies: + "@typescript-eslint/types": "npm:8.8.0" + eslint-visitor-keys: "npm:^3.4.3" + checksum: 10c0/580ce74c9b09b9e6a6f3f0ac2d2f0c6a6b983a78ce3b2544822ee08107c57142858d674897f61ff32a9a5e8fca00c916545c159bb75d134f4380884642542d38 + languageName: node + linkType: hard + "@ungap/structured-clone@npm:^1.2.0": version: 1.2.0 resolution: "@ungap/structured-clone@npm:1.2.0" @@ -16840,6 +17013,16 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-eslint-env@npm:^0.5.0": + version: 0.5.0 + resolution: "eslint-plugin-eslint-env@npm:0.5.0" + peerDependencies: + "@types/eslint": ">=8" + eslint: ">=8.21" + checksum: 10c0/686f616f5b06384ccfc47df66a3b56c0ddc755fc4bfa9dc7635cc4cf19652f8ac508178fa866b8a5d338c6bfb3f0c61131894bd37626fe61c5f137b2660d9e57 + languageName: node + linkType: hard + "eslint-plugin-import@npm:2.30.0": version: 2.30.0 resolution: "eslint-plugin-import@npm:2.30.0" @@ -16881,6 +17064,22 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-jest-dom@npm:5.4.0": + version: 5.4.0 + resolution: "eslint-plugin-jest-dom@npm:5.4.0" + dependencies: + "@babel/runtime": "npm:^7.16.3" + requireindex: "npm:^1.2.0" + peerDependencies: + "@testing-library/dom": ^8.0.0 || ^9.0.0 || ^10.0.0 + eslint: ^6.8.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 + peerDependenciesMeta: + "@testing-library/dom": + optional: true + checksum: 10c0/7a3cab6bae787345f1e485a2b767068121ce5084276d67ab2132411792c63f1303cdebfb9fad8c755baaabaa10e0511e606a4175a56fe8fd199062807b2cda10 + languageName: node + linkType: hard + "eslint-plugin-jsx-a11y@npm:6.10.0": version: 6.10.0 resolution: "eslint-plugin-jsx-a11y@npm:6.10.0" @@ -18625,6 +18824,13 @@ __metadata: languageName: node linkType: hard +"globals@npm:^15.10.0": + version: 15.10.0 + resolution: "globals@npm:15.10.0" + checksum: 10c0/fef8f320e88f01f1492fef1b04b056908e1f6726eeaffe3bca03247237300c2d86e71585ee641b62ba71460a6eaff0d6ca7fca284e61bd1b3f833c7ad68b160a + languageName: node + linkType: hard + "globalthis@npm:^1.0.3": version: 1.0.3 resolution: "globalthis@npm:1.0.3" @@ -26909,6 +27115,8 @@ __metadata: "@actions/glob": "npm:0.5.0" "@babel/cli": "npm:7.25.6" "@babel/core": "npm:^7.22.20" + "@babel/eslint-parser": "npm:^7.25.7" + "@babel/eslint-plugin": "npm:^7.25.7" "@babel/generator": "npm:7.25.6" "@babel/node": "npm:7.25.0" "@babel/plugin-proposal-decorators": "npm:7.24.7" @@ -26922,6 +27130,7 @@ __metadata: "@babel/preset-react": "npm:^7.22.15" "@babel/preset-typescript": "npm:^7.22.15" "@babel/runtime-corejs3": "npm:7.25.6" + "@eslint/compat": "npm:^1.2.0" "@faker-js/faker": "npm:8.4.1" "@npmcli/arborist": "npm:7.5.4" "@playwright/test": "npm:1.47.2" @@ -26929,13 +27138,14 @@ __metadata: "@testing-library/react": "npm:14.3.1" "@testing-library/user-event": "npm:14.5.2" "@types/babel__generator": "npm:7.6.8" + "@types/eslint-plugin-jsx-a11y": "npm:^6" "@types/fs-extra": "npm:11.0.4" "@types/jest": "npm:29.5.13" "@types/jscodeshift": "npm:0.11.11" "@types/ncp": "npm:2.0.8" "@types/prompts": "npm:2.4.9" - "@typescript-eslint/eslint-plugin": "npm:8.5.0" - "@typescript-eslint/parser": "npm:8.5.0" + "@typescript-eslint/eslint-plugin": "npm:8.8.0" + "@typescript-eslint/parser": "npm:8.8.0" "@yarnpkg/types": "npm:4.0.0" all-contributors-cli: "npm:6.26.1" babel-jest: "npm:^29.7.0" @@ -26951,12 +27161,18 @@ __metadata: dependency-cruiser: "npm:16.4.2" dotenv: "npm:16.4.5" eslint: "npm:8.57.1" + eslint-plugin-eslint-env: "npm:^0.5.0" + eslint-plugin-import: "npm:2.30.0" + eslint-plugin-jest-dom: "npm:5.4.0" + eslint-plugin-jsx-a11y: "npm:6.10.0" + eslint-plugin-prettier: "npm:5.2.1" eslint-plugin-react: "npm:7.36.1" eslint-plugin-react-hooks: "npm:4.6.0" eslint-plugin-unused-imports: "npm:3.2.0" execa: "npm:5.1.1" fast-glob: "npm:3.3.2" fs-extra: "npm:11.2.0" + globals: "npm:^15.10.0" human-id: "npm:^4.1.1" jest: "npm:29.7.0" jscodeshift: "npm:17.0.0" @@ -26978,6 +27194,7 @@ __metadata: tstyche: "npm:2.1.1" tsx: "npm:4.19.1" typescript: "npm:5.6.2" + typescript-eslint: "npm:^8.8.0" vitest: "npm:2.0.5" yargs: "npm:17.7.2" zx: "npm:8.1.8" @@ -29252,6 +29469,20 @@ __metadata: languageName: node linkType: hard +"typescript-eslint@npm:^8.8.0": + version: 8.8.0 + resolution: "typescript-eslint@npm:8.8.0" + dependencies: + "@typescript-eslint/eslint-plugin": "npm:8.8.0" + "@typescript-eslint/parser": "npm:8.8.0" + "@typescript-eslint/utils": "npm:8.8.0" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/545f0ce051282921aff56288baf288cffe6f7bafee5149f1b87af2c67f81f8c2088924a2e0fc0f0dcd12692b6a97eca10149a619c8c85d4aaef2fe763938da8d + languageName: node + linkType: hard + "typescript@npm:5.6.1-rc": version: 5.6.1-rc resolution: "typescript@npm:5.6.1-rc"