diff --git a/.changeset/happy-sloths-smile.md b/.changeset/happy-sloths-smile.md new file mode 100644 index 0000000..5c517c1 --- /dev/null +++ b/.changeset/happy-sloths-smile.md @@ -0,0 +1,5 @@ +--- +"@qlik/eslint-config": major +--- + +feat!: switch to eslint 9 flat config diff --git a/.gitignore b/.gitignore index 849425f..9e3ec10 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. +.eslintcache + # dependencies node_modules .pnp @@ -8,10 +10,8 @@ node_modules # testing coverage -# next.js -.next/ -out/ -build +# build output +lib # misc .DS_Store diff --git a/package.json b/package.json index 5146b54..e2283b6 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ }, "prettier": "@qlik/prettier-config", "devDependencies": { - "@changesets/cli": "2.27.8", + "@changesets/cli": "2.27.9", "@qlik/prettier-config": "workspace:*", "prettier": "3.3.3", "turbo": "2.1.3" diff --git a/packages/eslint-config/README.md b/packages/eslint-config/README.md index 5159d95..42911f0 100644 --- a/packages/eslint-config/README.md +++ b/packages/eslint-config/README.md @@ -1,110 +1,167 @@ + # @qlik/eslint-config -Qlik's ESlint config for pure javascript/typescript environments. Based on airbnb-base/prettier config with some modifications. +Qlik's ESlint config for JavaScript/TypeScript environments with optional framework support. -## usage +## Migrating from 0.x -These configs assumes that you are using typescript. It is still possible to write .js files and get linting on those. +1. Install latest `@qlik/eslint-config` +2. Update to ESLint 9 +3. Rename your config to `eslint.config.js` (if you have `"type": "module"` in your package json) / `eslint.config.mjs` (if otherwise) -Simplest approach is to add one of the following field in `package.json`: +example config that uses typescript, react, vitest, react-query plugin: -For a pure environment with no specific frameworks use: +```js +// @ts-check +import qlik from "@qlik/eslint-config"; +import pluginQuery from "@tanstack/eslint-plugin-query"; -```json -"eslintConfig": { - "root": true, - "parserOptions": { - "project": "path/to/tsconfig.json" +export default qlik.compose( + ...qlik.configs.react, + ...qlik.configs.vitest, + ...pluginQuery.configs["flat/recommended"], + { + rules: { + // Override rules if needed + }, }, - "extends": [ - "@qlik/eslint-config" - ] -}, + // In its own object so it's global + { + ignores: ["dist", "node_modules", "script"], + }, +); ``` -Using react: +4. If you are not using typescript to build your project, then include all files `"include": [".*", "**/*"]` in the project's `tsconfig.json` +5. Run your `lint` script -```json -"eslintConfig": { - "root": true, - "parserOptions": { - "project": "path/to/tsconfig.json" - }, - "extends": [ - "@qlik/eslint-config/react" - ] -}, +### v1 notable changes + +- Updates [`@typescript-eslint/typescript-eslint`](https://github.com/typescript-eslint/typescript-eslint) to v8, this brings a few new rules. See article for v8 +- Moves from [`eslint-plugin-import`](https://github.com/import-js/eslint-plugin-import) to [`eslint-plugin-import-x`](https://github.com/un-ts/eslint-plugin-import-x). If you reference any of the `import/` rules you'll need to replace `import/` with `import-x/`. +- Some stylistic rules have been disabled (for example `function` vs arrow functions) + +## Usage + +These configs works on both TypeScript and JavaSript out of the box. (as long as the file endings are any of `.js, .jsx, .mjs, .cjs, .ts, .tsx, .cts, .mts`) + +To get started, create `eslint.config.js` (if your package json has `"type": "module"`), otherwise create `eslint.config.mjs`. +If you are not building your project with TypeScript (using Webpack or Vite for example), then tell TypeScript to include +all files by setting `"include": [".*", "**/*"]` in `tsconfig.json`. + +For a pure browser environment with no specific frameworks use: + +```js +// @ts-check +import qlik from "@qlik/eslint-config"; + +export default qlik.compose( + ...qlik.configs.recommended, // adds linting on .js, .jsx, .mjs, .cjs, .ts, .tsx, .cts, .mts files. use for pure browser environment + { + ignores: ["dist", "npm", "node_modules"], + } +); ``` -Using svelte: +Using React with vitest: -```json -"eslintConfig": { - "root": true, - "parserOptions": { - "project": "path/to/tsconfig.json" +```js +// @ts-check +import qlik from "@qlik/eslint-config"; + +export default qlik.compose( + ...qlik.configs.react, // based on the recommended config and adds react linting on .jsx and .tsx files + { + ignores: ["dist", "node_modules"], }, - "extends": [ - "@qlik/eslint-config/svelte" - ] -}, +); ``` -Using react AND svelte (rare occasion): +Using Svelte: -```json -"eslintConfig": { - "root": true, - "parserOptions": { - "project": "path/to/tsconfig.json" - }, - "extends": [ - "@qlik/eslint-config/react-svelte" - ] -}, +```js +// @ts-check +import qlik from "@qlik/eslint-config"; + +export default qlik.compose( + ...qlik.configs.svelte, // based on the recommended config and adds svelte linting on .svelte files + { + ignores: ["dist", "node_modules"], + } +); ``` -For a node environment with commonjs modules use: +Using React and Svelte: -```json -"eslintConfig": { - "root": true, - "parserOptions": { - "project": "path/to/tsconfig.json" - }, - "extends": [ - "@qlik/eslint-config/node" - ] -}, +```js +// @ts-check +import qlik from "@qlik/eslint-config"; + +export default qlik.compose( + ...qlik.configs.react, + ...qlik.configs.svelte, + { + ignores: ["dist", "node_modules"], + } +); ``` -For a node environment with ES modules use: +Node environment: -```json -"eslintConfig": { - "root": true, - "parserOptions": { - "project": "path/to/tsconfig.json" +```js +// @ts-check +import qlik from "@qlik/eslint-config"; + +export default qlik.compose( + ...qlik.configs.esm, // or qlik.configs.cjs for commonjs, recommended config with node environment enabled + { + ignores: ["dist", "npm", "node_modules"], }, - "extends": [ - "@qlik/eslint-config/esm" - ] -}, +); ``` -Additional configs that can be used in conjunction with the above: +Additional configs that can be used in conjunction with the ones above: + +```js +// @ts-check +import qlik from "@qlik/eslint-config"; -```json -"eslintConfig": { - "root": true, - "parserOptions": { - "project": "path/to/tsconfig.json" +export default qlik.compose( + ...qlik.configs.recommended, // pure browser environment + ...qlik.configs.vitest, // enable vitest linting on files inside __test(s)__ folder + ...qlik.configs.jest, // enable jest linting on files inside __test(s)__ folder, DON'T use together with vitest + ...qlik.configs.playwright, // enable playwright linting on files inside ./test(s) folder. + { + ignores: ["dist", "npm", "node_modules"], }, - "extends": [ - "...", - "@qlik/eslint-config/vitest", // adds linting on vitest test and config files - // AND/OR - "@qlik/eslint-config/playwright" // adds linting on playwright test and config files - ] -}, +); ``` + +A config can be extended if needed. For example if the default file patterns needs to be altered. + +```js +// @ts-check +import qlik from "@qlik/eslint-config"; + +export default qlik.compose( + ...qlik.configs.recommended, // pure browser environment, no framework config added + { + // adds vitest lint rules on the specified files with an altered rule + files: ['**/my_tests_are_here/*.spec.ts'] + extends [qlik.configs.vitest], + rules: { + "vitest/max-nested-describe": [ + "error", + { + "max": 3 + } + ] + } + }, + { + ignores: ["dist", "npm", "node_modules"], + }, +); +``` + + diff --git a/packages/eslint-config/configs/airbnb-base-mod.js b/packages/eslint-config/configs/airbnb-base-mod.js deleted file mode 100644 index 9960f8f..0000000 --- a/packages/eslint-config/configs/airbnb-base-mod.js +++ /dev/null @@ -1,77 +0,0 @@ -module.exports = { - rules: { - // modifies airbnb default rules - "no-void": "off", - "no-underscore-dangle": "off", - "class-methods-use-this": "off", - "no-plusplus": "off", - "prefer-destructuring": "off", - "guard-for-in": "off", - // allow prev to be re-assigned in reducers - "no-param-reassign": [ - "error", - { - props: true, - ignorePropertyModificationsFor: [ - "prev", // for reduce accumulators - "acc", // for reduce accumulators - "accumulator", // for reduce accumulators - "e", // for e.returnvalue - "ctx", // for Koa routing - "context", // for Koa routing - "req", // for Express requests - "request", // for Express requests - "res", // for Express responses - "response", // for Express responses - "$scope", // for Angular 1 scopes - "staticContext", // for ReactRouter context - ], - }, - ], - - // eslint import/order and prettier-plugin-organize-imports are currently incompatible - "import/order": "off", - - // allows for..in and for..of - "no-restricted-syntax": [ - "error", - // { - // selector: "ForInStatement", - // message: - // "for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.", - // }, - // { - // selector: "ForOfStatement", - // message: - // "iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations.", - // }, - { - selector: "LabeledStatement", - message: "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.", - }, - { - selector: "WithStatement", - message: "`with` is disallowed in strict mode because it makes code impossible to predict and optimize.", - }, - ], - - // modifies airbnb ts default rules - "lines-between-class-members": "off", - "no-use-before-define": "off", - "dot-notation": "off", - - // import plugin - "import/prefer-default-export": "off", - "import/no-extraneous-dependencies": [ - "off", - { - devDependencies: [ - "**/webpack.config.js", - "**/svelte.config.js", - "**/playwright.config.ts", - "**/playwright.config.js", - ], - }, - ], - }, -}; diff --git a/packages/eslint-config/configs/airbnb-mod.js b/packages/eslint-config/configs/airbnb-mod.js deleted file mode 100644 index cdfa414..0000000 --- a/packages/eslint-config/configs/airbnb-mod.js +++ /dev/null @@ -1,17 +0,0 @@ -module.exports = { - extends: ["./airbnb-base-mod.js"], - rules: { - // modifies airbnb rules for react - "react/jsx-props-no-spreading": "off", - "react/jsx-uses-react": "off", - "react/react-in-jsx-scope": "off", - "react/forbid-prop-types": "off", - "react/function-component-definition": [ - 2, - { - namedComponents: "arrow-function", - unnamedComponents: "arrow-function", - }, - ], - }, -}; diff --git a/packages/eslint-config/configs/airbnb-ts-base-mod.js b/packages/eslint-config/configs/airbnb-ts-base-mod.js deleted file mode 100644 index 2d49388..0000000 --- a/packages/eslint-config/configs/airbnb-ts-base-mod.js +++ /dev/null @@ -1,37 +0,0 @@ -module.exports = { - extends: ["./airbnb-base-mod"], - rules: { - // modifies airbnb ts default rules - "lines-between-class-members": "off", - "@typescript-eslint/lines-between-class-members": "off", - - // discouraged https://palantir.github.io/tslint/rules/no-use-before-declare/ - "no-use-before-define": "off", - "@typescript-eslint/no-use-before-define": "off", - - "dot-notation": "off", - "@typescript-eslint/dot-notation": "off", - - "@typescript-eslint/no-namespace": "off", - "@typescript-eslint/prefer-ts-expect-error": "error", - "@typescript-eslint/no-misused-promises": [ - "error", - { - checksConditionals: false, - }, - ], - "@typescript-eslint/no-floating-promises": [ - "error", - { - ignoreIIFE: true, - }, - ], - - // no-unsafe-* does not work good - "@typescript-eslint/no-unsafe-call": "off", - "@typescript-eslint/no-unsafe-member-access": "off", - "@typescript-eslint/no-unsafe-return": "off", - "@typescript-eslint/no-unsafe-argument": "off", - "@typescript-eslint/no-unsafe-assignment": "off", - }, -}; diff --git a/packages/eslint-config/configs/airbnb-ts-mod.js b/packages/eslint-config/configs/airbnb-ts-mod.js deleted file mode 100644 index 9126308..0000000 --- a/packages/eslint-config/configs/airbnb-ts-mod.js +++ /dev/null @@ -1,17 +0,0 @@ -module.exports = { - extends: ["./airbnb-ts-base-mod.js"], - rules: { - // modifies airbnb rules for react - "react/jsx-props-no-spreading": "off", - "react/jsx-uses-react": "off", - "react/react-in-jsx-scope": "off", - "react/forbid-prop-types": "off", - "react/function-component-definition": [ - 2, - { - namedComponents: "arrow-function", - unnamedComponents: "arrow-function", - }, - ], - }, -}; diff --git a/packages/eslint-config/configs/env.js b/packages/eslint-config/configs/env.js deleted file mode 100644 index 434daa0..0000000 --- a/packages/eslint-config/configs/env.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = { - env: { - browser: true, - node: true, - es2022: true, - }, - parserOptions: { - sourceType: "module", - ecmaVersion: "2022", - }, -}; diff --git a/packages/eslint-config/eslint.config.js b/packages/eslint-config/eslint.config.js new file mode 100644 index 0000000..a36cee3 --- /dev/null +++ b/packages/eslint-config/eslint.config.js @@ -0,0 +1,4 @@ +import eslint from "@eslint/js"; +import tseslint from "typescript-eslint"; + +export default tseslint.config(eslint.configs.recommended, ...tseslint.configs.recommended); diff --git a/packages/eslint-config/esm.js b/packages/eslint-config/esm.js deleted file mode 100644 index f4fde78..0000000 --- a/packages/eslint-config/esm.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - extends: ["./node"], - rules: { - "import/extensions": ["error", "ignorePackages"], - }, -}; diff --git a/packages/eslint-config/index.js b/packages/eslint-config/index.js deleted file mode 100644 index ae8f348..0000000 --- a/packages/eslint-config/index.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = { - extends: [ - "eslint:recommended", - "airbnb-base", - "./configs/airbnb-base-mod", - "prettier", - "./overrides/ts", - "./configs/env", - ], -}; diff --git a/packages/eslint-config/jest.js b/packages/eslint-config/jest.js deleted file mode 100644 index 990fa37..0000000 --- a/packages/eslint-config/jest.js +++ /dev/null @@ -1,25 +0,0 @@ -module.exports = { - overrides: [ - { - files: [ - "test/**/*.{js,ts,jsx,tsx}", - "**/__test__/**/*.{js,ts,jsx,tsx}", - "**/__tests__/**/*.{js,ts,jsx,tsx}", - "**/*.spec.{js,ts,jsx,tsx}", - "**/*.test.{js,ts,jsx,tsx}", - ], - extends: ["plugin:jest/recommended"], - plugins: ["jest", "testing-library"], - env: { - commonjs: true, - node: true, - "jest/globals": true, - }, - rules: { - "import/no-extraneous-dependencies": "off", - "@typescript-eslint/unbound-method": "off", - "jest/unbound-method": "error", - }, - }, - ], -}; diff --git a/packages/eslint-config/node.js b/packages/eslint-config/node.js deleted file mode 100644 index 6b3656a..0000000 --- a/packages/eslint-config/node.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = { - extends: ["./index"], - env: { - node: true, - browser: false, - }, - rules: { - "no-console": "off", - }, -}; diff --git a/packages/eslint-config/overrides/react.js b/packages/eslint-config/overrides/react.js deleted file mode 100644 index c900b76..0000000 --- a/packages/eslint-config/overrides/react.js +++ /dev/null @@ -1,27 +0,0 @@ -module.exports = { - overrides: [ - { - files: ["*.js", "*.jsx"], - extends: ["airbnb", "airbnb/hooks", "../configs/airbnb-mod", "prettier", "../configs/env"], - }, - { - files: ["*.ts", "*.tsx"], - extends: [ - "plugin:@typescript-eslint/recommended", - "plugin:@typescript-eslint/recommended-requiring-type-checking", - "airbnb", - "airbnb/hooks", - "airbnb-typescript", - "../configs/airbnb-ts-mod", - "prettier", - "../configs/env", - ], - plugins: ["@typescript-eslint"], - parser: "@typescript-eslint/parser", - rules: { - "react/require-default-props": "off", - "react/prop-types": "off", - }, - }, - ], -}; diff --git a/packages/eslint-config/overrides/sveltejs.js b/packages/eslint-config/overrides/sveltejs.js deleted file mode 100644 index ff819bd..0000000 --- a/packages/eslint-config/overrides/sveltejs.js +++ /dev/null @@ -1,25 +0,0 @@ -module.exports = { - overrides: [ - { - files: ["*.svelte"], - extends: [ - "airbnb-base", - "../configs/airbnb-base-mod", - "plugin:svelte/recommended", - "plugin:svelte/prettier", - "prettier", - "../configs/env", - ], - parser: "svelte-eslint-parser", - - parserOptions: { - extraFileExtensions: [".svelte"], - }, - rules: { - "no-undef-init": "off", - "no-unused-vars": "off", - "import/no-mutable-exports": "off", - }, - }, - ], -}; diff --git a/packages/eslint-config/overrides/sveltets.js b/packages/eslint-config/overrides/sveltets.js deleted file mode 100644 index 4719c6a..0000000 --- a/packages/eslint-config/overrides/sveltets.js +++ /dev/null @@ -1,32 +0,0 @@ -module.exports = { - overrides: [ - { - files: ["*.svelte"], - extends: [ - "plugin:@typescript-eslint/recommended", - "plugin:@typescript-eslint/recommended-requiring-type-checking", - "airbnb-base", - "airbnb-typescript/base", - "../configs/airbnb-ts-base-mod", - "plugin:svelte/recommended", - "plugin:svelte/prettier", - "prettier", - "../configs/env", - ], - parser: "svelte-eslint-parser", - - parserOptions: { - parser: "@typescript-eslint/parser", - extraFileExtensions: [".svelte"], - }, - rules: { - "no-undef-init": "off", - "no-unused-vars": "off", - "@typescript-eslint/no-unused-vars": "off", - "import/no-mutable-exports": "off", - // import/no-unresolved doesn't work properly in .svelte files, but ts takes care of this - "import/no-unresolved": "off", - }, - }, - ], -}; diff --git a/packages/eslint-config/overrides/ts.js b/packages/eslint-config/overrides/ts.js deleted file mode 100644 index bbf4977..0000000 --- a/packages/eslint-config/overrides/ts.js +++ /dev/null @@ -1,23 +0,0 @@ -module.exports = { - overrides: [ - { - files: ["*.ts"], - extends: [ - "plugin:@typescript-eslint/recommended", - "plugin:@typescript-eslint/recommended-requiring-type-checking", - "airbnb-base", - "airbnb-typescript/base", - "../configs/airbnb-ts-base-mod", - "prettier", - "../configs/env", - ], - settings: { - "import/resolver": { - typescript: {}, // this loads /tsconfig.json to eslint - }, - }, - plugins: ["@typescript-eslint"], - parser: "@typescript-eslint/parser", - }, - ], -}; diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index 4d79ddc..88420a0 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -1,69 +1,66 @@ { "name": "@qlik/eslint-config", "version": "0.8.2", - "description": "Qlik's ESLint config for typescript", + "description": "Qlik's ESLint configs", "repository": "git@github.com:qlik-oss/dev-tools-js.git", "license": "ISC", - "main": "index.js", + "type": "module", + "exports": { + ".": "./src/index.js" + }, + "module": "./src/index.js", + "types": "./src/index.d.ts", "files": [ - "configs", - "overrides", - "index.js", - "jest.js", - "node.js", - "esm.js", - "react.js", - "svelte.js", - "svelte-js.js", - "vitest.js", - "playwright.js", - "react-svelte.js" + "src", + "!**/__tests__" ], "scripts": { + "check-types": "tsc --noEmit", "format:check": "prettier --check '**' --ignore-unknown", "format:write": "prettier --write '**' --ignore-unknown", - "lint": "ESLINT_USE_FLAT_CONFIG=false eslint ." + "lint": "eslint ." }, "prettier": "@qlik/prettier-config", - "eslintConfig": { - "env": { - "es6": true, - "node": true - }, - "extends": "eslint:recommended" - }, "dependencies": { - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "@vitest/eslint-plugin": "1.1.10", - "eslint-config-airbnb": "^19.0.4", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-config-airbnb-typescript": "^18.0.0", - "eslint-config-prettier": "^9.1.0", + "@eslint-react/eslint-plugin": "1.16.2", + "@eslint/js": "^9.15.0", + "@typescript-eslint/utils": "^8.15.0", + "@vitest/eslint-plugin": "^1.1.10", + "confusing-browser-globals": "^1.0.11", "eslint-import-resolver-typescript": "^3.6.3", - "eslint-plugin-import": "^2.31.0", + "eslint-plugin-import-x": "^4.4.2", "eslint-plugin-jest": "^28.9.0", "eslint-plugin-jsx-a11y": "^6.10.2", - "eslint-plugin-playwright": "^2.1.0", + "eslint-plugin-playwright": "2.1.0", "eslint-plugin-react": "^7.37.2", "eslint-plugin-react-hooks": "^5.0.0", - "eslint-plugin-svelte": "^2.46.0", - "eslint-plugin-testing-library": "^6.5.0", - "svelte-eslint-parser": "^0.43.0" + "eslint-plugin-svelte": "2.46.0", + "eslint-plugin-testing-library": "^7.0.0", + "globals": "^15.12.0", + "svelte-eslint-parser": "0.43.0", + "typescript-eslint": "^8.15.0" }, "devDependencies": { "@qlik/prettier-config": "workspace:*", + "@qlik/tsconfig": "workspace:*", + "@types/confusing-browser-globals": "^1.0.3", + "@types/eslint-plugin-jsx-a11y": "^6.9.0", + "@types/eslint__js": "^8.42.3", "eslint": "^9.15.0", - "prettier": "^3.3.3" + "prettier": "^3.3.3", + "vitest": "^2.1.5" }, "peerDependencies": { - "eslint": "^8.0.0" + "eslint": ">=9.0.0" }, "engines": { - "node": ">=16" + "node": ">=18" }, "publishConfig": { "access": "public", + "exports": { + ".": "./lib/index.js" + }, "registry": "https://registry.npmjs.org/" } } diff --git a/packages/eslint-config/playwright.js b/packages/eslint-config/playwright.js deleted file mode 100644 index fe911f7..0000000 --- a/packages/eslint-config/playwright.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = { - overrides: [ - { - files: ["playwright.config.{js,ts}", "**/{test,tests}/**/*.{ts,js}"], - extends: ["plugin:playwright/playwright-test"], - rules: { - "import/no-extraneous-dependencies": "off", - "playwright/no-networkidle": "off", - }, - }, - ], -}; diff --git a/packages/eslint-config/react-svelte.js b/packages/eslint-config/react-svelte.js deleted file mode 100644 index 3bca219..0000000 --- a/packages/eslint-config/react-svelte.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - extends: ["./index", "./overrides/react", "./overrides/sveltets"], - parserOptions: { - extraFileExtensions: [".svelte"], - }, -}; diff --git a/packages/eslint-config/react.js b/packages/eslint-config/react.js deleted file mode 100644 index 6565b02..0000000 --- a/packages/eslint-config/react.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: ["./index", "./overrides/react"], -}; diff --git a/packages/eslint-config/src/__tests__/qlik-eslint.test.ts b/packages/eslint-config/src/__tests__/qlik-eslint.test.ts new file mode 100644 index 0000000..3af7c15 --- /dev/null +++ b/packages/eslint-config/src/__tests__/qlik-eslint.test.ts @@ -0,0 +1,9 @@ +import { describe, expect, it } from "vitest"; +import qlikEslint from "../index.js"; + +describe("qlik-eslint", () => { + it("should export a base config", () => { + const base = qlikEslint.configs.recommended; + expect(base[0]).toHaveProperty("rules"); + }); +}); diff --git a/packages/eslint-config/src/configs/cjs.js b/packages/eslint-config/src/configs/cjs.js new file mode 100644 index 0000000..ea2c451 --- /dev/null +++ b/packages/eslint-config/src/configs/cjs.js @@ -0,0 +1,45 @@ +// @ts-check +import globals from "globals"; +import { mergeConfigs } from "../utils/config.js"; +import { recommendedJS, recommendedTS } from "./recommended.js"; + +/** + * @satisfies {import("../types/index.js").ESLintFlatConfig['rules']} + */ +const cjsRules = { + // modify rules for node here +}; + +/** + * @type {import("../types/index.js").ESLintFlatConfig} + */ +const cjsJS = mergeConfigs(recommendedJS, { + name: "node-cjs-js", + files: ["**/*.{js,cjs}"], + languageOptions: { + globals: globals.node, + sourceType: "commonjs", + }, + rules: { + ...cjsRules, + }, +}); + +/** + * @type {import("../types/index.js").ESLintFlatConfig} + */ +const cjsTS = mergeConfigs(recommendedTS, { + name: "node-cjs-ts", + files: ["**/*.{ts,cts}"], + languageOptions: { + globals: globals.node, + sourceType: "commonjs", + }, + rules: { + ...cjsRules, + // modify ts specific rules for node here + }, +}); + +export default [cjsJS, cjsTS]; +export { cjsJS, cjsTS }; diff --git a/packages/eslint-config/src/configs/esm.js b/packages/eslint-config/src/configs/esm.js new file mode 100644 index 0000000..94569e8 --- /dev/null +++ b/packages/eslint-config/src/configs/esm.js @@ -0,0 +1,43 @@ +// @ts-check +import { mergeConfigs } from "../utils/config.js"; +import { cjsJS, cjsTS } from "./cjs.js"; + +/** + * @satisfies {import("../types/index.js").ESLintFlatConfig["rules"]} + */ +const nodeEsmRules = { + // modify rules for node esm here + "import-x/extensions": ["error", "ignorePackages"], +}; + +/** + * @type {import("../types/index.js").ESLintFlatConfig} + */ +const esmJS = mergeConfigs(cjsJS, { + name: "node-esm-js", + files: ["**/*.{js,mjs}"], + languageOptions: { + sourceType: "module", + }, + rules: { + ...nodeEsmRules, + }, +}); + +/** + * @type {import("../types/index.js").ESLintFlatConfig} + */ +const esmTS = mergeConfigs(cjsTS, { + name: "node-esm-ts", + files: ["**/*.{ts,mts}"], + languageOptions: { + sourceType: "module", + }, + rules: { + ...nodeEsmRules, + // modify ts specific rules for node esm here + }, +}); + +export default [esmJS, esmTS]; +export { esmJS, esmTS }; diff --git a/packages/eslint-config/src/configs/jest.js b/packages/eslint-config/src/configs/jest.js new file mode 100644 index 0000000..e824062 --- /dev/null +++ b/packages/eslint-config/src/configs/jest.js @@ -0,0 +1,24 @@ +// @ts-check +import jestPlugin from "eslint-plugin-jest"; +import testingLibraryPlugin from "eslint-plugin-testing-library"; +import { mergeConfigs } from "../utils/config.js"; +import rules from "./rules/index.js"; + +/** + * @type {import("../types/index.js").ESLintFlatConfig} + * config for jest https://github.com/jest-community/eslint-plugin-jest + */ +const jest = mergeConfigs(jestPlugin.configs["flat/recommended"], { + name: "jest-js", + files: ["**/__test__/**/*.{js,jsx,ts,tsx}", "**/__tests__/**/*.{js,jsx,ts,tsx}"], + plugins: { + "testing-library": testingLibraryPlugin, + }, + rules: { + ...rules.testingLibraryRules, + // modify rules from eslint-plugin-jest here + }, +}); + +export default [jest]; +export { jest }; diff --git a/packages/eslint-config/src/configs/playwright.js b/packages/eslint-config/src/configs/playwright.js new file mode 100644 index 0000000..a90ccda --- /dev/null +++ b/packages/eslint-config/src/configs/playwright.js @@ -0,0 +1,19 @@ +// @ts-check +import playwrightEslint from "eslint-plugin-playwright"; +import { mergeConfigs } from "../utils/config.js"; + +/** + * @type {import("../types/index.js").ESLintFlatConfig} + * config for Playwright https://github.com/playwright-community/eslint-plugin-playwright + */ +const playwright = mergeConfigs(playwrightEslint.configs["flat/recommended"], { + name: "playwright", + files: ["tests/**", "test/**"], + rules: { + ...playwrightEslint.configs["flat/recommended"].rules, + // modify rules from eslint-plugin-playwright here + }, +}); + +export default [playwright]; +export { playwright }; diff --git a/packages/eslint-config/src/configs/react.js b/packages/eslint-config/src/configs/react.js new file mode 100644 index 0000000..38a92d4 --- /dev/null +++ b/packages/eslint-config/src/configs/react.js @@ -0,0 +1,75 @@ +// @ts-check +import react from "@eslint-react/eslint-plugin"; +import jsxA11y from "eslint-plugin-jsx-a11y"; +import eslintPluginReact from "eslint-plugin-react"; +// @ts-expect-error no types for this plugin yet +import reactHooks from "eslint-plugin-react-hooks"; +import { mergeConfigs } from "../utils/config.js"; +import { recommendedJS, recommendedTS } from "./recommended.js"; +import rules from "./rules/index.js"; + +/** @type {any} */ +const reactPlugin = eslintPluginReact; + +/** + * @type {import("../types/index.js").ESLintFlatConfig} + */ +const reactConfig = mergeConfigs({ + languageOptions: { + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + jsxPragma: null, // for @typescript/eslint-parser + }, + }, + + plugins: { ...react.configs.recommended.plugins, react: reactPlugin, "jsx-a11y": jsxA11y, "react-hooks": reactHooks }, + + settings: { + ...react.configs.recommended.settings, + react: { + version: "detect", + }, + }, + + rules: { + // react plugin + ...reactPlugin.configs.flat.recommended.rules, + ...rules.reactRules, + // jsx-a11y plugin + ...jsxA11y.flatConfigs.recommended.rules, + ...rules.reactA11yRules, + ...react.configs.recommended.rules, + // react-hooks plugin + ...reactHooks.configs.recommended.rules, + ...rules.reactHooksRules, + }, +}); + +/** + * @type {import("../types/index.js").ESLintFlatConfig} + */ +const reactJS = mergeConfigs(reactConfig, recommendedJS, { + name: "react-js", + files: ["**/*.jsx"], + rules: { + // turn on/off or modify js rules necessary for react + "react/jsx-filename-extension": [2, { extensions: [".js", ".jsx"] }], + }, +}); + +/** + * @type {import("../types/index.js").ESLintFlatConfig} + */ +const reactTS = mergeConfigs(reactConfig, recommendedTS, { + name: "react-ts", + files: ["**/*.tsx"], + rules: { + // turn on/off or modify js/ts rules necessary for react + "react/jsx-filename-extension": [2, { extensions: [".js", ".jsx", ".ts", ".tsx"] }], + }, +}); + +export default [recommendedJS, reactTS, recommendedTS, reactTS]; +export { reactJS, reactTS }; diff --git a/packages/eslint-config/src/configs/recommended.js b/packages/eslint-config/src/configs/recommended.js new file mode 100644 index 0000000..1eb090a --- /dev/null +++ b/packages/eslint-config/src/configs/recommended.js @@ -0,0 +1,64 @@ +// @ts-check +import js from "@eslint/js"; +import tsParser from "@typescript-eslint/parser"; +import eslintPluginImportX from "eslint-plugin-import-x"; +import globals from "globals"; +import tsconfig from "typescript-eslint"; +import { mergeConfigs } from "../utils/config.js"; +import rules from "./rules/index.js"; + +/** + * @type {import("../types/index.js").ESLintFlatConfig} + */ +const recommendedJS = mergeConfigs( + { + files: ["**/*.js", "**/*.jsx", "**/*.mjs", "**/*.cjs"], + languageOptions: { + globals: globals.browser, + parserOptions: { + warnOnUnsupportedTypeScriptVersion: false, + }, + ecmaVersion: 2021, + sourceType: "module", + }, + }, + // tsconfig.configs.base sets eslint parser to use the typescript parser to parse .js files - handles all modern syntax + tsconfig.configs.base, + js.configs.recommended, + eslintPluginImportX.flatConfigs.recommended, + { + name: "recommended-js", + rules: { + ...rules.importXRules, + ...rules.eslintCoreRules, + }, + }, +); + +/** + * @type {import("../types/index.js").ESLintFlatConfig} + */ +const recommendedTS = mergeConfigs( + recommendedJS, + { + files: ["**/*.ts", "**/*.tsx", "**/*.mts", "**/*.cts", "**/*.d.ts"], + languageOptions: { + parserOptions: { + parser: tsParser, + projectService: true, + ecmaVersion: "latest", + sourceType: "module", + }, + }, + }, + ...tsconfig.configs.recommended, + eslintPluginImportX.flatConfigs.recommended, + eslintPluginImportX.flatConfigs.typescript, + { + name: "recommended-ts", + rules: rules.typescriptRules, + }, +); + +export default [recommendedJS, recommendedTS]; +export { recommendedJS, recommendedTS }; diff --git a/packages/eslint-config/src/configs/rules/eslint-core.js b/packages/eslint-config/src/configs/rules/eslint-core.js new file mode 100644 index 0000000..7d8f7bd --- /dev/null +++ b/packages/eslint-config/src/configs/rules/eslint-core.js @@ -0,0 +1,970 @@ +// @ts-check +import confusingBrowserGlobals from "confusing-browser-globals"; + +/** + * @satisfies {import("../../types/index.js").ESLintFlatConfig["rules"]} + * + * eslint core package https://eslint.org/docs/latest/rules/ + */ +const rules = { + // modify/add rules from eslint core package here additionally to the recommended rules + + // enforces return statements in callbacks of array's methods + // https://eslint.org/docs/rules/array-callback-return + "array-callback-return": ["error", { allowImplicit: true }], + + // treat var statements as if they were block scoped + // https://eslint.org/docs/rules/block-scoped-var + "block-scoped-var": "error", + + // enforce that class methods use "this" + // https://eslint.org/docs/rules/class-methods-use-this + "class-methods-use-this": [ + "warn", + { + exceptMethods: [], + }, + ], + + // require return statements to either always or never specify values + // https://eslint.org/docs/rules/consistent-return + "consistent-return": "error", + + // specify curly brace conventions for all control statements + // https://eslint.org/docs/rules/curly + curly: ["error", "multi-line"], // multiline + + // require default case in switch statements + // https://eslint.org/docs/rules/default-case + "default-case": ["error", { commentPattern: "^no default$" }], + + // Enforce default clauses in switch statements to be last + // https://eslint.org/docs/rules/default-case-last + "default-case-last": "error", + + // https://eslint.org/docs/rules/default-param-last + "default-param-last": "error", + + // DEPRECATED. enforces consistent newlines before or after dots + // https://eslint.org/docs/rules/dot-location + // "dot-location": ["error", "property"], + + // require the use of === and !== + // https://eslint.org/docs/rules/eqeqeq + eqeqeq: ["error", "always", { null: "ignore" }], + + // Require grouped accessor pairs in object literals and classes + // https://eslint.org/docs/rules/grouped-accessor-pairs + "grouped-accessor-pairs": "error", + + // enforce a maximum number of classes per file + // https://eslint.org/docs/rules/max-classes-per-file + "max-classes-per-file": ["error", 1], + + // disallow the use of alert, confirm, and prompt + // https://eslint.org/docs/rules/no-alert + "no-alert": "error", + + // disallow use of arguments.caller or arguments.callee + // https://eslint.org/docs/rules/no-caller + "no-caller": "error", + + // disallow lexical declarations in case/default clauses + // https://eslint.org/docs/rules/no-case-declarations + "no-case-declarations": "error", + + // Disallow returning value in constructor + // https://eslint.org/docs/rules/no-constructor-return + "no-constructor-return": "error", + + // disallow else after a return in an if + // https://eslint.org/docs/rules/no-else-return + "no-else-return": ["error", { allowElseIf: false }], + + // disallow empty functions, except for standalone funcs/arrows + // https://eslint.org/docs/rules/no-empty-function + "no-empty-function": [ + "error", + { + allow: ["arrowFunctions", "functions", "methods"], + }, + ], + + // disallow empty destructuring patterns + // https://eslint.org/docs/rules/no-empty-pattern + "no-empty-pattern": "error", + + // disallow use of eval() + // https://eslint.org/docs/rules/no-eval + "no-eval": "error", + + // disallow adding to native types + // https://eslint.org/docs/rules/no-extend-native + "no-extend-native": "error", + + // disallow unnecessary function binding + // https://eslint.org/docs/rules/no-extra-bind + "no-extra-bind": "error", + + // disallow Unnecessary Labels + // https://eslint.org/docs/rules/no-extra-label + "no-extra-label": "error", + + // disallow fallthrough of case statements + // https://eslint.org/docs/rules/no-fallthrough + "no-fallthrough": "error", + + // DEPRECATED. disallow the use of leading or trailing decimal points in numeric literals + // https://eslint.org/docs/rules/no-floating-decimal + // "no-floating-decimal": "error", + + // disallow reassignments of native objects or read-only globals + // https://eslint.org/docs/rules/no-global-assign + "no-global-assign": ["error", { exceptions: [] }], + + // disallow use of eval()-like methods + // https://eslint.org/docs/rules/no-implied-eval + "no-implied-eval": "error", + + // disallow usage of __iterator__ property + // https://eslint.org/docs/rules/no-iterator + "no-iterator": "error", + + // disallow use of labels for anything other than loops and switches + // https://eslint.org/docs/rules/no-labels + "no-labels": ["error", { allowLoop: false, allowSwitch: false }], + + // disallow unnecessary nested blocks + // https://eslint.org/docs/rules/no-lone-blocks + "no-lone-blocks": "error", + + // disallow creation of functions within loops + // https://eslint.org/docs/rules/no-loop-func + "no-loop-func": "error", + + // don't use magic numbers + // https://eslint.org/docs/rules/no-magic-numbers + "no-magic-numbers": "off", + + // DEPRECATED. disallow use of multiple spaces + // https://eslint.org/docs/rules/no-multi-spaces + // "no-multi-spaces": [ + // "error", + // { + // ignoreEOLComments: false, + // }, + // ], + + // disallow use of multiline strings + // https://eslint.org/docs/rules/no-multi-str + "no-multi-str": "error", + + // disallow use of new operator when not part of the assignment or comparison + // https://eslint.org/docs/rules/no-new + "no-new": "error", + + // disallow use of new operator for Function object + // https://eslint.org/docs/rules/no-new-func + "no-new-func": "error", + + // disallows creating new instances of String, Number, and Boolean + // https://eslint.org/docs/rules/no-new-wrappers + "no-new-wrappers": "error", + + // Disallow \8 and \9 escape sequences in string literals + // https://eslint.org/docs/rules/no-nonoctal-decimal-escape + "no-nonoctal-decimal-escape": "error", + + // Disallow calls to the Object constructor without an argument + // https://eslint.org/docs/latest/rules/no-object-constructor + "no-object-constructor": "error", + + // disallow use of (old style) octal literals + // https://eslint.org/docs/rules/no-octal + "no-octal": "error", + + // disallow use of octal escape sequences in string literals, such as + // var foo = 'Copyright \251'; + // https://eslint.org/docs/rules/no-octal-escape + "no-octal-escape": "error", + + // disallow reassignment of function parameters + // disallow parameter object manipulation except for specific exclusions + // rule: https://eslint.org/docs/rules/no-param-reassign.html + "no-param-reassign": [ + "error", + { + props: true, + ignorePropertyModificationsFor: [ + "prev", // for reduce accumulators + "acc", // for reduce accumulators + "accumulator", // for reduce accumulators + "e", // for e.returnvalue + "ctx", // for Koa routing + "context", // for Koa routing + "req", // for Express requests + "request", // for Express requests + "res", // for Express responses + "response", // for Express responses + "$scope", // for Angular 1 scopes + "staticContext", // for ReactRouter context + ], + }, + ], + + // disallow usage of __proto__ property + // https://eslint.org/docs/rules/no-proto + "no-proto": "error", + + // disallow declaring the same variable more than once + // https://eslint.org/docs/rules/no-redeclare + "no-redeclare": "error", + + // disallow certain object properties + // https://eslint.org/docs/rules/no-restricted-properties + "no-restricted-properties": [ + "error", + { + object: "arguments", + property: "callee", + message: "arguments.callee is deprecated", + }, + { + object: "global", + property: "isFinite", + message: "Please use Number.isFinite instead", + }, + { + object: "self", + property: "isFinite", + message: "Please use Number.isFinite instead", + }, + { + object: "window", + property: "isFinite", + message: "Please use Number.isFinite instead", + }, + { + object: "global", + property: "isNaN", + message: "Please use Number.isNaN instead", + }, + { + object: "self", + property: "isNaN", + message: "Please use Number.isNaN instead", + }, + { + object: "window", + property: "isNaN", + message: "Please use Number.isNaN instead", + }, + { + property: "__defineGetter__", + message: "Please use Object.defineProperty instead.", + }, + { + property: "__defineSetter__", + message: "Please use Object.defineProperty instead.", + }, + { + object: "Math", + property: "pow", + message: "Use the exponentiation operator (**) instead.", + }, + ], + + // disallow use of assignment in return statement + // https://eslint.org/docs/rules/no-return-assign + "no-return-assign": ["error", "always"], + + // DEPRECATED. disallow redundant `return await` + // https://eslint.org/docs/rules/no-return-await + // "no-return-await": "error", + + // disallow use of `javascript:` urls. + // https://eslint.org/docs/rules/no-script-url + "no-script-url": "error", + + // disallow self assignment + // https://eslint.org/docs/rules/no-self-assign + "no-self-assign": [ + "error", + { + props: true, + }, + ], + + // disallow comparisons where both sides are exactly the same + // https://eslint.org/docs/rules/no-self-compare + "no-self-compare": "error", + + // disallow use of comma operator + // https://eslint.org/docs/rules/no-sequences + "no-sequences": "error", + + // restrict what can be thrown as an exception + // https://eslint.org/docs/rules/no-throw-literal + "no-throw-literal": "error", + + // disallow unmodified conditions of loops + // https://eslint.org/docs/rules/no-unmodified-loop-condition + "no-unmodified-loop-condition": "error", + + // disallow usage of expressions in statement position + // https://eslint.org/docs/rules/no-unused-expressions + "no-unused-expressions": [ + "error", + { + allowShortCircuit: false, + allowTernary: false, + allowTaggedTemplates: false, + }, + ], + + // disallow unused labels + // https://eslint.org/docs/rules/no-unused-labels + "no-unused-labels": "error", + + // disallow unnecessary .call() and .apply() + // https://eslint.org/docs/rules/no-useless-call + "no-useless-call": "error", + + // Disallow unnecessary catch clauses + // https://eslint.org/docs/rules/no-useless-catch + "no-useless-catch": "error", + + // disallow useless string concatenation + // https://eslint.org/docs/rules/no-useless-concat + "no-useless-concat": "error", + + // disallow unnecessary string escaping + // https://eslint.org/docs/rules/no-useless-escape + "no-useless-escape": "error", + + // disallow redundant return; keywords + // https://eslint.org/docs/rules/no-useless-return + "no-useless-return": "error", + + // disallow use of the with statement + // https://eslint.org/docs/rules/no-with + "no-with": "error", + + // require using Error objects as Promise rejection reasons + // https://eslint.org/docs/rules/prefer-promise-reject-errors + "prefer-promise-reject-errors": ["error", { allowEmptyReject: true }], + + // Prefer Object.hasOwn() over Object.prototype.hasOwnProperty.call() + // https://eslint.org/docs/rules/prefer-object-has-own + "prefer-object-has-own": "error", + + // https://eslint.org/docs/rules/prefer-regex-literals + "prefer-regex-literals": [ + "error", + { + disallowRedundantWrapping: true, + }, + ], + + // require use of the second argument for parseInt() + // https://eslint.org/docs/rules/radix + radix: "error", + + // DEPRECATED. require immediate function invocation to be wrapped in parentheses + // https://eslint.org/docs/rules/wrap-iife.html + // "wrap-iife": ["error", "outside", { functionPrototypeMethods: false }], + + // require or disallow Yoda conditions + // https://eslint.org/docs/rules/yoda + yoda: "error", + + // Enforce “for” loop update clause moving the counter in the right direction + // https://eslint.org/docs/rules/for-direction + "for-direction": "error", + + // Enforces that a return statement is present in property getters + // https://eslint.org/docs/rules/getter-return + "getter-return": ["error", { allowImplicit: true }], + + // disallow using an async function as a Promise executor + // https://eslint.org/docs/rules/no-async-promise-executor + "no-async-promise-executor": "error", + + // Disallow await inside of loops + // https://eslint.org/docs/rules/no-await-in-loop + "no-await-in-loop": "error", + + // Disallow comparisons to negative zero + // https://eslint.org/docs/rules/no-compare-neg-zero + "no-compare-neg-zero": "error", + + // disallow assignment in conditional expressions + "no-cond-assign": ["error", "always"], + + // disallow use of console + "no-console": "warn", + + // Disallows expressions where the operation doesn't affect the value + // https://eslint.org/docs/rules/no-constant-binary-expression + "no-constant-binary-expression": "error", + + // disallow use of constant expressions in conditions + "no-constant-condition": "warn", + + // disallow control characters in regular expressions + "no-control-regex": "error", + + // disallow use of debugger + "no-debugger": "error", + + // disallow duplicate arguments in functions + "no-dupe-args": "error", + + // Disallow duplicate conditions in if-else-if chains + // https://eslint.org/docs/rules/no-dupe-else-if + "no-dupe-else-if": "error", + + // disallow duplicate keys when creating object literals + "no-dupe-keys": "error", + + // disallow a duplicate case label. + "no-duplicate-case": "error", + + // disallow empty statements + "no-empty": "error", + + // disallow the use of empty character classes in regular expressions + "no-empty-character-class": "error", + + // disallow assigning to the exception in a catch block + "no-ex-assign": "error", + + // disallow double-negation boolean casts in a boolean context + // https://eslint.org/docs/rules/no-extra-boolean-cast + "no-extra-boolean-cast": "error", + + // DEPRECATED. disallow unnecessary semicolons + // "no-extra-semi": "error", + + // disallow overwriting functions written as function declarations + "no-func-assign": "error", + + // https://eslint.org/docs/rules/no-import-assign + "no-import-assign": "error", + + // disallow function or variable declarations in nested blocks + "no-inner-declarations": "error", + + // disallow invalid regular expression strings in the RegExp constructor + "no-invalid-regexp": "error", + + // disallow irregular whitespace outside of strings and comments + "no-irregular-whitespace": "error", + + // Disallow Number Literals That Lose Precision + // https://eslint.org/docs/rules/no-loss-of-precision + "no-loss-of-precision": "error", + + // Disallow characters which are made with multiple code points in character class syntax + // https://eslint.org/docs/rules/no-misleading-character-class + "no-misleading-character-class": "error", + + // disallow the use of object properties of the global object (Math and JSON) as functions + "no-obj-calls": "error", + + // Disallow new operators with global non-constructor functions + // https://eslint.org/docs/latest/rules/no-new-native-nonconstructor + "no-new-native-nonconstructor": "error", + + // Disallow returning values from Promise executor functions + // https://eslint.org/docs/rules/no-promise-executor-return + "no-promise-executor-return": "error", + + // disallow use of Object.prototypes builtins directly + // https://eslint.org/docs/rules/no-prototype-builtins + "no-prototype-builtins": "error", + + // disallow multiple spaces in a regular expression literal + "no-regex-spaces": "error", + + // Disallow returning values from setters + // https://eslint.org/docs/rules/no-setter-return + "no-setter-return": "error", + + // disallow sparse arrays + "no-sparse-arrays": "error", + + // Disallow template literal placeholder syntax in regular strings + // https://eslint.org/docs/rules/no-template-curly-in-string + "no-template-curly-in-string": "error", + + // Avoid code that looks like two expressions but is actually one + // https://eslint.org/docs/rules/no-unexpected-multiline + "no-unexpected-multiline": "error", + + // disallow unreachable statements after a return, throw, continue, or break statement + "no-unreachable": "error", + + // Disallow loops with a body that allows only one iteration + // https://eslint.org/docs/rules/no-unreachable-loop + "no-unreachable-loop": [ + "error", + { + ignore: [], // WhileStatement, DoWhileStatement, ForStatement, ForInStatement, ForOfStatement + }, + ], + + // disallow return/throw/break/continue inside finally blocks + // https://eslint.org/docs/rules/no-unsafe-finally + "no-unsafe-finally": "error", + + // disallow negating the left operand of relational operators + // https://eslint.org/docs/rules/no-unsafe-negation + "no-unsafe-negation": "error", + + // disallow use of optional chaining in contexts where the undefined value is not allowed + // https://eslint.org/docs/rules/no-unsafe-optional-chaining + "no-unsafe-optional-chaining": ["error", { disallowArithmeticOperators: true }], + + // Disallow Unused Private Class Members + // https://eslint.org/docs/rules/no-unused-private-class-members + "no-unused-private-class-members": "error", + + // Disallow useless backreferences in regular expressions + // https://eslint.org/docs/rules/no-useless-backreference + "no-useless-backreference": "error", + + // Disallow assignments that can lead to race conditions due to usage of await or yield + // https://eslint.org/docs/rules/require-atomic-updates + // note: not enabled because it is very buggy + "require-atomic-updates": "error", + + // disallow comparisons with the value NaN + "use-isnan": "error", + + // ensure that the results of typeof are compared against a valid string + // https://eslint.org/docs/rules/valid-typeof + "valid-typeof": ["error", { requireStringLiterals: true }], + + // enforces no braces where they can be omitted + // https://eslint.org/docs/rules/arrow-body-style + "arrow-body-style": "off", + + // DEPRECATED. require parens in arrow function arguments + // https://eslint.org/docs/rules/arrow-parens + // "arrow-parens": ["error", "always"], + + // DEPREACTED. require space before/after arrow function's arrow + // https://eslint.org/docs/rules/arrow-spacing + // "arrow-spacing": ["error", { before: true, after: true }], + + // verify super() callings in constructors + "constructor-super": "error", + + // DEPREACTED. enforce the spacing around the * in generator functions + // https://eslint.org/docs/rules/generator-star-spacing + // "generator-star-spacing": ["error", { before: false, after: true }], + + // disallow modifying variables of class declarations + // https://eslint.org/docs/rules/no-class-assign + "no-class-assign": "error", + + // DEPRECATED. disallow arrow functions where they could be confused with comparisons + // https://eslint.org/docs/rules/no-confusing-arrow + // "no-confusing-arrow": [ + // "error", + // { + // allowParens: true, + // }, + // ], + + // disallow modifying variables that are declared using const + "no-const-assign": "error", + + // disallow duplicate class members + // https://eslint.org/docs/rules/no-dupe-class-members + "no-dupe-class-members": "error", + + // DEPRECATED. disallow symbol constructor + // https://eslint.org/docs/rules/no-new-symbol + // "no-new-symbol": "error", + + // Disallow specified names in exports + // https://eslint.org/docs/rules/no-restricted-exports + "no-restricted-exports": [ + "error", + { + restrictedNamedExports: [ + "default", // use `export default` to provide a default export + "then", // this will cause tons of confusion when your module is dynamically `import()`ed, and will break in most node ESM versions + ], + }, + ], + + // disallow specific imports + // https://eslint.org/docs/rules/no-restricted-imports + "no-restricted-imports": [ + "off", + { + paths: [], + patterns: [], + }, + ], + + // disallow to use this/super before super() calling in constructors. + // https://eslint.org/docs/rules/no-this-before-super + "no-this-before-super": "error", + + // disallow useless computed property keys + // https://eslint.org/docs/rules/no-useless-computed-key + "no-useless-computed-key": "error", + + // disallow unnecessary constructor + // https://eslint.org/docs/rules/no-useless-constructor + "no-useless-constructor": "error", + + // disallow renaming import, export, and destructured assignments to the same name + // https://eslint.org/docs/rules/no-useless-rename + "no-useless-rename": [ + "error", + { + ignoreDestructuring: false, + ignoreImport: false, + ignoreExport: false, + }, + ], + + // require let or const instead of var + "no-var": "error", + + // require method and property shorthand syntax for object literals + // https://eslint.org/docs/rules/object-shorthand + "object-shorthand": [ + "error", + "always", + { + ignoreConstructors: false, + avoidQuotes: true, + }, + ], + + // suggest using arrow functions as callbacks + "prefer-arrow-callback": "off", + + // suggest using of const declaration for variables that are never modified after declared + "prefer-const": [ + "error", + { + destructuring: "any", + ignoreReadBeforeAssign: true, + }, + ], + + // disallow parseInt() in favor of binary, octal, and hexadecimal literals + // https://eslint.org/docs/rules/prefer-numeric-literals + "prefer-numeric-literals": "error", + + // use rest parameters instead of arguments + // https://eslint.org/docs/rules/prefer-rest-params + "prefer-rest-params": "error", + + // suggest using the spread syntax instead of .apply() + // https://eslint.org/docs/rules/prefer-spread + "prefer-spread": "error", + + // suggest using template literals instead of string concatenation + // https://eslint.org/docs/rules/prefer-template + "prefer-template": "error", + + // disallow generator functions that do not have yield + // https://eslint.org/docs/rules/require-yield + "require-yield": "error", + + // DEPRECATED. enforce spacing between object rest-spread + // https://eslint.org/docs/rules/rest-spread-spacing + // "rest-spread-spacing": ["error", "never"], + + // require a Symbol description + // https://eslint.org/docs/rules/symbol-description + "symbol-description": "error", + + // DEPRECATED. enforce usage of spacing in template strings + // https://eslint.org/docs/rules/template-curly-spacing + // "template-curly-spacing": "error", + + // DEPRECATED. enforce spacing around the * in yield* expressions + // https://eslint.org/docs/rules/yield-star-spacing + // "yield-star-spacing": ["error", "after"], + + // disallow labels that share a name with a variable + // https://eslint.org/docs/rules/no-label-var + "no-label-var": "error", + + // disallow specific globals + // https://eslint.org/docs/latest/rules/no-restricted-globals + "no-restricted-globals": [ + "error", + { + name: "isFinite", + message: "Use Number.isFinite instead https://github.com/airbnb/javascript#standard-library--isfinite", + }, + { + name: "isNaN", + message: "Use Number.isNaN instead https://github.com/airbnb/javascript#standard-library--isnan", + }, + ...confusingBrowserGlobals.map((g) => ({ + name: g, + message: `Use window.${g} instead. https://github.com/facebook/create-react-app/blob/HEAD/packages/confusing-browser-globals/README.md`, + })), + ], + + // disallow declaration of variables already declared in the outer scope + "no-shadow": "error", + + // disallow shadowing of names such as arguments + "no-shadow-restricted-names": "error", + + // disallow use of undeclared variables unless mentioned in a /*global */ block + "no-undef": "error", + + // disallow use of undefined when initializing variables + "no-undef-init": "error", + + // disallow declaration of variables that are not used in the code + "no-unused-vars": ["error", { vars: "all", args: "after-used", ignoreRestSiblings: true }], + + // require camel case names + camelcase: ["error", { properties: "never", ignoreDestructuring: false }], + + // DEPRECATED. https://eslint.org/docs/rules/function-call-argument-newline + // "function-call-argument-newline": ["error", "consistent"], + + // require function expressions to have a name + // https://eslint.org/docs/rules/func-names + "func-names": "warn", + + // DEPRECATED. require or disallow newlines around directives + // https://eslint.org/docs/rules/lines-around-directive + // "lines-around-directive": [ + // "error", + // { + // before: "always", + // after: "always", + // }, + // ], + + // DEPRECATED. specify the maximum length of a line in your program + // https://eslint.org/docs/rules/max-len + // "max-len": [ + // "error", + // 100, + // 2, + // { + // ignoreUrls: true, + // ignoreComments: false, + // ignoreRegExpLiterals: true, + // ignoreStrings: true, + // ignoreTemplateLiterals: true, + // }, + // ], + + // require a capital letter for constructors + "new-cap": [ + "error", + { + newIsCap: true, + newIsCapExceptions: [], + capIsNew: false, + capIsNewExceptions: ["Immutable.Map", "Immutable.Set", "Immutable.List"], + }, + ], + + // DEPRECATED. disallow the omission of parentheses when invoking a constructor with no arguments + // https://eslint.org/docs/rules/new-parens + // "new-parens": "error", + + // DEPRECATED. enforces new line after each method call in the chain to make it + // more readable and easy to maintain + // https://eslint.org/docs/rules/newline-per-chained-call + // "newline-per-chained-call": ["error", { ignoreChainWithDepth: 4 }], + + // disallow use of the Array constructor + "no-array-constructor": "error", + + // disallow use of bitwise operators + // https://eslint.org/docs/rules/no-bitwise + "no-bitwise": "error", + + // disallow use of the continue statement + // https://eslint.org/docs/rules/no-continue + "no-continue": "error", + + // disallow if as the only statement in an else block + // https://eslint.org/docs/rules/no-lonely-if + "no-lonely-if": "error", + + // DEPRECATED. disallow un-paren'd mixes of different operators + // https://eslint.org/docs/rules/no-mixed-operators + // "no-mixed-operators": [ + // "error", + // { + // // the list of arithmetic groups disallows mixing `%` and `**` + // // with other arithmetic operators. + // groups: [ + // ["%", "**"], + // ["%", "+"], + // ["%", "-"], + // ["%", "*"], + // ["%", "/"], + // ["/", "*"], + // ["&", "|", "<<", ">>", ">>>"], + // ["==", "!=", "===", "!=="], + // ["&&", "||"], + // ], + // allowSamePrecedence: false, + // }, + // ], + + // DEPRECATED. disallow mixed spaces and tabs for indentation + // "no-mixed-spaces-and-tabs": "error", + + // disallow use of chained assignment expressions + // https://eslint.org/docs/rules/no-multi-assign + "no-multi-assign": ["error"], + + // DEPRECATED. disallow multiple empty lines, only one newline at the end, and no new lines at the beginning + // https://eslint.org/docs/rules/no-multiple-empty-lines + // "no-multiple-empty-lines": ["error", { max: 1, maxBOF: 0, maxEOF: 0 }], + + // disallow nested ternary expressions + "no-nested-ternary": "error", + + // DEPRECATED. disallow use of the Object constructor + // "no-new-object": "error", + + // disallow certain syntax forms + // https://eslint.org/docs/rules/no-restricted-syntax + "no-restricted-syntax": [ + "error", + // { + // selector: "ForInStatement", + // message: + // "for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use for..of or Object.{keys,values,entries}, and iterate over the resulting array.", + // }, + { + selector: "LabeledStatement", + message: "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.", + }, + { + selector: "WithStatement", + message: "`with` is disallowed in strict mode because it makes code impossible to predict and optimize.", + }, + ], + + // DEPRECATED. disallow tab characters entirely + // "no-tabs": "error", + + // disallow dangling underscores in identifiers + // https://eslint.org/docs/rules/no-underscore-dangle + "no-underscore-dangle": [ + "error", + { + allow: [], + allowAfterThis: false, + allowAfterSuper: false, + enforceInMethodNames: true, + }, + ], + + // disallow the use of Boolean literals in conditional expressions + // also, prefer `a || b` over `a ? a : b` + // https://eslint.org/docs/rules/no-unneeded-ternary + "no-unneeded-ternary": ["error", { defaultAssignment: false }], + + // DEPRECATED. disallow whitespace before properties + // https://eslint.org/docs/rules/no-whitespace-before-property + // "no-whitespace-before-property": "error", + + // DEPRECATED. enforce the location of single-line statements + // https://eslint.org/docs/rules/nonblock-statement-body-position + // "nonblock-statement-body-position": ["error", "beside", { overrides: {} }], + + // DEPRECATED. require padding inside curly braces + // "object-curly-spacing": ["error", "always"], + + // DEPRECATED. enforce line breaks between braces + // https://eslint.org/docs/rules/object-curly-newline + // "object-curly-newline": [ + // "error", + // { + // ObjectExpression: { minProperties: 4, multiline: true, consistent: true }, + // ObjectPattern: { minProperties: 4, multiline: true, consistent: true }, + // ImportDeclaration: { minProperties: 4, multiline: true, consistent: true }, + // ExportDeclaration: { minProperties: 4, multiline: true, consistent: true }, + // }, + // ], + + // DEPRECATED. enforce "same line" or "multiple line" on object properties. + // https://eslint.org/docs/rules/object-property-newline + // "object-property-newline": [ + // "error", + // { + // allowAllPropertiesOnSameLine: true, + // }, + // ], + + // allow just one var statement per function + // https://eslint.org/docs/rules/one-var + "one-var": ["error", "never"], + + // DEPREACTED. require a newline around variable declaration + // https://eslint.org/docs/rules/one-var-declaration-per-line + // "one-var-declaration-per-line": ["error", "always"], + + // require assignment operator shorthand where possible or prohibit it entirely + // https://eslint.org/docs/rules/operator-assignment + "operator-assignment": ["error", "always"], + + // DEPRECATED. Requires operator at the beginning of the line in multiline statements + // https://eslint.org/docs/rules/operator-linebreak + // "operator-linebreak": ["error", "before", { overrides: { "=": "none" } }], + + // Disallow the use of Math.pow in favor of the ** operator + // https://eslint.org/docs/rules/prefer-exponentiation-operator + "prefer-exponentiation-operator": "error", + + // Prefer use of an object spread over Object.assign + // https://eslint.org/docs/rules/prefer-object-spread + "prefer-object-spread": "error", + + // DEPRECATED. require quotes around object literal property names + // https://eslint.org/docs/rules/quote-props.html + // "quote-props": ["error", "as-needed", { keywords: false, unnecessary: true, numbers: false }], + + // DEPRECATED. require or disallow use of semicolons instead of ASI + // semi: ["error", "always"], + + // DEPRECATED. require or disallow a space immediately following the // or /* in a comment + // https://eslint.org/docs/rules/spaced-comment + // "spaced-comment": [ + // "error", + // "always", + // { + // line: { + // exceptions: ["-", "+"], + // markers: ["=", "!", "/"], // space here to support sprockets directives, slash for TS /// comments + // }, + // block: { + // exceptions: ["-", "+"], + // markers: ["=", "!", ":", "::"], // space here to support sprockets directives and flow comment types + // balanced: true, + // }, + // }, + // ], + + // require or disallow the Unicode Byte Order Mark + // https://eslint.org/docs/rules/unicode-bom + "unicode-bom": ["error", "never"], +}; + +export default rules; diff --git a/packages/eslint-config/src/configs/rules/import-x.js b/packages/eslint-config/src/configs/rules/import-x.js new file mode 100644 index 0000000..06602f4 --- /dev/null +++ b/packages/eslint-config/src/configs/rules/import-x.js @@ -0,0 +1,159 @@ +// @ts-check + +/** + * @satisfies {import("../../types/index.js").ESLintFlatConfig["rules"]} + * + * eslint-plugin-import-x package https://github.com/un-ts/eslint-plugin-import-x/blob/master/README.md + */ +const rules = { + // modify rules from eslint-plugin-import-x here + /* -------------------------------------------------------------------------- */ + /* Static analysis: */ + /* -------------------------------------------------------------------------- */ + // ensure imports point to files/modules that can be resolved + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-unresolved.md + "import-x/no-unresolved": ["error", { commonjs: true, caseSensitive: true }], + // ensure named imports coupled with named exports + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/named.md#when-not-to-use-it + "import-x/named": "error", + /* -------------------------------------------------------------------------- */ + /* Helpful warnings: */ + /* -------------------------------------------------------------------------- */ + // disallow invalid exports, e.g. multiple defaults + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/export.md + "import-x/export": "error", + // do not allow a default import name to match a named export + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-named-as-default.md + "import-x/no-named-as-default": "error", + // warn on accessing default export property names that are also named exports + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-named-as-default-member.md + "import-x/no-named-as-default-member": "error", + // disallow use of jsdoc-marked-deprecated imports + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-deprecated.md + "import-x/no-deprecated": "warn", + + // Can depend on bundler setup, and other things. Disabling for now. + // Forbid the use of extraneous packages + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-extraneous-dependencies.md + // paths are treated both as absolute paths, and relative to process.cwd() + "import-x/no-extraneous-dependencies": [ + "off", + { + devDependencies: [ + "**/test*/**", + "**/mocks/**", + "**/mock/**", + "test/**", // tape, common npm pattern + "tests/**", // also common npm pattern + "spec/**", // mocha, rspec-like pattern + "**/__tests__/**", // jest pattern + "**/__mocks__/**", // jest pattern + "test.{js,jsx,ts,tsx}", // repos with a single test file + "test-*.{js,jsx,ts,tsx}", // repos with multiple top-level test files + "**/*{.,_}{test,spec}.{js,jsx,ts,tsx}", // tests where the extension or filename suffix denotes that it is a test + "**/jest.config.{cjs,mjs,js,ts}", // jest config + "**/jest.setup.{cjs,mjs,js,ts}", // jest setup + "**/vitest.config.{cjs,mjs,js,ts}", // vitest config + "**/vue.config.{cjs,mjs,js,ts}", // vue-cli config + "**/svelte.config.{cjs,mjs,js,ts}", // svelte config + "**/tsup.config.{cjs,mjs,js,ts}", // tsup config + "**/playwright.config.{cjs,mjs,js,ts}", // playwright config + "**/webpack.config.{cjs,mjs,js,ts}", // webpack config + "**/webpack.mod.{cjs,mjs,js,ts}", // webpack config + "**/rollup.config.{cjs,mjs,js,ts}", // rollup config + "**/rollup.config.*cjs,mjs,.{js,ts}", // rollup config + "**/protractor.conf.{cjs,mjs,js,ts}", // protractor config + "**/protractor.conf.*.{cjs,mjs,js,ts}", // protractor config + "**/.eslintrc.{cjs,mjs,js,ts}", // eslint config + "**/eslint.config.{cjs,mjs,js,ts}", // eslint config + "**/.prettierrc.{cjs,mjs,js,ts}", // prettier config + "**/.prettierrc", // prettier config + ], + optionalDependencies: false, + }, + ], + // Forbid mutable exports + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-mutable-exports.md + "import-x/no-mutable-exports": "error", + /* -------------------------------------------------------------------------- */ + /* Module systems: */ + /* -------------------------------------------------------------------------- */ + // disallow AMD require/define + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-amd.md + "import-x/no-amd": "error", + // No Node.js builtin modules + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-nodejs-modules.md + // TODO: enable? + "import-x/no-nodejs-modules": "off", + /* -------------------------------------------------------------------------- */ + /* Style guide: */ + /* -------------------------------------------------------------------------- */ + // disallow duplicate imports + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-duplicates.md + "import-x/no-duplicates": "error", + // Ensure consistent use of file extension within the import path + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/extensions.md + "import-x/extensions": [ + "error", + "ignorePackages", + { + js: "never", + mjs: "never", + jsx: "never", + ts: "never", + mts: "never", + tsx: "never", + }, + ], + // Require a newline after the last import-x/require in a group + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/newline-after-import.md + "import-x/newline-after-import": "error", + // Require modules with a single export to use a default export + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/prefer-default-export.md + "import-x/prefer-default-export": "off", + // Forbid import of modules using absolute paths + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-absolute-path.md + "import-x/no-absolute-path": "error", + // Forbid require() calls with expressions + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-dynamic-require.md + "import-x/no-dynamic-require": "error", + // Forbid Webpack loader syntax in imports + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-webpack-loader-syntax.md + "import-x/no-webpack-loader-syntax": "error", + // Prevent importing the default as if it were named + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-named-default.md + "import-x/no-named-default": "error", + // Forbid a module from importing itself + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-self-import.md + "import-x/no-self-import": "error", + // Forbid cyclical dependencies between modules + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-cycle.md + "import-x/no-cycle": ["error", { maxDepth: "∞" }], + // Ensures that there are no useless path segments + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-useless-path-segments.md + "import-x/no-useless-path-segments": ["error", { commonjs: true }], + // Reports modules without any exports, or with unused exports + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-unused-modules.md + "import-x/no-unused-modules": "error", + // Reports the use of import declarations with CommonJS exports in any module except for the main module. + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-import-module-exports.md + "import-x/no-import-module-exports": [ + "error", + { + exceptions: [], + }, + ], + // Use this rule to prevent importing packages through relative paths. + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-relative-packages-exports.md + "import-x/no-relative-packages": "error", + // This seems conflicting with @typescript-eslint/no-import-type-side-effects + // enforce a consistent style for type specifiers (inline or top-level) + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/consistent-type-specifier-style.md + "import-x/consistent-type-specifier-style": "off", + // Makes importing runtime (`import type {} from ...`) types annoying + // Reports the use of empty named import blocks. + // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-empty-named-blocks.md + "import-x/no-empty-named-blocks": "off", +}; + +export default rules; diff --git a/packages/eslint-config/src/configs/rules/index.js b/packages/eslint-config/src/configs/rules/index.js new file mode 100644 index 0000000..25b7f6a --- /dev/null +++ b/packages/eslint-config/src/configs/rules/index.js @@ -0,0 +1,17 @@ +import eslintCoreRules from "./eslint-core.js"; +import importXRules from "./import-x.js"; +import reactA11yRules from "./react-a11y.js"; +import reactHooksRules from "./react-hooks.js"; +import reactRules from "./react.js"; +import testingLibraryRules from "./testing-library.js"; +import typescriptRules from "./typescript.js"; + +export default { + importXRules, + eslintCoreRules, + typescriptRules, + reactRules, + reactA11yRules, + reactHooksRules, + testingLibraryRules, +}; diff --git a/packages/eslint-config/src/configs/rules/node.js b/packages/eslint-config/src/configs/rules/node.js new file mode 100644 index 0000000..d0f30f4 --- /dev/null +++ b/packages/eslint-config/src/configs/rules/node.js @@ -0,0 +1,10 @@ +// @ts-check + +/** + * @satisfies {import("../../types/index.js").ESLintFlatConfig["rules"]} + */ +const rules = { + // TODO use eslint-plugin-n https://github.com/eslint-community/eslint-plugin-n +}; + +export default rules; diff --git a/packages/eslint-config/src/configs/rules/react-a11y.js b/packages/eslint-config/src/configs/rules/react-a11y.js new file mode 100644 index 0000000..f388c5f --- /dev/null +++ b/packages/eslint-config/src/configs/rules/react-a11y.js @@ -0,0 +1,232 @@ +// @ts-check + +/** + * @satisfies {import("../../types/index.js").ESLintFlatConfig["rules"]} + */ +const rules = { + // Enforce that all elements that require alternative text have meaningful information + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/alt-text.md + "jsx-a11y/alt-text": [ + "error", + { + elements: ["img", "object", "area", 'input[type="image"]'], + img: [], + object: [], + area: [], + 'input[type="image"]': [], + }, + ], + + // Enforce that anchors have content + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-has-content.md + "jsx-a11y/anchor-has-content": ["error", { components: [] }], + + // ensure tags are valid + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/0745af376cdc8686d85a361ce36952b1fb1ccf6e/docs/rules/anchor-is-valid.md + "jsx-a11y/anchor-is-valid": [ + "error", + { + components: ["Link"], + specialLink: ["to"], + aspects: ["noHref", "invalidHref", "preferButton"], + }, + ], + + // elements with aria-activedescendant must be tabbable + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-activedescendant-has-tabindex.md + "jsx-a11y/aria-activedescendant-has-tabindex": "error", + + // Enforce all aria-* props are valid. + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-props.md + "jsx-a11y/aria-props": "error", + + // Enforce ARIA state and property values are valid. + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-proptypes.md + "jsx-a11y/aria-proptypes": "error", + + // Require ARIA roles to be valid and non-abstract + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-role.md + "jsx-a11y/aria-role": ["error", { ignoreNonDOM: false }], + + // Enforce that elements that do not support ARIA roles, states, and + // properties do not have those attributes. + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-unsupported-elements.md + "jsx-a11y/aria-unsupported-elements": "error", + + // require onClick be accompanied by onKeyUp/onKeyDown/onKeyPress + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/click-events-have-key-events.md + "jsx-a11y/click-events-have-key-events": "error", + + // Enforce that a control (an interactive element) has a text label. + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/control-has-associated-label.md + "jsx-a11y/control-has-associated-label": [ + "error", + { + labelAttributes: ["label"], + controlComponents: [], + ignoreElements: ["audio", "canvas", "embed", "input", "textarea", "tr", "video"], + ignoreRoles: [ + "grid", + "listbox", + "menu", + "menubar", + "radiogroup", + "row", + "tablist", + "toolbar", + "tree", + "treegrid", + ], + depth: 5, + }, + ], + + // ensure tags have content and are not aria-hidden + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/heading-has-content.md + "jsx-a11y/heading-has-content": ["error", { components: [""] }], + + // require HTML elements to have a "lang" prop + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/html-has-lang.md + "jsx-a11y/html-has-lang": "error", + + // ensure iframe elements have a unique title + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/iframe-has-title.md + "jsx-a11y/iframe-has-title": "error", + + // Prevent img alt text from containing redundant words like "image", "picture", or "photo" + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/img-redundant-alt.md + "jsx-a11y/img-redundant-alt": "error", + + // Elements with an interactive role and interaction handlers must be focusable + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/interactive-supports-focus.md + "jsx-a11y/interactive-supports-focus": "error", + + // Enforce that a label tag has a text label and an associated control. + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/b800f40a2a69ad48015ae9226fbe879f946757ed/docs/rules/label-has-associated-control.md + "jsx-a11y/label-has-associated-control": [ + "error", + { + labelComponents: [], + labelAttributes: [], + controlComponents: [], + assert: "both", + depth: 25, + }, + ], + + // require HTML element's lang prop to be valid + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/lang.md + "jsx-a11y/lang": "error", + + // media elements must have captions + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/media-has-caption.md + "jsx-a11y/media-has-caption": [ + "error", + { + audio: [], + video: [], + track: [], + }, + ], + + // require that mouseover/out come with focus/blur, for keyboard-only users + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/mouse-events-have-key-events.md + "jsx-a11y/mouse-events-have-key-events": "error", + + // Prevent use of `accessKey` + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-access-key.md + "jsx-a11y/no-access-key": "error", + + // prohibit autoFocus prop + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-autofocus.md + "jsx-a11y/no-autofocus": ["error", { ignoreNonDOM: true }], + + // prevent distracting elements, like and + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-distracting-elements.md + "jsx-a11y/no-distracting-elements": [ + "error", + { + elements: ["marquee", "blink"], + }, + ], + + // WAI-ARIA roles should not be used to convert an interactive element to non-interactive + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-interactive-element-to-noninteractive-role.md + "jsx-a11y/no-interactive-element-to-noninteractive-role": [ + "error", + { + tr: ["none", "presentation"], + }, + ], + + // A non-interactive element does not support event handlers (mouse and key handlers) + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-element-interactions.md + "jsx-a11y/no-noninteractive-element-interactions": [ + "error", + { + handlers: ["onClick", "onMouseDown", "onMouseUp", "onKeyPress", "onKeyDown", "onKeyUp"], + }, + ], + + // WAI-ARIA roles should not be used to convert a non-interactive element to interactive + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-element-to-interactive-role.md + "jsx-a11y/no-noninteractive-element-to-interactive-role": [ + "error", + { + ul: ["listbox", "menu", "menubar", "radiogroup", "tablist", "tree", "treegrid"], + ol: ["listbox", "menu", "menubar", "radiogroup", "tablist", "tree", "treegrid"], + li: ["menuitem", "option", "row", "tab", "treeitem"], + table: ["grid"], + td: ["gridcell"], + }, + ], + + // Tab key navigation should be limited to elements on the page that can be interacted with. + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-tabindex.md + "jsx-a11y/no-noninteractive-tabindex": [ + "error", + { + tags: [], + roles: ["tabpanel"], + allowExpressionValues: true, + }, + ], + + // ensure HTML elements do not specify redundant ARIA roles + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-redundant-roles.md + "jsx-a11y/no-redundant-roles": [ + "error", + { + nav: ["navigation"], + }, + ], + + // Enforce that DOM elements without semantic behavior not have interaction handlers + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-static-element-interactions.md + "jsx-a11y/no-static-element-interactions": [ + "error", + { + handlers: ["onClick", "onMouseDown", "onMouseUp", "onKeyPress", "onKeyDown", "onKeyUp"], + }, + ], + + // Enforce that elements with ARIA roles must have all required attributes + // for that role. + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-has-required-aria-props.md + "jsx-a11y/role-has-required-aria-props": "error", + + // Enforce that elements with explicit or implicit roles defined contain + // only aria-* properties supported by that role. + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-supports-aria-props.md + "jsx-a11y/role-supports-aria-props": "error", + + // only allow to have the "scope" attr + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/scope.md + "jsx-a11y/scope": "error", + + // Enforce tabIndex value is not greater than zero. + // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/tabindex-no-positive.md + "jsx-a11y/tabindex-no-positive": "error", +}; + +export default rules; diff --git a/packages/eslint-config/src/configs/rules/react-hooks.js b/packages/eslint-config/src/configs/rules/react-hooks.js new file mode 100644 index 0000000..c2e7424 --- /dev/null +++ b/packages/eslint-config/src/configs/rules/react-hooks.js @@ -0,0 +1,16 @@ +// @ts-check + +/** + * @satisfies {import("../../types/index.js").ESLintFlatConfig["rules"]} + */ +const rules = { + // Enforce Rules of Hooks + // https://github.com/facebook/react/blob/c11015ff4f610ac2924d1fc6d569a17657a404fd/packages/eslint-plugin-react-hooks/src/RulesOfHooks.js + "react-hooks/rules-of-hooks": "error", + + // Verify the list of the dependencies for Hooks like useEffect and similar + // https://github.com/facebook/react/blob/1204c789776cb01fbaf3e9f032e7e2ba85a44137/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js + "react-hooks/exhaustive-deps": "error", +}; + +export default rules; diff --git a/packages/eslint-config/src/configs/rules/react.js b/packages/eslint-config/src/configs/rules/react.js new file mode 100644 index 0000000..4fd23e5 --- /dev/null +++ b/packages/eslint-config/src/configs/rules/react.js @@ -0,0 +1,479 @@ +// @ts-check + +/** + * @satisfies {import("../../types/index.js").ESLintFlatConfig["rules"]} + */ +const rules = { + "class-methods-use-this": [ + "warn", + { + exceptMethods: [ + "render", + "getInitialState", + "getDefaultProps", + "getChildContext", + "componentWillMount", + "UNSAFE_componentWillMount", + "componentDidMount", + "componentWillReceiveProps", + "UNSAFE_componentWillReceiveProps", + "shouldComponentUpdate", + "componentWillUpdate", + "UNSAFE_componentWillUpdate", + "componentDidUpdate", + "componentWillUnmount", + "componentDidCatch", + "getSnapshotBeforeUpdate", + ], + }, + ], + + // Forbid certain propTypes (any, array, object) + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/forbid-prop-types.md + "react/forbid-prop-types": [ + "error", + { + forbid: ["any", "array", "object"], + checkContextTypes: true, + checkChildContextTypes: true, + }, + ], + + // Enforce boolean attributes notation in JSX + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md + "react/jsx-boolean-value": ["error", "never", { always: [] }], + + // Validate closing bracket location in JSX + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-closing-bracket-location.md + "react/jsx-closing-bracket-location": ["error", "line-aligned"], + + // Validate closing tag location in JSX + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-closing-tag-location.md + "react/jsx-closing-tag-location": "error", + + // Enforce or disallow spaces inside of curly braces in JSX attributes + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-curly-spacing.md + "react/jsx-curly-spacing": ["error", "never", { allowMultiline: true }], + + // Validate props indentation in JSX + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-indent-props.md + "react/jsx-indent-props": ["error", 2], + + // Limit maximum of props on a single line in JSX + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-max-props-per-line.md + "react/jsx-max-props-per-line": ["error", { maximum: 1, when: "multiline" }], + + // Prevent usage of .bind() in JSX props + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md + "react/jsx-no-bind": [ + "error", + { + ignoreRefs: true, + allowArrowFunctions: true, + allowFunctions: false, + allowBind: false, + ignoreDOMComponents: true, + }, + ], + + // Prevent duplicate props in JSX + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-no-duplicate-props.md + "react/jsx-no-duplicate-props": ["error", { ignoreCase: true }], + + // Disallow undeclared variables in JSX + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-no-undef.md + "react/jsx-no-undef": "error", + + // Enforce PascalCase for user-defined JSX components + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-pascal-case.md + "react/jsx-pascal-case": [ + "error", + { + allowAllCaps: true, + ignore: [], + }, + ], + + // Prevent React to be incorrectly marked as unused + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-uses-react.md + "react/jsx-uses-react": "off", + + // Prevent variables used in JSX to be incorrectly marked as unused + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-uses-vars.md + "react/jsx-uses-vars": "error", + + // Prevent usage of dangerous JSX properties + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-danger.md + "react/no-danger": "warn", + + // Prevent usage of deprecated methods + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-deprecated.md + "react/no-deprecated": ["error"], + + // Prevent usage of setState in componentDidUpdate + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-did-update-set-state.md + "react/no-did-update-set-state": "error", + + // Prevent usage of setState in componentWillUpdate + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-will-update-set-state.md + "react/no-will-update-set-state": "error", + + // Prevent usage of isMounted + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-is-mounted.md + "react/no-is-mounted": "error", + + // Prevent using string references + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-string-refs.md + "react/no-string-refs": "error", + + // Prevent usage of unknown DOM property + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-unknown-property.md + "react/no-unknown-property": "error", + + // Require ES6 class declarations over React.createClass + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/prefer-es6-class.md + "react/prefer-es6-class": ["error", "always"], + + // Require stateless functions when not using lifecycle methods, setState or ref + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/prefer-stateless-function.md + "react/prefer-stateless-function": ["error", { ignorePureComponents: true }], + + // Prevent missing props validation in a React component definition + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/prop-types.md + "react/prop-types": [ + "error", + { + ignore: [], + customValidators: [], + skipUndeclared: false, + }, + ], + + // Prevent missing React when using JSX + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/react-in-jsx-scope.md + "react/react-in-jsx-scope": "off", + + // Require render() methods to return something + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/require-render-return.md + "react/require-render-return": "error", + + // Prevent extra closing tags for components without children + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/self-closing-comp.md + "react/self-closing-comp": "error", + + // Enforce component methods order + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/sort-comp.md + "react/sort-comp": [ + "error", + { + order: [ + "static-variables", + "static-methods", + "instance-variables", + "lifecycle", + "/^handle.+$/", + "/^on.+$/", + "getters", + "setters", + "/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/", + "instance-methods", + "everything-else", + "rendering", + ], + groups: { + lifecycle: [ + "displayName", + "propTypes", + "contextTypes", + "childContextTypes", + "mixins", + "statics", + "defaultProps", + "constructor", + "getDefaultProps", + "getInitialState", + "state", + "getChildContext", + "getDerivedStateFromProps", + "componentWillMount", + "UNSAFE_componentWillMount", + "componentDidMount", + "componentWillReceiveProps", + "UNSAFE_componentWillReceiveProps", + "shouldComponentUpdate", + "componentWillUpdate", + "UNSAFE_componentWillUpdate", + "getSnapshotBeforeUpdate", + "componentDidUpdate", + "componentDidCatch", + "componentWillUnmount", + ], + rendering: ["/^render.+$/", "render"], + }, + }, + ], + + // Prevent missing parentheses around multilines JSX + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-wrap-multilines.md + "react/jsx-wrap-multilines": [ + "error", + { + declaration: "parens-new-line", + assignment: "parens-new-line", + return: "parens-new-line", + arrow: "parens-new-line", + condition: "parens-new-line", + logical: "parens-new-line", + prop: "ignore", + }, + ], + + // Require that the first prop in a JSX element be on a new line when the element is multiline + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-first-prop-new-line.md + "react/jsx-first-prop-new-line": ["error", "multiline-multiprop"], + + // Stylistic, Prettier handles this. + // Enforce spacing around jsx equals signs + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-equals-spacing.md + "react/jsx-equals-spacing": "off", + + // Stylistic, Prettier handles this. + // Enforce JSX indentation + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-indent.md + "react/jsx-indent": "off", + + // Disallow target="_blank" on links + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-no-target-blank.md + "react/jsx-no-target-blank": ["error", { enforceDynamicLinks: "always" }], + + // only .jsx files may have JSX + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-filename-extension.md + "react/jsx-filename-extension": ["error", { extensions: [".jsx"] }], + + // prevent accidental JS comments from being injected into JSX as text + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-no-comment-textnodes.md + "react/jsx-no-comment-textnodes": "error", + + // disallow using React.render/ReactDOM.render's return value + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-render-return-value.md + "react/no-render-return-value": "error", + + // warn against using findDOMNode() + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-find-dom-node.md + "react/no-find-dom-node": "error", + + // Prevent problem with children and props.dangerouslySetInnerHTML + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-danger-with-children.md + "react/no-danger-with-children": "error", + + // Prevent unused propType definitions + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-unused-prop-types.md + "react/no-unused-prop-types": [ + "error", + { + customValidators: [], + skipShapeProps: true, + }, + ], + + // Require style prop value be an object or var + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/style-prop-object.md + "react/style-prop-object": "error", + + // Prevent invalid characters from appearing in markup + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-unescaped-entities.md + "react/no-unescaped-entities": "error", + + // Prevent passing of children as props + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-children-prop.md + "react/no-children-prop": "error", + + // Validate whitespace in and around the JSX opening and closing brackets + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-tag-spacing.md + "react/jsx-tag-spacing": [ + "error", + { + closingSlash: "never", + beforeSelfClosing: "always", + afterOpening: "never", + beforeClosing: "never", + }, + ], + + // Prevent usage of Array index in keys + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-array-index-key.md + "react/no-array-index-key": "error", + + // We dont use `.defaultProps` any more, we use fallbacks on props (`{ foo = "bar" }`) + // Enforce a defaultProps definition for every prop that is not a required prop + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/require-default-props.md + "react/require-default-props": "off", + + // Forbids using non-exported propTypes + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/forbid-foreign-prop-types.md + // this is intentionally set to "warn". it would be "error", + // but it's only critical if you're stripping propTypes in production. + "react/forbid-foreign-prop-types": ["warn", { allowInPropTypes: true }], + + // Prevent void DOM elements from receiving children + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/void-dom-elements-no-children.md + "react/void-dom-elements-no-children": "error", + + // Enforce all defaultProps have a corresponding non-required PropType + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/default-props-match-prop-types.md + "react/default-props-match-prop-types": ["error", { allowRequiredDefaults: false }], + + // Prevent usage of shouldComponentUpdate when extending React.PureComponent + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-redundant-should-component-update.md + "react/no-redundant-should-component-update": "error", + + // Prevent unused state values + // https://github.com/jsx-eslint/eslint-plugin-react/pull/1103/ + "react/no-unused-state": "error", + + // Prevents common casing typos + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-typos.md + "react/no-typos": "error", + + // Enforce curly braces or disallow unnecessary curly braces in JSX props and/or children + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-curly-brace-presence.md + "react/jsx-curly-brace-presence": ["error", { props: "never", children: "never" }], + + // Stylistic, Prettier handles this. + // One JSX Element Per Line + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-one-expression-per-line.md + "react/jsx-one-expression-per-line": "off", + + // Enforce consistent usage of destructuring assignment of props, state, and context + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/destructuring-assignment.md + "react/destructuring-assignment": ["error", "always"], + + // Prevent using this.state within a this.setState + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-access-state-in-setstate.md + "react/no-access-state-in-setstate": "error", + + // Prevent usage of button elements without an explicit type attribute + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/button-has-type.md + "react/button-has-type": [ + "error", + { + button: true, + submit: true, + reset: false, + }, + ], + + // Prevent this from being used in stateless functional components + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-this-in-sfc.md + "react/no-this-in-sfc": "error", + + // Disallow multiple spaces between inline JSX props + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-props-no-multi-spaces.md + "react/jsx-props-no-multi-spaces": "error", + + // Enforce shorthand or standard form for React fragments + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-fragments.md + "react/jsx-fragments": ["error", "syntax"], + + // Enforce linebreaks in curly braces in JSX attributes and expressions. + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-curly-newline.md + "react/jsx-curly-newline": [ + "error", + { + multiline: "consistent", + singleline: "consistent", + }, + ], + + // Enforce state initialization style + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/state-in-constructor.md + // TODO: set to "never" once babel-preset-airbnb supports public class fields + "react/state-in-constructor": ["error", "always"], + + // Enforces where React component static properties should be positioned + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/static-property-placement.md + // TODO: set to "static public field" once babel-preset-airbnb supports public class fields + "react/static-property-placement": ["error", "property assignment"], + + // This has valid cases but best practice to be explicit about the props + // Disallow JSX props spreading + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-props-no-spreading.md + "react/jsx-props-no-spreading": [ + "off", + { + html: "enforce", + custom: "enforce", + explicitSpread: "ignore", + exceptions: [], + }, + ], + + // Prevent usage of `javascript:` URLs + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-no-script-url.md + "react/jsx-no-script-url": [ + "error", + [ + { + name: "Link", + props: ["to"], + }, + ], + ], + + // Disallow unnecessary fragments + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-no-useless-fragment.md + "react/jsx-no-useless-fragment": "error", + + // Stylistic rule + // Enforce a specific function type for function components + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/function-component-definition.md + "react/function-component-definition": "off", + + // Prevent react contexts from taking non-stable values + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-no-constructed-context-values.md + "react/jsx-no-constructed-context-values": "error", + + // Prevent creating unstable components inside components + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-unstable-nested-components.md + "react/no-unstable-nested-components": "error", + + // Enforce that namespaces are not used in React elements + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-namespace.md + "react/no-namespace": "error", + + // Prefer exact proptype definitions + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/prefer-exact-props.md + "react/prefer-exact-props": "error", + + // Lifecycle methods should be methods on the prototype, not class fields + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-arrow-function-lifecycle.md + "react/no-arrow-function-lifecycle": "error", + + // Prevent usage of invalid attributes + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-invalid-html-attribute.md + "react/no-invalid-html-attribute": "error", + + // Prevent declaring unused methods of component class + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-unused-class-component-methods.md + "react/no-unused-class-component-methods": "error", + + // Ensure destructuring and symmetric naming of useState hook value and setter variables + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/hook-use-state.md + "react/hook-use-state": "error", + + // Prevent problematic leaked values from being rendered + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-no-leaked-render.md + "react/jsx-no-leaked-render": "error", + + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-object-type-as-default-prop.md + + "react/no-object-type-as-default-prop": "error", + + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/forward-ref-uses-ref.md + "react/forward-ref-uses-ref": "error", + + // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-props-no-spread-multi.md + "react/jsx-props-no-spread-multi": "error", +}; + +export default rules; diff --git a/packages/eslint-config/src/configs/rules/svelte.js b/packages/eslint-config/src/configs/rules/svelte.js new file mode 100644 index 0000000..b7d968b --- /dev/null +++ b/packages/eslint-config/src/configs/rules/svelte.js @@ -0,0 +1,11 @@ +// @ts-check + +/** + * @satisfies {import("../../types/index.js").ESLintFlatConfig["rules"]} + * Svelte plugin https://sveltejs.github.io/eslint-plugin-svelte/rules/ + */ +const rules = { + // Override rules here +}; + +export default rules; diff --git a/packages/eslint-config/src/configs/rules/testing-library.js b/packages/eslint-config/src/configs/rules/testing-library.js new file mode 100644 index 0000000..fa476d3 --- /dev/null +++ b/packages/eslint-config/src/configs/rules/testing-library.js @@ -0,0 +1,74 @@ +// @ts-check + +/** + * @satisfies {import("../../types/index.js").ESLintFlatConfig["rules"]} + */ +const rules = { + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/await-async-events.md + "testing-library/await-async-events": ["error", { eventModule: "userEvent" }], + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/await-async-queries.md + "testing-library/await-async-queries": "error", + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/await-async-utils.md + "testing-library/await-async-utils": "error", + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-await-sync-events.md + "testing-library/no-await-sync-events": ["error", { eventModules: ["fire-event"] }], + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-await-sync-queries.md + "testing-library/no-await-sync-queries": "error", + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-container.md + "testing-library/no-container": "error", + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-debugging-utils.md + "testing-library/no-debugging-utils": "warn", + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-dom-import.md + "testing-library/no-dom-import": ["error", "react"], + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-global-regexp-flag-in-query.md + "testing-library/no-global-regexp-flag-in-query": "error", + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-manual-cleanup.md + "testing-library/no-manual-cleanup": "error", + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-node-access.md + "testing-library/no-node-access": "error", + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-promise-in-fire-event.md + "testing-library/no-promise-in-fire-event": "error", + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-render-in-lifecycle.md + "testing-library/no-render-in-lifecycle": "error", + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-unnecessary-act.md + "testing-library/no-unnecessary-act": "error", + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-wait-for-multiple-assertions.md + "testing-library/no-wait-for-multiple-assertions": "error", + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-wait-for-side-effects.md + "testing-library/no-wait-for-side-effects": "error", + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-wait-for-snapshot.md + "testing-library/no-wait-for-snapshot": "error", + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/prefer-find-by.md + "testing-library/prefer-find-by": "error", + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/prefer-presence-queries.md + "testing-library/prefer-presence-queries": "error", + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/prefer-query-by-disappearance.md + "testing-library/prefer-query-by-disappearance": "error", + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/prefer-screen-queries.md + "testing-library/prefer-screen-queries": "error", + + // https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/render-result-naming-convention.md + "testing-library/render-result-naming-convention": "error", +}; + +export default rules; diff --git a/packages/eslint-config/src/configs/rules/typescript.js b/packages/eslint-config/src/configs/rules/typescript.js new file mode 100644 index 0000000..3a669d1 --- /dev/null +++ b/packages/eslint-config/src/configs/rules/typescript.js @@ -0,0 +1,228 @@ +// @ts-check +import eslintCoreRules from "./eslint-core.js"; + +/** + * @satisfies {import("../../types/index.js").ESLintFlatConfig["rules"]} + * + * typescript-eslint package https://typescript-eslint.io/rules/ + */ +const rules = { + // note some eslint core rules are disabled by tsconfig https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/configs/eslint-recommended-raw.ts + + // class methods don't have to use this, but should maybe be turned into static methods + // https://typescript-eslint.io/rules/class-methods-use-this + "class-methods-use-this": "off", + "@typescript-eslint/class-methods-use-this": eslintCoreRules["class-methods-use-this"], + + // enforce consistent type imports + // https://typescript-eslint.io/rules/consistent-type-imports + "@typescript-eslint/consistent-type-imports": "error", + + // enforce default parameters to be last + // https://typescript-eslint.io/rules/default-param-last + "default-param-last": "off", + "@typescript-eslint/default-param-last": eslintCoreRules["default-param-last"], + + // enforce exported functions to have return types + // https://typescript-eslint.io/rules/explicit-module-boundary-types + "@typescript-eslint/explicit-module-boundary-types": "off", + + // enforce method signatures has the same style + // https://typescript-eslint.io/rules/method-signature-style + "@typescript-eslint/method-signature-style": "error", + + // don't use the delete operator on dynamic properties + // https://typescript-eslint.io/rules/no-dynamic-delete + "@typescript-eslint/no-dynamic-delete": "error", + + // don't have classes with only static members + // https://typescript-eslint.io/rules/no-extraneous-class + "@typescript-eslint/no-extraneous-class": "error", + + // use top-level type imports + // https://typescript-eslint.io/rules/no-import-type-side-effects + "@typescript-eslint/no-import-type-side-effects": "error", + + // don't use void where it shouldn't be used + // https://typescript-eslint.io/rules/no-invalid-void-type + "@typescript-eslint/no-invalid-void-type": "error", + + // don't do weird things in loops + // https://typescript-eslint.io/rules/no-loop-func + "no-loop-func": "off", + "@typescript-eslint/no-loop-func": eslintCoreRules["no-loop-func"], + + // no magic numbers please + // https://typescript-eslint.io/rules/no-magic-numbers + "no-magic-numbers": "off", + "@typescript-eslint/no-magic-numbers": eslintCoreRules["no-magic-numbers"], + + // disallow non-null assertions in the left operand of a nullish coalescing operator. + // https://typescript-eslint.io/rules/no-non-null-asserted-nullish-coalescing + "@typescript-eslint/no-non-null-asserted-nullish-coalescing": "error", + + // https://typescript-eslint.io/rules/no-non-null-assertion + "@typescript-eslint/no-non-null-assertion": "error", + + // don't allow redeclaration of variables + // https://typescript-eslint.io/rules/no-redeclare + "no-redeclare": "off", + "@typescript-eslint/no-redeclare": eslintCoreRules["no-redeclare"], + + // add forbidden imports if needed + // https://typescript-eslint.io/rules/no-restricted-imports + "no-restricted-imports": "off", + "@typescript-eslint/no-restricted-imports": eslintCoreRules["no-restricted-imports"], + + // add forbidden types if needed + // https://typescript-eslint.io/rules/no-restricted-types + "@typescript-eslint/no-restricted-types": ["error", {}], + + // shadows from outer scopes are not allowed + // https://typescript-eslint.io/rules/no-shadow + "no-shadow": "off", + "@typescript-eslint/no-shadow": eslintCoreRules["no-shadow"], + + // no unnecessary assignment of constructor property parameter. + // https://typescript-eslint.io/rules/no-unnecessary-parameter-property-assignment + "@typescript-eslint/no-unnecessary-parameter-property-assignment": "error", + + // don't use stuff that hasn't been defined + // https://typescript-eslint.io/rules/no-useless-constructor + "no-useless-constructor": "off", + "@typescript-eslint/no-useless-constructor": eslintCoreRules["no-useless-constructor"], + + // useless exports can be removed + // https://typescript-eslint.io/rules/no-useless-empty-export + "@typescript-eslint/no-useless-empty-export": "error", + + // yes, please initialize your enums + // https://typescript-eslint.io/rules/prefer-enum-initializers + "@typescript-eslint/prefer-enum-initializers": "error", + + // allow classic for loops + // https://typescript-eslint.io/rules/prefer-for-of + "@typescript-eslint/prefer-for-of": "off", + + // enums are not based on dynamic values + // https://typescript-eslint.io/rules/prefer-literal-enum-member + "@typescript-eslint/prefer-literal-enum-member": "error", + + // disallow two overloads that could be unified into one with a union or an optional/rest parameter. + // https://typescript-eslint.io/rules/unified-signatures + "@typescript-eslint/unified-signatures": "error", + + // enforce explicityly set type exports + // https://typescript-eslint.io/rules/consistent-type-exports + "@typescript-eslint/consistent-type-exports": "error", + + // void should not be assigned to variables + // https://typescript-eslint.io/rules/no-confusing-void-expression + "@typescript-eslint/no-confusing-void-expression": "error", + + // https://typescript-eslint.io/rules/no-floating-promises + "@typescript-eslint/no-floating-promises": [ + "error", + { + ignoreIIFE: true, + }, + ], + + // remove void when it's not needed + // https://typescript-eslint.io/rules/no-meaningless-void-operator + "@typescript-eslint/no-meaningless-void-operator": "error", + + // https://typescript-eslint.io/rules/no-misused-promises + "@typescript-eslint/no-misused-promises": [ + "error", + { + checksConditionals: false, + }, + ], + + // use constistent enum types + // https://typescript-eslint.io/rules/no-mixed-enums + "@typescript-eslint/no-mixed-enums": "error", + + // don't do silly comparisons + // https://typescript-eslint.io/rules/no-unnecessary-boolean-literal-compare + "@typescript-eslint/no-unnecessary-boolean-literal-compare": "error", + + // Lots of false/iffy positives + // watch out for always truthy conditions + // https://typescript-eslint.io/rules/no-unnecessary-condition + "@typescript-eslint/no-unnecessary-condition": "off", + + // no unnecessary namespace qualifiers. + // https://typescript-eslint.io/rules/no-unnecessary-qualifier + "@typescript-eslint/no-unnecessary-qualifier": "error", + + // no need for template literals if they just refer to a string + // https://typescript-eslint.io/rules/no-unnecessary-template-expression + "@typescript-eslint/no-unnecessary-template-expression": "error", + + // don't use type arguments when they're not needed + // https://typescript-eslint.io/rules/no-unnecessary-type-arguments + "@typescript-eslint/no-unnecessary-type-arguments": "error", + + // Not working 100% + // don't use type parameters when they're not needed + // https://typescript-eslint.io/rules/no-unnecessary-type-parameters + "@typescript-eslint/no-unnecessary-type-parameters": "off", + + // reducers should be typed correctly + // https://typescript-eslint.io/rules/prefer-reduce-type-parameter + "@typescript-eslint/prefer-reduce-type-parameter": "error", + + // https://typescript-eslint.io/rules/prefer-return-this-type + "@typescript-eslint/prefer-return-this-type": "error", + + // https://typescript-eslint.io/rules/ban-ts-comment + "@typescript-eslint/ban-ts-comment": "error", + + // https://typescript-eslint.io/rules/require-array-sort-compare + "@typescript-eslint/require-array-sort-compare": "error", + + // not sure about this one + // https://typescript-eslint.io/rules/return-await + "no-return-await": "off", + "@typescript-eslint/return-await": "error", + + // Not sure about this one + // disallow certain types in boolean expressions. + // https://typescript-eslint.io/rules/strict-boolean-expressions + "@typescript-eslint/strict-boolean-expressions": "off", + + // make sure switch statements are exhaustive + // https://typescript-eslint.io/rules/switch-exhaustiveness-check + "@typescript-eslint/switch-exhaustiveness-check": "error", + + // enforce typing arguments in Promise rejection callbacks as unknown + // https://typescript-eslint.io/rules/use-unknown-in-catch-callback-variable + "@typescript-eslint/use-unknown-in-catch-callback-variable": "error", + + // Replace Airbnb 'camelcase' rule with '@typescript-eslint/naming-convention' + // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/naming-convention.md + camelcase: "off", + // The `@typescript-eslint/naming-convention` rule allows `leadingUnderscore` and `trailingUnderscore` settings. However, the existing `no-underscore-dangle` rule already takes care of this. + "@typescript-eslint/naming-convention": [ + "error", + // Allow camelCase variables (23.2), PascalCase variables (23.8), and UPPER_CASE variables (23.10) + { + selector: "variable", + format: ["camelCase", "PascalCase", "UPPER_CASE"], + }, + // Allow camelCase functions (23.2), and PascalCase functions (23.8) + { + selector: "function", + format: ["camelCase", "PascalCase"], + }, + // Airbnb recommends PascalCase for classes (23.3), and although Airbnb does not make TypeScript recommendations, we are assuming this rule would similarly apply to anything "type like", including interfaces, type aliases, and enums + { + selector: "typeLike", + format: ["PascalCase"], + }, + ], +}; + +export default rules; diff --git a/packages/eslint-config/src/configs/svelte.js b/packages/eslint-config/src/configs/svelte.js new file mode 100644 index 0000000..b8a362d --- /dev/null +++ b/packages/eslint-config/src/configs/svelte.js @@ -0,0 +1,48 @@ +// @ts-check +import eslintPluginSvelte from "eslint-plugin-svelte"; +import svelteParser from "svelte-eslint-parser"; +import tsEslint from "typescript-eslint"; +import { mergeConfigs } from "../utils/config.js"; +import { recommendedJS, recommendedTS } from "./recommended.js"; +import rules from "./rules/svelte.js"; + +/** + * @type {import("../types/index.js").ESLintFlatConfig} + * config for Svelte https://github.com/sveltejs/eslint-plugin-svelte + */ +const svelte = mergeConfigs(...eslintPluginSvelte.configs["flat/recommended"], { + name: "svelte", + files: ["**/*.svelte"], + languageOptions: { + parser: svelteParser, + parserOptions: { + parser: tsEslint.parser, + extraFileExtensions: [".svelte"], + }, + }, + rules: { + ...rules, + // modify rules from eslint-plugin-svelte here + + // Conflicting rules + // https://github.com/sveltejs/eslint-plugin-svelte3/blob/master/OTHER_PLUGINS.md + "import-x/first": "off", + "import-x/no-duplicates": "off", + "import-x/no-mutable-exports": "off", + "import-x/no-unresolved": "off", + "import-x/prefer-default-export": "off", + "import-x/extensions": "off", + + "@typescript-eslint/no-unsafe-call": "off", + "@typescript-eslint/no-unsafe-return": "off", + "@typescript-eslint/no-unsafe-argument": "off", + "@typescript-eslint/no-unsafe-assignment": "off", + "@typescript-eslint/no-unsafe-member-access": "off", + + // Issues with function types that define parameters + "no-unused-vars": "off", + }, +}); + +export default [recommendedJS, recommendedTS, svelte]; +export { svelte }; diff --git a/packages/eslint-config/src/configs/vitest.js b/packages/eslint-config/src/configs/vitest.js new file mode 100644 index 0000000..ac6ba0c --- /dev/null +++ b/packages/eslint-config/src/configs/vitest.js @@ -0,0 +1,36 @@ +// @ts-check +import vitestPlugin from "@vitest/eslint-plugin"; +// @ts-expect-error no types yet +import testingLibraryPlugin from "eslint-plugin-testing-library"; +import { mergeConfigs } from "../utils/config.js"; +import rules from "./rules/index.js"; + +/** + * @satisfies {import("../types/index.js").ESLintFlatConfig["rules"]} + */ +const vitestCommon = {}; + +/** + * @type {import("../types/index.js").ESLintFlatConfig} + * config for jest https://github.com/jest-community/eslint-plugin-jest + */ +const vitest = mergeConfigs(vitestCommon, { + name: "vitest-js", + plugins: { + vitest: vitestPlugin, + "testing-library": testingLibraryPlugin, + }, + + files: ["**/__test__/**/*.{js,jsx,ts,tsx}", "**/__tests__/**/*.{js,jsx,ts,tsx}"], + + rules: { + // modify rules from eslint-plugin-vitest here + ...vitestPlugin.configs.recommended.rules, // you can also use vitest.configs.all.rules to enable all rules + ...rules.testingLibraryRules, + "no-magic-numbers": "off", + "@typescript-eslint/no-magic-numbers": "off", + }, +}); + +export default [vitest]; +export { vitest }; diff --git a/packages/eslint-config/src/index.d.ts b/packages/eslint-config/src/index.d.ts new file mode 100644 index 0000000..54de5cc --- /dev/null +++ b/packages/eslint-config/src/index.d.ts @@ -0,0 +1,24 @@ +export default qlikEslintConfig; + +declare namespace qlikEslintConfig { + export namespace configs { + export { cjs }; + export { esm }; + export { playwright }; + export { jest }; + export { react }; + export { recommended }; + export { svelte }; + export { vitest }; + } + export { compose }; +} +import cjs from "./configs/cjs.js"; +import esm from "./configs/esm.js"; +import jest from "./configs/jest.js"; +import playwright from "./configs/playwright.js"; +import react from "./configs/react.js"; +import recommended from "./configs/recommended.js"; +import svelte from "./configs/svelte.js"; +import vitest from "./configs/vitest.js"; +import compose from "./utils/compose.js"; diff --git a/packages/eslint-config/src/index.js b/packages/eslint-config/src/index.js new file mode 100644 index 0000000..456a15b --- /dev/null +++ b/packages/eslint-config/src/index.js @@ -0,0 +1,29 @@ +// Import ESLint configuration modules +import cjs from "./configs/cjs.js"; +import esm from "./configs/esm.js"; +import jest from "./configs/jest.js"; +import playwright from "./configs/playwright.js"; +import react from "./configs/react.js"; +import recommended from "./configs/recommended.js"; +import svelte from "./configs/svelte.js"; +import vitest from "./configs/vitest.js"; +import compose from "./utils/compose.js"; + +/** + * @satisfies {import("./types/index.js").QlikEslintConfig} + */ +const qlikEslintConfig = { + configs: { + cjs, + esm, + jest, + playwright, + react, + recommended, + svelte, + vitest, + }, + compose, +}; + +export default qlikEslintConfig; diff --git a/packages/eslint-config/src/types/index.ts b/packages/eslint-config/src/types/index.ts new file mode 100644 index 0000000..3e2a95e --- /dev/null +++ b/packages/eslint-config/src/types/index.ts @@ -0,0 +1,52 @@ +/* eslint-disable @typescript-eslint/no-empty-object-type */ +import { TSESLint } from "@typescript-eslint/utils"; + +interface ESLintFlatConfig extends TSESLint.FlatConfig.Config {} +interface ESLintPlugin extends TSESLint.FlatConfig.Plugin {} +interface ESLintLanguageOptions extends TSESLint.FlatConfig.LanguageOptions {} + +interface ESLintFlatConfigWithExtend extends ESLintFlatConfig { + /** + * Allows you to "extend" a set of configs similar to `extends` from the + * classic configs. + * + * This is just a convenience short-hand to help reduce duplication. + * + * ```js + * export default qlikEslint.compose({ + * files: ['** /*.ts'], + * extend: [ + * ...qlikEslint.configs.ts, + * ], + * rules: { + * '@typescript-eslint/array-type': 'error', + * '@typescript-eslint/consistent-type-imports': 'error', + * }, + * }) + * + * // expands to + * + * export default [ + * ...qlikEslint.configs.ts.map(conf => ({ + * ...conf, + * files: ['** /*.ts'], + * })), + * { + * files: ['** /*.ts'], + * rules: { + * '@typescript-eslint/array-type': 'error', + * '@typescript-eslint/consistent-type-imports': 'error', + * }, + * }, + * ] + * ``` + */ + extend?: ESLintFlatConfig[]; +} + +export type QlikEslintConfig = { + configs: Record; + compose: (...configs: ESLintFlatConfigWithExtend[]) => ESLintFlatConfig[]; +}; + +export type { ESLintFlatConfig, ESLintFlatConfigWithExtend, ESLintLanguageOptions, ESLintPlugin }; diff --git a/packages/eslint-config/src/utils/__tests__/compose.test.ts b/packages/eslint-config/src/utils/__tests__/compose.test.ts new file mode 100644 index 0000000..e08a0d3 --- /dev/null +++ b/packages/eslint-config/src/utils/__tests__/compose.test.ts @@ -0,0 +1,232 @@ +import { describe, expect, it } from "vitest"; +import type { ESLintFlatConfig, ESLintFlatConfigWithExtend } from "../../types/index.js"; +import compose from "../compose.js"; + +describe("compose function", () => { + it("should return an empty array when no configs are provided", () => { + const result = compose(); + expect(result).toEqual([]); + }); + + it("should return the same config when a single config is provided without extend", () => { + const config: ESLintFlatConfig = { rules: { "no-console": "error" } }; + const result = compose(config); + expect(result).toEqual([config]); + }); + + it("should merge configs with extend property correctly", () => { + const baseConfig: ESLintFlatConfig = { rules: { "no-console": "error" } }; + + const result = compose({ + extend: [baseConfig], + rules: { "no-debugger": "warn" }, + files: ["*.js"], + }); + + expect(result).toEqual([ + { files: ["*.js"], rules: { "no-console": "error" } }, + { files: ["*.js"], rules: { "no-debugger": "warn" } }, + ]); + }); + + it("should handle multiple extends on an otherwise empty config", () => { + const baseConfig1: ESLintFlatConfig = { rules: { "no-console": "error" } }; + const baseConfig2: ESLintFlatConfig = { rules: { "no-debugger": "warn" } }; + + const result = compose({ + extend: [baseConfig1, baseConfig2], + }); + + expect(result).toEqual([{ rules: { "no-console": "error" } }, { rules: { "no-debugger": "warn" } }, {}]); + }); + + it("should throw an error if extend property is not an array", () => { + // @ts-expect-error this is intentional + const invalidConfig: ESLintFlatConfigWithExtend = { extend: {}, rules: { "no-console": "error" } }; + expect(() => compose(invalidConfig)).toThrow("extend property must be an array"); + }); + + it("should throw an error if extend property is a string", () => { + // @ts-expect-error this is intentional + const invalidConfig: ESLintFlatConfigWithExtend = { extend: "someconfig", rules: { "no-console": "error" } }; + expect(() => compose(invalidConfig)).toThrow("extend property must be an array"); + }); + + it("should handle multiple configs with extend properties", () => { + const baseConfig1: ESLintFlatConfig = { rules: { "no-console": "error" } }; + const baseConfig2: ESLintFlatConfig = { rules: { "no-debugger": "warn" } }; + + const result = compose( + { + extend: [baseConfig1], + files: ["*.js"], + }, + { + extend: [baseConfig2], + files: ["*.ts"], + }, + ); + + expect(result).toEqual([ + { rules: { "no-console": "error" }, files: ["*.js"] }, + { files: ["*.js"] }, + { rules: { "no-debugger": "warn" }, files: ["*.ts"] }, + { files: ["*.ts"] }, + ]); + }); + + it("should handle when configs have a name property", () => { + const baseConfig1: ESLintFlatConfig = { name: "base-config-1", rules: { "no-console": "error" } }; + const baseConfig2: ESLintFlatConfig = { name: "base-config-2", rules: { "no-debugger": "warn" } }; + + const result = compose( + { + extend: [baseConfig1], + files: ["*.js"], + }, + { + extend: [baseConfig2], + files: ["*.ts"], + }, + ); + + expect(result).toEqual([ + { name: "base-config-1", rules: { "no-console": "error" }, files: ["*.js"] }, + { + files: ["*.js"], + }, + { name: "base-config-2", rules: { "no-debugger": "warn" }, files: ["*.ts"] }, + { + files: ["*.ts"], + }, + ]); + }); + + it("should handle extending from multiple configs", () => { + const baseConfig1: ESLintFlatConfig = { rules: { "no-console": "error" } }; + const baseConfig2: ESLintFlatConfig = { rules: { "no-debugger": "warn" } }; + + const result = compose({ + extend: [baseConfig1, baseConfig2], + files: ["*.js"], + }); + + expect(result).toEqual([ + { rules: { "no-console": "error" }, files: ["*.js"] }, + { rules: { "no-debugger": "warn" }, files: ["*.js"] }, + { files: ["*.js"] }, + ]); + }); + + it("should handle extending from configs in the array format", () => { + const baseConfig1: ESLintFlatConfig[] = [ + { rules: { "no-console": "error" } }, + { rules: { "no-debugger": "warn" } }, + ]; + + const result = compose({ + extend: [...baseConfig1], + files: ["*.tsx"], + }); + + expect(result).toEqual([ + { rules: { "no-console": "error" }, files: ["*.tsx"] }, + { rules: { "no-debugger": "warn" }, files: ["*.tsx"] }, + { files: ["*.tsx"] }, + ]); + }); + + it("should handle multiple configs in the array format with extend properties", () => { + const parseFn = () => "eslint"; + const baseConfig1: ESLintFlatConfig[] = [ + { languageOptions: { parser: { parse: parseFn } } }, + { rules: { "no-console": "error" }, files: ["*.js"] }, + ]; + const baseConfig2: ESLintFlatConfig[] = [{ rules: { "no-debugger": "warn" } }]; + + const result = compose( + { + extend: [...baseConfig1], + files: ["*.jsx"], + rules: { "no-debugger": "off" }, + }, + { + extend: [...baseConfig2], + files: ["*.tsx"], + rules: { "no-undef": "error" }, + }, + ); + + expect(result).toEqual([ + { + files: ["*.jsx"], + languageOptions: { + parser: { + parse: parseFn, + }, + }, + }, + { + files: ["*.jsx"], + rules: { + "no-console": "error", + }, + }, + { + files: ["*.jsx"], + rules: { + "no-debugger": "off", + }, + }, + { + files: ["*.tsx"], + rules: { + "no-debugger": "warn", + }, + }, + { + files: ["*.tsx"], + rules: { + "no-undef": "error", + }, + }, + ]); + }); + + it("should handle multiple nested extend properties", () => { + const baseConfig1: ESLintFlatConfig = { rules: { "no-console": "error" } }; + + const composedConfig = compose({ + extend: [baseConfig1], + rules: { "no-debugger": "warn" }, + files: ["*.js"], + }); + + const nestedComposedConfig = compose({ + extend: [...composedConfig], + rules: { "no-typescript": "error" }, + files: ["*.ts"], + }); + + expect(nestedComposedConfig).toEqual([ + { + files: ["*.ts"], + rules: { + "no-console": "error", + }, + }, + { + files: ["*.ts"], + rules: { + "no-debugger": "warn", + }, + }, + { + files: ["*.ts"], + rules: { + "no-typescript": "error", + }, + }, + ]); + }); +}); diff --git a/packages/eslint-config/src/utils/__tests__/config.test.ts b/packages/eslint-config/src/utils/__tests__/config.test.ts new file mode 100644 index 0000000..d970d46 --- /dev/null +++ b/packages/eslint-config/src/utils/__tests__/config.test.ts @@ -0,0 +1,158 @@ +import { describe, expect, it } from "vitest"; + +import type { ESLintFlatConfig } from "../../types/index.js"; +import { mergeConfigs } from "../config.js"; + +describe("config", () => { + it("should merge multiple config objects into one", () => { + const config1: ESLintFlatConfig = { + rules: { + "no-console": "error", + "no-debugger": "error", + }, + }; + + const config2: ESLintFlatConfig = { + rules: { + "no-alert": "warn", + "no-debugger": "off", + }, + }; + + const expectedConfig: ESLintFlatConfig = { + rules: { + "no-console": "error", + "no-debugger": "off", + "no-alert": "warn", + }, + }; + const result = mergeConfigs(config1, config2); + expect(result).toEqual(expectedConfig); + }); + + it("should override rules from previous configs", () => { + const config1: ESLintFlatConfig = { + rules: { + "no-console": "error", + }, + }; + + const config2: ESLintFlatConfig = { + rules: { + "no-console": "warn", + }, + }; + + const expectedConfig: ESLintFlatConfig = { + rules: { + "no-console": "warn", + }, + }; + const result = mergeConfigs(config1, config2); + expect(result).toEqual(expectedConfig); + }); + + it("should handle empty configs", () => { + const config1: ESLintFlatConfig = { + rules: { + "no-console": "error", + }, + }; + + const expectedConfig: ESLintFlatConfig = { + rules: { + "no-console": "error", + }, + }; + const result = mergeConfigs(config1, {}); + expect(result).toEqual(expectedConfig); + }); + + it("should return an empty object when no configs are provided", () => { + const expectedConfig = {}; + + const result = mergeConfigs(); + expect(result).toEqual(expectedConfig); + }); + + it("should handle names of the configs", () => { + const config1: ESLintFlatConfig = { + rules: { + "no-console": "error", + }, + name: "config1", + }; + + const config2: ESLintFlatConfig = { + rules: { + "no-debugger": "error", + }, + name: "config2", + }; + + const expectedConfig: ESLintFlatConfig = { + rules: { + "no-console": "error", + "no-debugger": "error", + }, + name: "@qlik/eslint-config/config2", + }; + const result = mergeConfigs(config1, config2); + expect(result).toEqual(expectedConfig); + }); + + it("should handle names of the configs when @qlik/eslint-config already been added", () => { + const config1: ESLintFlatConfig = { + rules: { + "no-console": "error", + }, + name: "config1", + }; + + const config2: ESLintFlatConfig = { + rules: { + "no-debugger": "error", + }, + name: "@qlik/eslint-config/config2", + }; + + expect(mergeConfigs(config1, config2)).toEqual({ + rules: { + "no-console": "error", + "no-debugger": "error", + }, + name: "@qlik/eslint-config/config2", + }); + + expect(mergeConfigs(config2, config1)).toEqual({ + rules: { + "no-console": "error", + "no-debugger": "error", + }, + name: "@qlik/eslint-config/config1", + }); + + const config3: ESLintFlatConfig = { + rules: { + "no-console": "error", + }, + name: "@qlik/eslint-config/config3", + }; + + expect(mergeConfigs(config2, config3)).toEqual({ + rules: { + "no-console": "error", + "no-debugger": "error", + }, + name: "@qlik/eslint-config/config3", + }); + + expect(mergeConfigs(config3, config2)).toEqual({ + rules: { + "no-console": "error", + "no-debugger": "error", + }, + name: "@qlik/eslint-config/config2", + }); + }); +}); diff --git a/packages/eslint-config/src/utils/__tests__/merge.test.ts b/packages/eslint-config/src/utils/__tests__/merge.test.ts new file mode 100644 index 0000000..b07fbc7 --- /dev/null +++ b/packages/eslint-config/src/utils/__tests__/merge.test.ts @@ -0,0 +1,63 @@ +import { describe, expect, it } from "vitest"; +import { merge } from "../merge.js"; + +describe("merge function", () => { + it("should merge two objects without duplicates", () => { + const obj1 = { a: 1, b: 2 }; + const obj2 = { b: 3, c: 4 }; + const result = merge(obj1, obj2); + expect(result).toEqual({ a: 1, b: 3, c: 4 }); + }); + // Add more tests here including arrays, nested objects, etc. + it("should merge two objects with arrays without duplicates", () => { + const obj1 = { a: 1, b: [1, 2] }; + const obj2 = { b: [2, 3], c: 4 }; + const result = merge(obj1, obj2); + expect(result).toEqual({ a: 1, b: [1, 2, 3], c: 4 }); + }); + // Add test with objects with nested objects + it("should merge two objects with nested objects without duplicates", () => { + const obj1 = { a: 1, b: { c: 2, d: 3 } }; + const obj2 = { b: { c: 3, e: 4 }, f: 5 }; + const result = merge(obj1, obj2); + expect(result).toEqual({ a: 1, b: { c: 3, d: 3, e: 4 }, f: 5 }); + }); + + it("should merge two objects with nested objects and arrays without duplicates", () => { + const obj1 = { a: 1, b: { c: 2, d: [1, 2] } }; + const obj2 = { b: { d: [2, 3], e: 4 }, f: 5 }; + const result = merge(obj1, obj2); + expect(result).toEqual({ a: 1, b: { c: 2, d: [1, 2, 3], e: 4 }, f: 5 }); + }); + + it("should handle deep merging of both objects and arrays", () => { + const obj1 = { a: 1, b: { c: 2, d: [1, 2] } }; + const obj2 = { b: { d: [2, 3], e: 4 }, f: 5 }; + const result = merge(obj1, obj2); + expect(result).toEqual({ a: 1, b: { c: 2, d: [1, 2, 3], e: 4 }, f: 5 }); + }); + + it("should overwrite object if it merges with a non-object", () => { + const obj1 = { a: 1, b: { c: 2, d: [1, 2] } }; + const obj2 = { b: 3, f: 5 }; + const result = merge(obj1, obj2); + expect(result).toEqual({ a: 1, b: 3, f: 5 }); + }); + + it("should not deep merge plugins or rules properties", () => { + const obj1 = { + plugins: { a: { deep: { b: "world" } }, b: "b" }, + rules: { a: ["error", { setting: { a: "foo" } }], b: "off" }, + }; + const obj2 = { + plugins: { a: { overwritten: { b: "nomerge" } } }, + rules: { a: ["warn", { changed: { b: "bar" } }] }, + }; + + const result = merge(obj1, obj2); + expect(result).toEqual({ + plugins: { a: { overwritten: { b: "nomerge" } }, b: "b" }, + rules: { a: ["warn", { changed: { b: "bar" } }], b: "off" }, + }); + }); +}); diff --git a/packages/eslint-config/src/utils/compose.js b/packages/eslint-config/src/utils/compose.js new file mode 100644 index 0000000..806631c --- /dev/null +++ b/packages/eslint-config/src/utils/compose.js @@ -0,0 +1,62 @@ +// @ts-check +/** + * Utility function to make it easy to strictly type your "Flat" config file + * + * @param {...(import("../types/index.js").ESLintFlatConfigWithExtend)} configs + * @returns {import("../types/index.js").ESLintFlatConfig[]} + * + * @example + * ```js + * import eslint from '@eslint/js'; + * import tseslint from 'typescript-eslint'; + * + * export default qlik.compose( + * eslint.configs.recommended, + * ...tseslint.configs.recommended, + * { + * rules: { + * '@typescript-eslint/array-type': 'error', + * }, + * }, + * ); + * ``` + */ +export default function compose(...configs) { + return configs.flatMap((configWithExtends, configIndex) => { + const { extend: extendArr, ...config } = configWithExtends; + if (extendArr && !Array.isArray(extendArr)) { + throw new Error("extend property must be an array"); + } + if (extendArr == null || extendArr.length === 0) { + return config; + } + const undefinedExtensions = extendArr.reduce((acc, extension, extensionIndex) => { + const maybeExtension = extension; + if (maybeExtension == null) { + acc.push(extensionIndex); + } + return acc; + }, /** @type {number[]} */ ([])); + if (undefinedExtensions.length) { + const configName = configWithExtends.name != null ? `, named "${configWithExtends.name}",` : " (anonymous)"; + const extensionIndices = undefinedExtensions.join(", "); + throw new Error( + `Your config at index ${configIndex}${configName} contains undefined` + + ` extensions at the following indices: ${extensionIndices}.`, + ); + } + + return [ + ...extendArr.map((extension) => { + const name = [config.name, extension.name].filter(Boolean).join("__"); + return { + ...extension, + ...(config.files && { files: config.files }), + ...(config.ignores && { ignores: config.ignores }), + ...(name && { name }), + }; + }), + config, + ]; + }); +} diff --git a/packages/eslint-config/src/utils/config.js b/packages/eslint-config/src/utils/config.js new file mode 100644 index 0000000..eba1bfc --- /dev/null +++ b/packages/eslint-config/src/utils/config.js @@ -0,0 +1,22 @@ +import tsEslint from "typescript-eslint"; +import { merge } from "./merge.js"; + +/** + * Merges multiple configs into one. + * + * @param {...(import("../types/index.js").ESLintFlatConfig)} configs + * @returns {import("../types/index.js").ESLintFlatConfig} + */ +export function mergeConfigs(...configs) { + // merge all configs into one + const mergedConfig = configs.reduce((acc, conf) => { + return merge(acc, conf); + }, {}); + + if (mergedConfig.name && !mergedConfig.name.startsWith("@qlik/eslint-config/")) { + mergedConfig.name = `@qlik/eslint-config/${mergedConfig.name}`; + } + return mergedConfig; +} + +export const config = tsEslint.config; diff --git a/packages/eslint-config/src/utils/merge.js b/packages/eslint-config/src/utils/merge.js new file mode 100644 index 0000000..8a12c83 --- /dev/null +++ b/packages/eslint-config/src/utils/merge.js @@ -0,0 +1,28 @@ +// these ones will only do shallow merge, but the merge function will do deep merge +const noNeedToDeepMerge = ["plugins", "rules", "parser"]; + +/** + * + * @param {any} obj1 + * @param {any} obj2 + * @returns + */ +export const merge = (obj1, obj2) => { + // add error handling + if (typeof obj1 !== "object" || typeof obj2 !== "object") { + throw new Error("Both arguments must be objects"); + } + const merged = { ...obj1 }; + Object.keys(obj2).forEach((key) => { + if (Array.isArray(obj1[key]) && Array.isArray(obj2[key])) { + merged[key] = [...new Set([...obj1[key], ...obj2[key]])]; + } else if (noNeedToDeepMerge.includes(key)) { + merged[key] = { ...obj1[key], ...obj2[key] }; + } else if (typeof obj1[key] === "object" && typeof obj2[key] === "object") { + merged[key] = merge(obj1[key], obj2[key]); + } else { + merged[key] = obj2[key]; + } + }); + return merged; +}; diff --git a/packages/eslint-config/svelte-js.js b/packages/eslint-config/svelte-js.js deleted file mode 100644 index 7098121..0000000 --- a/packages/eslint-config/svelte-js.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - extends: ["./index", "./overrides/sveltejs"], - parserOptions: { - extraFileExtensions: [".svelte"], - }, -}; diff --git a/packages/eslint-config/svelte.js b/packages/eslint-config/svelte.js deleted file mode 100644 index 8032a61..0000000 --- a/packages/eslint-config/svelte.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - extends: ["./index", "./overrides/sveltets"], - parserOptions: { - extraFileExtensions: [".svelte"], - }, -}; diff --git a/packages/eslint-config/tsconfig.json b/packages/eslint-config/tsconfig.json new file mode 100644 index 0000000..2a24ccb --- /dev/null +++ b/packages/eslint-config/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "@qlik/tsconfig/node.json", + "compilerOptions": { + "noEmit": true + }, + "include": ["**/*"], + "exclude": ["node_modules", "lib"] +} diff --git a/packages/eslint-config/vitest.config.ts b/packages/eslint-config/vitest.config.ts new file mode 100644 index 0000000..fdbbe3b --- /dev/null +++ b/packages/eslint-config/vitest.config.ts @@ -0,0 +1,4 @@ +/// +import { defineConfig } from "vitest/config"; + +export default defineConfig({}); diff --git a/packages/eslint-config/vitest.js b/packages/eslint-config/vitest.js deleted file mode 100644 index 0cbee8e..0000000 --- a/packages/eslint-config/vitest.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - overrides: [ - { - files: ["**/__tests__/**/*.{js,ts,jsx,tsx}", "**/*.{spec,test}.{js,ts,jsx,tsx}"], - plugins: ["@vitest", "testing-library"], - extends: ["plugin:@vitest/legacy-recommended"], - rules: { - "import/no-extraneous-dependencies": "off", - "@typescript-eslint/unbound-method": "off", - }, - }, - ], -}; diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index 59b5d21..e91e9a5 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -11,7 +11,7 @@ }, "dependencies": { "prettier-plugin-organize-imports": "^4.1.0", - "prettier-plugin-packagejson": "^2.5.2", + "prettier-plugin-packagejson": "^2.5.3", "prettier-plugin-sh": "^0.14.0", "prettier-plugin-svelte": "^3.2.7" }, diff --git a/packages/tsconfig/node.json b/packages/tsconfig/node.json index 894c7e3..db9d91b 100644 --- a/packages/tsconfig/node.json +++ b/packages/tsconfig/node.json @@ -1,6 +1,7 @@ { "compilerOptions": { "allowJs": true, + "checkJs": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "lib": ["ES2021"], diff --git a/packages/tsconfig/recommended.json b/packages/tsconfig/recommended.json index a582457..9f92d85 100644 --- a/packages/tsconfig/recommended.json +++ b/packages/tsconfig/recommended.json @@ -3,6 +3,7 @@ "allowJs": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, + "noImplicitReturns": true, "lib": ["DOM", "DOM.Iterable", "ESNext"], "module": "ESNext", "moduleResolution": "Bundler", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1e0fd5e..a2ba31d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: devDependencies: '@changesets/cli': - specifier: 2.27.8 - version: 2.27.8 + specifier: 2.27.9 + version: 2.27.9 '@qlik/prettier-config': specifier: workspace:* version: link:packages/prettier-config @@ -25,67 +25,82 @@ importers: packages/eslint-config: dependencies: - '@typescript-eslint/eslint-plugin': - specifier: ^7.18.0 - version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint@9.15.0)(typescript@5.6.2) - '@typescript-eslint/parser': - specifier: ^7.18.0 - version: 7.18.0(eslint@9.15.0)(typescript@5.6.2) + '@eslint-react/eslint-plugin': + specifier: 1.16.2 + version: 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint/js': + specifier: ^9.15.0 + version: 9.15.0 + '@typescript-eslint/utils': + specifier: ^8.15.0 + version: 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) '@vitest/eslint-plugin': - specifier: 1.1.10 - version: 1.1.10(@typescript-eslint/utils@8.7.0(eslint@9.15.0)(typescript@5.6.2))(eslint@9.15.0)(typescript@5.6.2)(vitest@2.1.1(@types/node@22.7.4)) - eslint-config-airbnb: - specifier: ^19.0.4 - version: 19.0.4(eslint-plugin-import@2.31.0)(eslint-plugin-jsx-a11y@6.10.2(eslint@9.15.0))(eslint-plugin-react-hooks@5.0.0(eslint@9.15.0))(eslint-plugin-react@7.37.2(eslint@9.15.0))(eslint@9.15.0) - eslint-config-airbnb-base: - specifier: ^15.0.0 - version: 15.0.0(eslint-plugin-import@2.31.0)(eslint@9.15.0) - eslint-config-airbnb-typescript: - specifier: ^18.0.0 - version: 18.0.0(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint@9.15.0)(typescript@5.6.2))(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint-plugin-import@2.31.0)(eslint@9.15.0) - eslint-config-prettier: - specifier: ^9.1.0 - version: 9.1.0(eslint@9.15.0) + specifier: ^1.1.10 + version: 1.1.10(@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2))(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2)(vitest@2.1.5(@types/node@22.7.4)) + confusing-browser-globals: + specifier: ^1.0.11 + version: 1.0.11 eslint-import-resolver-typescript: specifier: ^3.6.3 - version: 3.6.3(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint-plugin-import@2.31.0)(eslint@9.15.0) - eslint-plugin-import: - specifier: ^2.31.0 - version: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0) + version: 3.6.3(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2))(eslint-plugin-import-x@4.4.3(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2))(eslint-plugin-import@2.31.0)(eslint@9.15.0(jiti@2.4.0)) + eslint-plugin-import-x: + specifier: ^4.4.2 + version: 4.4.3(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) eslint-plugin-jest: specifier: ^28.9.0 - version: 28.9.0(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint@9.15.0)(typescript@5.6.2))(eslint@9.15.0)(typescript@5.6.2) + version: 28.9.0(@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2))(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2))(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) eslint-plugin-jsx-a11y: specifier: ^6.10.2 - version: 6.10.2(eslint@9.15.0) + version: 6.10.2(eslint@9.15.0(jiti@2.4.0)) eslint-plugin-playwright: - specifier: ^2.1.0 - version: 2.1.0(eslint@9.15.0) + specifier: 2.1.0 + version: 2.1.0(eslint@9.15.0(jiti@2.4.0)) eslint-plugin-react: specifier: ^7.37.2 - version: 7.37.2(eslint@9.15.0) + version: 7.37.2(eslint@9.15.0(jiti@2.4.0)) eslint-plugin-react-hooks: specifier: ^5.0.0 - version: 5.0.0(eslint@9.15.0) + version: 5.0.0(eslint@9.15.0(jiti@2.4.0)) eslint-plugin-svelte: - specifier: ^2.46.0 - version: 2.46.0(eslint@9.15.0)(svelte@4.2.19) + specifier: 2.46.0 + version: 2.46.0(eslint@9.15.0(jiti@2.4.0))(svelte@4.2.19) eslint-plugin-testing-library: - specifier: ^6.5.0 - version: 6.5.0(eslint@9.15.0)(typescript@5.6.2) + specifier: ^7.0.0 + version: 7.0.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + globals: + specifier: ^15.12.0 + version: 15.12.0 svelte-eslint-parser: - specifier: ^0.43.0 + specifier: 0.43.0 version: 0.43.0(svelte@4.2.19) + typescript-eslint: + specifier: ^8.15.0 + version: 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) devDependencies: '@qlik/prettier-config': specifier: workspace:* version: link:../prettier-config + '@qlik/tsconfig': + specifier: workspace:* + version: link:../tsconfig + '@types/confusing-browser-globals': + specifier: ^1.0.3 + version: 1.0.3 + '@types/eslint-plugin-jsx-a11y': + specifier: ^6.9.0 + version: 6.10.0 + '@types/eslint__js': + specifier: ^8.42.3 + version: 8.42.3 eslint: specifier: ^9.15.0 - version: 9.15.0 + version: 9.15.0(jiti@2.4.0) prettier: specifier: ^3.3.3 version: 3.3.3 + vitest: + specifier: ^2.1.5 + version: 2.1.5(@types/node@22.7.4) packages/prettier-config: dependencies: @@ -96,8 +111,8 @@ importers: specifier: ^4.1.0 version: 4.1.0(prettier@3.3.3)(typescript@5.6.2) prettier-plugin-packagejson: - specifier: ^2.5.2 - version: 2.5.2(prettier@3.3.3) + specifier: ^2.5.3 + version: 2.5.6(prettier@3.3.3) prettier-plugin-sh: specifier: ^0.14.0 version: 0.14.0(prettier@3.3.3) @@ -115,10 +130,6 @@ importers: version: 3.3.3 test/test-base: - dependencies: - react: - specifier: ^18.3.1 - version: 18.3.1 devDependencies: '@qlik/eslint-config': specifier: workspace:* @@ -130,14 +141,14 @@ importers: specifier: workspace:* version: link:../../packages/tsconfig '@types/react': - specifier: ^18.3.10 - version: 18.3.10 + specifier: ^18.3.11 + version: 18.3.12 eslint: - specifier: ^8.57.0 - version: 8.57.0 + specifier: ^9.15.0 + version: 9.15.0(jiti@2.4.0) vitest: - specifier: ^2.1.1 - version: 2.1.1(@types/node@22.7.4) + specifier: ^2.1.2 + version: 2.1.5(@types/node@22.7.4) test/test-react: dependencies: @@ -155,11 +166,11 @@ importers: specifier: workspace:* version: link:../../packages/tsconfig '@types/react': - specifier: ^18.3.10 - version: 18.3.10 + specifier: ^18.3.12 + version: 18.3.12 eslint: - specifier: ^8.57.0 - version: 8.57.0 + specifier: ^9.15.0 + version: 9.15.0(jiti@2.4.0) test/test-react-svelte: dependencies: @@ -180,11 +191,11 @@ importers: specifier: workspace:* version: link:../../packages/tsconfig '@types/react': - specifier: ^18.3.10 - version: 18.3.10 + specifier: ^18.3.11 + version: 18.3.12 eslint: - specifier: ^8.57.0 - version: 8.57.0 + specifier: ^9.15.0 + version: 9.15.0(jiti@2.4.0) packages: @@ -205,8 +216,8 @@ packages: '@changesets/changelog-git@0.2.0': resolution: {integrity: sha512-bHOx97iFI4OClIT35Lok3sJAwM31VbUM++gnMBV16fdbtBhgYu4dxsphBF/0AZZsyAHMrnM0yFcj5gZM1py6uQ==} - '@changesets/cli@2.27.8': - resolution: {integrity: sha512-gZNyh+LdSsI82wBSHLQ3QN5J30P4uHKJ4fXgoGwQxfXwYFTJzDdvIJasZn8rYQtmKhyQuiBj4SSnLuKlxKWq4w==} + '@changesets/cli@2.27.9': + resolution: {integrity: sha512-q42a/ZbDnxPpCb5Wkm6tMVIxgeI9C/bexntzTeCFBrQEdpisQqk8kCHllYZMDjYtEc1ZzumbMJAG8H0Z4rdvjg==} hasBin: true '@changesets/config@3.0.3': @@ -395,18 +406,41 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.10.1': - resolution: {integrity: sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - - '@eslint-community/regexpp@4.11.1': - resolution: {integrity: sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint-community/regexpp@4.12.1': resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint-react/ast@1.16.2': + resolution: {integrity: sha512-KFjXQS68TzUPUUoaCrfNhaYPAsSho7KGflerGWL0Sw5njaa7fwH+HyNgaHKsyhY99lidiPjMIveoOfcq1j7v3A==} + + '@eslint-react/core@1.16.2': + resolution: {integrity: sha512-dn+ByJoxH4tHxiWwqUwhLXq1gf1D/LmtG5XdLw3bLeFSkpNSGrR4k++1oHjIhv7pHN4/wFCUgIDShSbFEQtQNA==} + + '@eslint-react/eslint-plugin@1.16.2': + resolution: {integrity: sha512-B/46aHpW319ZZUoPb9rdhhiMqOAxERGqc45NxnEaRp3ig6p5zEFZEPBb7nDuphCfv+Ai4gk2EB/lXIv+DvYFjg==} + engines: {bun: '>=1.0.15', node: '>=18.18.0'} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ^4.9.5 || ^5.3.3 + peerDependenciesMeta: + typescript: + optional: true + + '@eslint-react/jsx@1.16.2': + resolution: {integrity: sha512-Sq9wFNydvMspJCsRwqxnxOvhVgZkaNFi+qZVzGu7azlmIOc9CWE2ktVqJ757onUIMtPcKD+O/r2nMPr/vSxxjA==} + + '@eslint-react/shared@1.16.2': + resolution: {integrity: sha512-IlSelSU8GDiYEIRk9QaB/gXMEBgEhuT51w0RtoyIb8On/yVMJhgv+wsXfCCJZbB/fRPdzO55GIfysJAJIeTmEw==} + + '@eslint-react/tools@1.16.2': + resolution: {integrity: sha512-gUxLR4Y2qV+vVw0bpwMvsMjbowXf1r3kqCxRFi5Nsn2IFbTQR2p3c9m1pzYkRVVhy75fgf9LDC8oUxshGOnoWA==} + + '@eslint-react/types@1.16.2': + resolution: {integrity: sha512-QDFm854YD2AprBB/6nSIqkVYO5K4AWBGpsDSEPEYUFjXwdCt0144Hr6onZf4smxLraeTQr2zkUlVfFkKsDXEng==} + + '@eslint-react/var@1.16.2': + resolution: {integrity: sha512-yGLt3rpoQTM4g+5nB6+WJHn4LYWk+xwSPoQ+ZMd18bJ0vArEpoiULSDESJv79mVyhXe8uM/irdKxGPz+cMtD6A==} + '@eslint/config-array@0.19.0': resolution: {integrity: sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -415,18 +449,10 @@ packages: resolution: {integrity: sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/eslintrc@2.1.4': - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@eslint/eslintrc@3.2.0': resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@8.57.0': - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@eslint/js@9.15.0': resolution: {integrity: sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -447,19 +473,10 @@ packages: resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} engines: {node: '>=18.18.0'} - '@humanwhocodes/config-array@0.11.14': - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} - deprecated: Use @eslint/config-array instead - '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - '@humanwhocodes/object-schema@2.0.3': - resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} - deprecated: Use @eslint/object-schema instead - '@humanwhocodes/retry@0.3.1': resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} engines: {node: '>=18.18'} @@ -595,6 +612,18 @@ packages: '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + '@types/confusing-browser-globals@1.0.3': + resolution: {integrity: sha512-q+6axdE3RyjrSsy2ONE4UpF89rwOfpoMBP3lqJ+OzLuOeYHwP+o2GITzuleKb1UT3FSYybO8QmeACgyHleu2CA==} + + '@types/eslint-plugin-jsx-a11y@6.10.0': + resolution: {integrity: sha512-TGKmk2gO6DrvTVADNOGQMqn3SzqcFcJILFnXNllQA34us9uClS3/AsL/cERPz6jS9ePI3bx+1q8/d2GZsxPVYw==} + + '@types/eslint@9.6.1': + resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} + + '@types/eslint__js@8.42.3': + resolution: {integrity: sha512-alfG737uhmPdnvkrLdZLcEKJ/B8s9Y4hrZ+YAdzUeoArBlSUERA2E87ROfOaS4jd/C45fzOoZzidLc1IPwLqOw==} + '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} @@ -613,127 +642,71 @@ packages: '@types/prop-types@15.7.13': resolution: {integrity: sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==} - '@types/react@18.3.10': - resolution: {integrity: sha512-02sAAlBnP39JgXwkAq3PeU9DVaaGpZyF3MGcC0MKgQVkZor5IiiDAipVaxQHtDJAmO4GIy/rVBy/LzVj76Cyqg==} + '@types/react@18.3.12': + resolution: {integrity: sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==} - '@types/semver@7.5.8': - resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - - '@typescript-eslint/eslint-plugin@7.18.0': - resolution: {integrity: sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/eslint-plugin@8.15.0': + resolution: {integrity: sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 + '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/parser@7.18.0': - resolution: {integrity: sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/parser@8.15.0': + resolution: {integrity: sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.56.0 + eslint: ^8.57.0 || ^9.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/scope-manager@5.62.0': - resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - '@typescript-eslint/scope-manager@7.18.0': - resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==} - engines: {node: ^18.18.0 || >=20.0.0} - - '@typescript-eslint/scope-manager@8.7.0': - resolution: {integrity: sha512-87rC0k3ZlDOuz82zzXRtQ7Akv3GKhHs0ti4YcbAJtaomllXoSO8hi7Ix3ccEvCd824dy9aIX+j3d2UMAfCtVpg==} + '@typescript-eslint/scope-manager@8.15.0': + resolution: {integrity: sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@7.18.0': - resolution: {integrity: sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/type-utils@8.15.0': + resolution: {integrity: sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.56.0 + eslint: ^8.57.0 || ^9.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/types@5.62.0': - resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - '@typescript-eslint/types@7.18.0': - resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==} - engines: {node: ^18.18.0 || >=20.0.0} - - '@typescript-eslint/types@8.7.0': - resolution: {integrity: sha512-LLt4BLHFwSfASHSF2K29SZ+ZCsbQOM+LuarPjRUuHm+Qd09hSe3GCeaQbcCr+Mik+0QFRmep/FyZBO6fJ64U3w==} + '@typescript-eslint/types@8.15.0': + resolution: {integrity: sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@5.62.0': - resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/typescript-estree@7.18.0': - resolution: {integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/typescript-estree@8.15.0': + resolution: {integrity: sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/typescript-estree@8.7.0': - resolution: {integrity: sha512-MC8nmcGHsmfAKxwnluTQpNqceniT8SteVwd2voYlmiSWGOtjvGXdPl17dYu2797GVscK30Z04WRM28CrKS9WOg==} + '@typescript-eslint/utils@8.15.0': + resolution: {integrity: sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: + eslint: ^8.57.0 || ^9.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/utils@5.62.0': - resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - - '@typescript-eslint/utils@7.18.0': - resolution: {integrity: sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - - '@typescript-eslint/utils@8.7.0': - resolution: {integrity: sha512-ZbdUdwsl2X/s3CiyAu3gOlfQzpbuG3nTWKPoIvAu1pu5r8viiJvv2NPN2AqArL35NCYtw/lrPPfM4gxrMLNLPw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - - '@typescript-eslint/visitor-keys@5.62.0': - resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - '@typescript-eslint/visitor-keys@7.18.0': - resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==} - engines: {node: ^18.18.0 || >=20.0.0} - - '@typescript-eslint/visitor-keys@8.7.0': - resolution: {integrity: sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==} + '@typescript-eslint/visitor-keys@8.15.0': + resolution: {integrity: sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@ungap/structured-clone@1.2.0': - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - '@vitest/eslint-plugin@1.1.10': resolution: {integrity: sha512-uScH5Kz5v32vvtQYB2iodpoPg2mGASK+VKpjlc2IUgE0+16uZKqVKi2vQxjxJ6sMCQLBs4xhBFZlmZBszsmfKQ==} peerDependencies: @@ -747,14 +720,13 @@ packages: vitest: optional: true - '@vitest/expect@2.1.1': - resolution: {integrity: sha512-YeueunS0HiHiQxk+KEOnq/QMzlUuOzbU1Go+PgAsHvvv3tUkJPm9xWt+6ITNTlzsMXUjmgm5T+U7KBPK2qQV6w==} + '@vitest/expect@2.1.5': + resolution: {integrity: sha512-nZSBTW1XIdpZvEJyoP/Sy8fUg0b8od7ZpGDkTUcfJ7wz/VoZAFzFfLyxVxGFhUjJzhYqSbIpfMtl/+k/dpWa3Q==} - '@vitest/mocker@2.1.1': - resolution: {integrity: sha512-LNN5VwOEdJqCmJ/2XJBywB11DLlkbY0ooDJW3uRX5cZyYCrc4PI/ePX0iQhE3BiEGiQmK4GE7Q/PqCkkaiPnrA==} + '@vitest/mocker@2.1.5': + resolution: {integrity: sha512-XYW6l3UuBmitWqSUXTNXcVBUCRytDogBsWuNXQijc00dtnU/9OqpXWp4OJroVrad/gLIomAq9aW8yWDBtMthhQ==} peerDependencies: - '@vitest/spy': 2.1.1 - msw: ^2.3.5 + msw: ^2.4.9 vite: ^5.0.0 peerDependenciesMeta: msw: @@ -762,31 +734,26 @@ packages: vite: optional: true - '@vitest/pretty-format@2.1.1': - resolution: {integrity: sha512-SjxPFOtuINDUW8/UkElJYQSFtnWX7tMksSGW0vfjxMneFqxVr8YJ979QpMbDW7g+BIiq88RAGDjf7en6rvLPPQ==} + '@vitest/pretty-format@2.1.5': + resolution: {integrity: sha512-4ZOwtk2bqG5Y6xRGHcveZVr+6txkH7M2e+nPFd6guSoN638v/1XQ0K06eOpi0ptVU/2tW/pIU4IoPotY/GZ9fw==} - '@vitest/runner@2.1.1': - resolution: {integrity: sha512-uTPuY6PWOYitIkLPidaY5L3t0JJITdGTSwBtwMjKzo5O6RCOEncz9PUN+0pDidX8kTHYjO0EwUIvhlGpnGpxmA==} + '@vitest/runner@2.1.5': + resolution: {integrity: sha512-pKHKy3uaUdh7X6p1pxOkgkVAFW7r2I818vHDthYLvUyjRfkKOU6P45PztOch4DZarWQne+VOaIMwA/erSSpB9g==} - '@vitest/snapshot@2.1.1': - resolution: {integrity: sha512-BnSku1WFy7r4mm96ha2FzN99AZJgpZOWrAhtQfoxjUU5YMRpq1zmHRq7a5K9/NjqonebO7iVDla+VvZS8BOWMw==} + '@vitest/snapshot@2.1.5': + resolution: {integrity: sha512-zmYw47mhfdfnYbuhkQvkkzYroXUumrwWDGlMjpdUr4jBd3HZiV2w7CQHj+z7AAS4VOtWxI4Zt4bWt4/sKcoIjg==} - '@vitest/spy@2.1.1': - resolution: {integrity: sha512-ZM39BnZ9t/xZ/nF4UwRH5il0Sw93QnZXd9NAZGRpIgj0yvVwPpLd702s/Cx955rGaMlyBQkZJ2Ir7qyY48VZ+g==} + '@vitest/spy@2.1.5': + resolution: {integrity: sha512-aWZF3P0r3w6DiYTVskOYuhBc7EMc3jvn1TkBg8ttylFFRqNN2XGD7V5a4aQdk6QiUzZQ4klNBSpCLJgWNdIiNw==} - '@vitest/utils@2.1.1': - resolution: {integrity: sha512-Y6Q9TsI+qJ2CC0ZKj6VBb+T8UPz593N113nnUykqwANqhgf3QkZeHFlusgKLTqrnVHbj/XDKZcDHol+dxVT+rQ==} + '@vitest/utils@2.1.5': + resolution: {integrity: sha512-yfj6Yrp0Vesw2cwJbP+cl04OC+IHFsuQsrsJBL9pyGeQXE56v1UAOQco+SR55Vf1nQzfV0QJg1Qum7AaWUwwYg==} acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.12.0: - resolution: {integrity: sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==} - engines: {node: '>=0.4.0'} - hasBin: true - acorn@8.12.1: resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} engines: {node: '>=0.4.0'} @@ -884,6 +851,9 @@ packages: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} + birecord@0.1.1: + resolution: {integrity: sha512-VUpsf/qykW0heRlC8LooCq28Kxn3mAqKohhDG/49rrsQ1dT1CXyj/pgXS+5BSRzFTR/3DyIBOqQOrGyZOh71Aw==} + brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -910,8 +880,8 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - chai@5.1.1: - resolution: {integrity: sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==} + chai@5.1.2: + resolution: {integrity: sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==} engines: {node: '>=12'} chalk@4.1.2: @@ -948,10 +918,6 @@ packages: cross-spawn@5.1.0: resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} - cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -991,15 +957,6 @@ packages: supports-color: optional: true - debug@4.3.5: - resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - debug@4.3.7: resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} engines: {node: '>=6.0'} @@ -1075,6 +1032,9 @@ packages: resolution: {integrity: sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q==} engines: {node: '>= 0.4'} + es-module-lexer@1.5.4: + resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} + es-object-atoms@1.0.0: resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} engines: {node: '>= 0.4'} @@ -1105,36 +1065,6 @@ packages: peerDependencies: eslint: '>=6.0.0' - eslint-config-airbnb-base@15.0.0: - resolution: {integrity: sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==} - engines: {node: ^10.12.0 || >=12.0.0} - peerDependencies: - eslint: ^7.32.0 || ^8.2.0 - eslint-plugin-import: ^2.25.2 - - eslint-config-airbnb-typescript@18.0.0: - resolution: {integrity: sha512-oc+Lxzgzsu8FQyFVa4QFaVKiitTYiiW3frB9KYW5OWdPrqFc7FzxgB20hP4cHMlr+MBzGcLl3jnCOVOydL9mIg==} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^7.0.0 - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 - - eslint-config-airbnb@19.0.4: - resolution: {integrity: sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==} - engines: {node: ^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^7.32.0 || ^8.2.0 - eslint-plugin-import: ^2.25.3 - eslint-plugin-jsx-a11y: ^6.5.1 - eslint-plugin-react: ^7.28.0 - eslint-plugin-react-hooks: ^4.3.0 - - eslint-config-prettier@9.1.0: - resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} @@ -1172,6 +1102,12 @@ packages: eslint-import-resolver-webpack: optional: true + eslint-plugin-import-x@4.4.3: + resolution: {integrity: sha512-QBprHvhLsfDhP++2T1NnjsOUt6bLDX3NMHaYwAB1FD3xmYTkdFH+HS1OamGhz28jLkRyIZa6UNAzTxbHnJwz5w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + eslint-plugin-import@2.31.0: resolution: {integrity: sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==} engines: {node: '>=4'} @@ -1207,12 +1143,72 @@ packages: peerDependencies: eslint: '>=8.40.0' + eslint-plugin-react-debug@1.16.2: + resolution: {integrity: sha512-RbjEvjryJll0n286SAmmfo1ecq1xvBK5iTtzB7SwkERlfEBH+UDPeoggz4dLa3pVbTwpzI5BFY4j+KPLpqrnZw==} + engines: {bun: '>=1.0.15', node: '>=18.18.0'} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ^4.9.5 || ^5.3.3 + peerDependenciesMeta: + typescript: + optional: true + + eslint-plugin-react-dom@1.16.2: + resolution: {integrity: sha512-WyKACJCESmps/DHSJAChNZcaSuD6GKKSw4kOQO4zcE/oeZ5rqHahn3hqh+PWDBz0UYEjkRhjuJ8c4VDCJzfDwg==} + engines: {bun: '>=1.0.15', node: '>=18.18.0'} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ^4.9.5 || ^5.3.3 + peerDependenciesMeta: + typescript: + optional: true + + eslint-plugin-react-hooks-extra@1.16.2: + resolution: {integrity: sha512-2jTqUViMukYGIgfqKuroHJcJMjz9RIzEVaogcbzO7VU1NUYKJzrLbex+A8trGzPhlY5f+gZTyonTDvEOeziylA==} + engines: {bun: '>=1.0.15', node: '>=18.18.0'} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ^4.9.5 || ^5.3.3 + peerDependenciesMeta: + typescript: + optional: true + eslint-plugin-react-hooks@5.0.0: resolution: {integrity: sha512-hIOwI+5hYGpJEc4uPRmz2ulCjAGD/N13Lukkh8cLV0i2IRk/bdZDYjgLVHj+U9Z704kLIdIO6iueGvxNur0sgw==} engines: {node: '>=10'} peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + eslint-plugin-react-naming-convention@1.16.2: + resolution: {integrity: sha512-YmnzqhoQ6oU1EE9HvieeIUu0mDNNTVDWPNZXMHmMQXTsJGW315+9/gR+PACiXnuEDS3rONa+UPRKLccxczy+SQ==} + engines: {bun: '>=1.0.15', node: '>=18.18.0'} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ^4.9.5 || ^5.3.3 + peerDependenciesMeta: + typescript: + optional: true + + eslint-plugin-react-web-api@1.16.2: + resolution: {integrity: sha512-vyrNlSKP8iT7tPxbhwQrYvHNEBCbvQlnJTmdbmhkkcklmKvAXsFUcdHD2MlKpRLkmn6dssSbOPZNAZBSojVRvg==} + engines: {bun: '>=1.0.15', node: '>=18.18.0'} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ^4.9.5 || ^5.3.3 + peerDependenciesMeta: + typescript: + optional: true + + eslint-plugin-react-x@1.16.2: + resolution: {integrity: sha512-gLgcAGsLtFbm5LzIpPP6oVNtPwddGbJb/5NsIzKPsCVJtAE4xb66VExmw+ZiAlvtO4AzWnEjS3e9wamMGmVOHQ==} + engines: {bun: '>=1.0.15', node: '>=18.18.0'} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ^4.9.5 || ^5.3.3 + peerDependenciesMeta: + typescript: + optional: true + eslint-plugin-react@7.37.2: resolution: {integrity: sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==} engines: {node: '>=4'} @@ -1229,15 +1225,11 @@ packages: svelte: optional: true - eslint-plugin-testing-library@6.5.0: - resolution: {integrity: sha512-Ls5TUfLm5/snocMAOlofSOJxNN0aKqwTlco7CrNtMjkTdQlkpSMaeTCDHCuXfzrI97xcx2rSCNeKeJjtpkNC1w==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'} + eslint-plugin-testing-library@7.0.0: + resolution: {integrity: sha512-Bwrn5Qi08Lf5Huv4ZGDNYxwkFLAyGQIPB9lC0ALlojymP32aKsSxWnccP1NvIcI5vMhkENg4Y5Td/Q9/tLYmGQ==} + engines: {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-scope@5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} + eslint: ^8.57.0 || ^9.0.0 eslint-scope@7.2.2: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} @@ -1255,12 +1247,6 @@ packages: resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. - hasBin: true - eslint@9.15.0: resolution: {integrity: sha512-7CrWySmIibCgT1Os28lUU6upBshZ+GxybLOrmRzi08kS8MBuO8QA7pXEgYgY5W8vK3e74xv0lpjo9DbaGU9Rkw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1292,10 +1278,6 @@ packages: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} - estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} @@ -1307,6 +1289,10 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + expect-type@1.1.0: + resolution: {integrity: sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==} + engines: {node: '>=12.0.0'} + extendable-error@0.1.7: resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} @@ -1330,9 +1316,13 @@ packages: fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} + fdir@6.4.2: + resolution: {integrity: sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} @@ -1354,10 +1344,6 @@ packages: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} - flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} - flat-cache@4.0.1: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} @@ -1376,9 +1362,6 @@ packages: resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} engines: {node: '>=6 <7 || >=8'} - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -1423,10 +1406,6 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - globals@13.24.0: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} engines: {node: '>=8'} @@ -1435,6 +1414,10 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} + globals@15.12.0: + resolution: {integrity: sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==} + engines: {node: '>=18'} + globalthis@1.0.4: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} @@ -1443,10 +1426,6 @@ packages: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} - globby@13.2.2: - resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} @@ -1489,10 +1468,6 @@ packages: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} - ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -1505,13 +1480,6 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - internal-slot@1.0.7: resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} engines: {node: '>= 0.4'} @@ -1565,6 +1533,12 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-immutable-type@5.0.0: + resolution: {integrity: sha512-mcvHasqbRBWJznuPqqHRKiJgYAz60sZ0mvO3bN70JbkuK7ksfmgc489aKZYxMEjIbRvyOseaTjaRZLRF/xFeRA==} + peerDependencies: + eslint: '*' + typescript: '>=4.7.4' + is-map@2.0.3: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} @@ -1581,10 +1555,6 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - is-plain-obj@4.1.0: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} @@ -1645,6 +1615,10 @@ packages: resolution: {integrity: sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==} engines: {node: '>= 0.4'} + jiti@2.4.0: + resolution: {integrity: sha512-H5UpaUI+aHOqZXlYOaFP/8AzKsg+guWu+Pr3Y8i7+Y3zr1aXAvCvTAQ1RxSc6oVD8R8c7brgNtTVP91E7upH/g==} + hasBin: true + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -1721,12 +1695,18 @@ packages: loupe@3.1.1: resolution: {integrity: sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==} + loupe@3.1.2: + resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==} + lru-cache@4.1.5: resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} magic-string@0.30.11: resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} + magic-string@0.30.13: + resolution: {integrity: sha512-8rYBO+MsWkgjDSOvLomYnzhdwEG51olQ4zL5KXnNJWV5MNmrb4rTZdrtkhxjnD/QyZUqR/Z/XDsUs/4ej2nx0g==} + mdn-data@2.0.30: resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} @@ -1742,6 +1722,10 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} + minimatch@10.0.1: + resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} + engines: {node: 20 || >=22} + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -1756,9 +1740,6 @@ packages: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} - ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -1805,9 +1786,6 @@ packages: resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} engines: {node: '>= 0.4'} - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -1858,10 +1836,6 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -1890,6 +1864,10 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + pify@4.0.1: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} @@ -1944,8 +1922,8 @@ packages: vue-tsc: optional: true - prettier-plugin-packagejson@2.5.2: - resolution: {integrity: sha512-w+TmoLv2pIa+siplW1cCj2ujEXQQS6z7wmWLOiLQK/2QVl7Wy6xh/ZUpqQw8tbKMXDodmSW4GONxlA33xpdNOg==} + prettier-plugin-packagejson@2.5.6: + resolution: {integrity: sha512-TY7KiLtyt6Tlf53BEbXUWkN0+TRdHKgIMmtXtDCyHH6yWnZ50Lwq6Vb6lyjapZrhDTXooC4EtlY5iLe1sCgi5w==} peerDependencies: prettier: '>= 1.16.0' peerDependenciesMeta: @@ -2032,11 +2010,6 @@ packages: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - rollup@4.22.5: resolution: {integrity: sha512-WoinX7GeQOFMGznEcWA1WrTQCd/tpEbMkc3nuMs9BT0CPjMdSjPMTVClwWd4pgSQwJdP65SK9mTCNvItlr5o7w==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -2093,6 +2066,10 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + short-unique-id@5.2.0: + resolution: {integrity: sha512-cMGfwNyfDZ/nzJ2k2M+ClthBIh//GlZl1JEf47Uoa9XR11bz8Pa2T2wQO4bVrRdH48LrIDWJahQziKo3MjhsWg==} + hasBin: true + side-channel@1.0.6: resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} engines: {node: '>= 0.4'} @@ -2107,15 +2084,11 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} - slash@4.0.0: - resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} - engines: {node: '>=12'} - sort-object-keys@1.1.3: resolution: {integrity: sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==} - sort-package-json@2.10.1: - resolution: {integrity: sha512-d76wfhgUuGypKqY72Unm5LFnMpACbdxXsLPcL27pOsSrmVqH3PztFp1uq+Z22suk15h7vXmTesuh2aEjdCqb5w==} + sort-package-json@2.12.0: + resolution: {integrity: sha512-/HrPQAeeLaa+vbAH/znjuhwUluuiM/zL5XX9kop8UpDgjtyWKt43hGDk2vd/TBdDpzIyzIHVUgmYofzYrAQjew==} hasBin: true source-map-js@1.2.1: @@ -2128,11 +2101,17 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + stable-hash@0.0.4: + resolution: {integrity: sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==} + stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - std-env@3.7.0: - resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} + std-env@3.8.0: + resolution: {integrity: sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==} + + string-ts@2.2.0: + resolution: {integrity: sha512-VTP0LLZo4Jp9Gz5IiDVMS9WyLx/3IeYh0PXUn0NdPqusUFNgkHPWiEdbB9TU2Iv3myUskraD5WtYEdHUrQEIlQ==} string.prototype.includes@2.0.1: resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} @@ -2189,8 +2168,8 @@ packages: resolution: {integrity: sha512-IY1rnGr6izd10B0A8LqsBfmlT5OILVuZ7XsI0vdGPEvuonFV7NYEUK4dAkm9Zg2q0Um92kYjTpS1CAP3Nh/KWw==} engines: {node: '>=16'} - synckit@0.9.1: - resolution: {integrity: sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==} + synckit@0.9.2: + resolution: {integrity: sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==} engines: {node: ^14.18.0 || >=16.0.0} tapable@2.2.1: @@ -2201,14 +2180,15 @@ packages: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} - text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - tinyexec@0.3.0: - resolution: {integrity: sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==} + tinyexec@0.3.1: + resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==} + + tinyglobby@0.2.10: + resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==} + engines: {node: '>=12.0.0'} tinypool@1.0.1: resolution: {integrity: sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==} @@ -2236,21 +2216,20 @@ packages: peerDependencies: typescript: '>=4.2.0' + ts-declaration-location@1.0.4: + resolution: {integrity: sha512-r4JoxYhKULbZuH81Pjrp9OEG5St7XWk7zXwGkLKhmVcjiBVHTJXV5wK6dEa9JKW5QGSTW6b1lOjxAKp8R1SQhg==} + peerDependencies: + typescript: '>=4.0.0' + + ts-pattern@5.5.0: + resolution: {integrity: sha512-jqbIpTsa/KKTJYWgPNsFNbLVpwCgzXfFJ1ukNn4I8hMwyQzHMJnk/BqWzggB0xpkILuKzaO/aMYhS0SkaJyKXg==} + tsconfig-paths@3.15.0: resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} - tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - tslib@2.7.0: resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} - tsutils@3.21.0: - resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} - engines: {node: '>= 6'} - peerDependencies: - typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' - turbo-darwin-64@2.1.3: resolution: {integrity: sha512-ouJOm0g0YyoBuhmikEujVCBGo3Zr0lbSOWFIsQtWUTItC88F2w2byhjtsYGPXQwMlTbXwmoBU2lOCfWNkeEwHQ==} cpu: [x64] @@ -2309,6 +2288,16 @@ packages: resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} engines: {node: '>= 0.4'} + typescript-eslint@8.15.0: + resolution: {integrity: sha512-wY4FRGl0ZI+ZU4Jo/yjdBu0lVTSML58pu6PgGtJmCufvzfV565pUF6iACQt092uFOd49iLOTX/sEVmHtbSrS+w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + typescript@5.6.2: resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==} engines: {node: '>=14.17'} @@ -2330,8 +2319,8 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - vite-node@2.1.1: - resolution: {integrity: sha512-N/mGckI1suG/5wQI35XeR9rsMsPqKXzq1CdUndzVstBj/HvyxxGctwnK6WX43NGt5L3Z5tcRf83g4TITKJhPrA==} + vite-node@2.1.5: + resolution: {integrity: sha512-rd0QIgx74q4S1Rd56XIiL2cYEdyWn13cunYBIuqh9mpmQr7gGS0IxXoP8R6OaZtNQQLyXSWbd4rXKYUbhFpK5w==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true @@ -2366,15 +2355,15 @@ packages: terser: optional: true - vitest@2.1.1: - resolution: {integrity: sha512-97We7/VC0e9X5zBVkvt7SGQMGrRtn3KtySFQG5fpaMlS+l62eeXRQO633AYhSTC3z7IMebnPPNjGXVGNRFlxBA==} + vitest@2.1.5: + resolution: {integrity: sha512-P4ljsdpuzRTPI/kbND2sDZ4VmieerR2c9szEZpjc+98Z9ebvnXmM5+0tHEKqYZumXqlvnmfWsjeFOjXVriDG7A==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@types/node': ^18.0.0 || >=20.0.0 - '@vitest/browser': 2.1.1 - '@vitest/ui': 2.1.1 + '@vitest/browser': 2.1.5 + '@vitest/ui': 2.1.5 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -2424,9 +2413,6 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - yallist@2.1.2: resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} @@ -2478,7 +2464,7 @@ snapshots: dependencies: '@changesets/types': 6.0.0 - '@changesets/cli@2.27.8': + '@changesets/cli@2.27.9': dependencies: '@changesets/apply-release-plan': 7.0.5 '@changesets/assemble-release-plan': 6.0.4 @@ -2495,14 +2481,12 @@ snapshots: '@changesets/types': 6.0.0 '@changesets/write': 0.3.2 '@manypkg/get-packages': 1.1.3 - '@types/semver': 7.5.8 ansi-colors: 4.1.3 ci-info: 3.9.0 enquirer: 2.4.1 external-editor: 3.1.0 fs-extra: 7.0.1 mri: 1.2.0 - outdent: 0.5.0 p-limit: 2.3.0 package-manager-detector: 0.2.0 picocolors: 1.1.0 @@ -2662,46 +2646,130 @@ snapshots: '@esbuild/win32-x64@0.21.5': optional: true - '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': + '@eslint-community/eslint-utils@4.4.0(eslint@9.15.0(jiti@2.4.0))': dependencies: - eslint: 8.57.0 + eslint: 9.15.0(jiti@2.4.0) eslint-visitor-keys: 3.4.3 - '@eslint-community/eslint-utils@4.4.0(eslint@9.15.0)': + '@eslint-community/regexpp@4.12.1': {} + + '@eslint-react/ast@1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2)': dependencies: - eslint: 9.15.0 - eslint-visitor-keys: 3.4.3 + '@eslint-react/tools': 1.16.2 + '@eslint-react/types': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.6.2) + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + birecord: 0.1.1 + string-ts: 2.2.0 + ts-pattern: 5.5.0 + transitivePeerDependencies: + - eslint + - supports-color + - typescript - '@eslint-community/regexpp@4.10.1': {} + '@eslint-react/core@1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2)': + dependencies: + '@eslint-react/ast': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/jsx': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/shared': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/tools': 1.16.2 + '@eslint-react/types': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/var': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/type-utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + birecord: 0.1.1 + short-unique-id: 5.2.0 + ts-pattern: 5.5.0 + transitivePeerDependencies: + - eslint + - supports-color + - typescript - '@eslint-community/regexpp@4.11.1': {} + '@eslint-react/eslint-plugin@1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2)': + dependencies: + '@eslint-react/shared': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/tools': 1.16.2 + '@eslint-react/types': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/type-utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + eslint: 9.15.0(jiti@2.4.0) + eslint-plugin-react-debug: 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + eslint-plugin-react-dom: 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + eslint-plugin-react-hooks-extra: 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + eslint-plugin-react-naming-convention: 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + eslint-plugin-react-web-api: 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + eslint-plugin-react-x: 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + optionalDependencies: + typescript: 5.6.2 + transitivePeerDependencies: + - supports-color - '@eslint-community/regexpp@4.12.1': {} + '@eslint-react/jsx@1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2)': + dependencies: + '@eslint-react/ast': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/tools': 1.16.2 + '@eslint-react/types': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/var': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + ts-pattern: 5.5.0 + transitivePeerDependencies: + - eslint + - supports-color + - typescript - '@eslint/config-array@0.19.0': + '@eslint-react/shared@1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2)': dependencies: - '@eslint/object-schema': 2.1.4 - debug: 4.3.7 - minimatch: 3.1.2 + '@eslint-react/tools': 1.16.2 + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + picomatch: 4.0.2 transitivePeerDependencies: + - eslint - supports-color + - typescript - '@eslint/core@0.9.0': {} + '@eslint-react/tools@1.16.2': {} - '@eslint/eslintrc@2.1.4': + '@eslint-react/types@1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2)': dependencies: - ajv: 6.12.6 - debug: 4.3.5 - espree: 9.6.1 - globals: 13.24.0 - ignore: 5.3.2 - import-fresh: 3.3.0 - js-yaml: 4.1.0 + '@eslint-react/tools': 1.16.2 + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + transitivePeerDependencies: + - eslint + - supports-color + - typescript + + '@eslint-react/var@1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2)': + dependencies: + '@eslint-react/ast': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/tools': 1.16.2 + '@eslint-react/types': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + ts-pattern: 5.5.0 + transitivePeerDependencies: + - eslint + - supports-color + - typescript + + '@eslint/config-array@0.19.0': + dependencies: + '@eslint/object-schema': 2.1.4 + debug: 4.3.7 minimatch: 3.1.2 - strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color + '@eslint/core@0.9.0': {} + '@eslint/eslintrc@3.2.0': dependencies: ajv: 6.12.6 @@ -2716,8 +2784,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@8.57.0': {} - '@eslint/js@9.15.0': {} '@eslint/object-schema@2.1.4': {} @@ -2733,18 +2799,8 @@ snapshots: '@humanfs/core': 0.19.1 '@humanwhocodes/retry': 0.3.1 - '@humanwhocodes/config-array@0.11.14': - dependencies: - '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.5 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - '@humanwhocodes/module-importer@1.0.1': {} - '@humanwhocodes/object-schema@2.0.3': {} - '@humanwhocodes/retry@0.3.1': {} '@humanwhocodes/retry@0.4.1': {} @@ -2846,13 +2902,30 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.22.5': optional: true - '@rtsao/scc@1.1.0': {} + '@rtsao/scc@1.1.0': + optional: true + + '@types/confusing-browser-globals@1.0.3': {} + + '@types/eslint-plugin-jsx-a11y@6.10.0': + dependencies: + '@types/eslint': 9.6.1 + + '@types/eslint@9.6.1': + dependencies: + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 + + '@types/eslint__js@8.42.3': + dependencies: + '@types/eslint': 9.6.1 '@types/estree@1.0.6': {} '@types/json-schema@7.0.15': {} - '@types/json5@0.0.29': {} + '@types/json5@0.0.29': + optional: true '@types/node@12.20.55': {} @@ -2863,22 +2936,20 @@ snapshots: '@types/prop-types@15.7.13': {} - '@types/react@18.3.10': + '@types/react@18.3.12': dependencies: '@types/prop-types': 15.7.13 csstype: 3.1.3 - '@types/semver@7.5.8': {} - - '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint@9.15.0)(typescript@5.6.2)': + '@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2))(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2)': dependencies: - '@eslint-community/regexpp': 4.11.1 - '@typescript-eslint/parser': 7.18.0(eslint@9.15.0)(typescript@5.6.2) - '@typescript-eslint/scope-manager': 7.18.0 - '@typescript-eslint/type-utils': 7.18.0(eslint@9.15.0)(typescript@5.6.2) - '@typescript-eslint/utils': 7.18.0(eslint@9.15.0)(typescript@5.6.2) - '@typescript-eslint/visitor-keys': 7.18.0 - eslint: 9.15.0 + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/type-utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/visitor-keys': 8.15.0 + eslint: 9.15.0(jiti@2.4.0) graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 @@ -2888,72 +2959,44 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2)': + '@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2)': dependencies: - '@typescript-eslint/scope-manager': 7.18.0 - '@typescript-eslint/types': 7.18.0 - '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.6.2) - '@typescript-eslint/visitor-keys': 7.18.0 + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.6.2) + '@typescript-eslint/visitor-keys': 8.15.0 debug: 4.3.7 - eslint: 9.15.0 + eslint: 9.15.0(jiti@2.4.0) optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@5.62.0': - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - - '@typescript-eslint/scope-manager@7.18.0': - dependencies: - '@typescript-eslint/types': 7.18.0 - '@typescript-eslint/visitor-keys': 7.18.0 - - '@typescript-eslint/scope-manager@8.7.0': + '@typescript-eslint/scope-manager@8.15.0': dependencies: - '@typescript-eslint/types': 8.7.0 - '@typescript-eslint/visitor-keys': 8.7.0 + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/visitor-keys': 8.15.0 - '@typescript-eslint/type-utils@7.18.0(eslint@9.15.0)(typescript@5.6.2)': + '@typescript-eslint/type-utils@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2)': dependencies: - '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.6.2) - '@typescript-eslint/utils': 7.18.0(eslint@9.15.0)(typescript@5.6.2) + '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.6.2) + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) debug: 4.3.7 - eslint: 9.15.0 + eslint: 9.15.0(jiti@2.4.0) ts-api-utils: 1.3.0(typescript@5.6.2) optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@5.62.0': {} - - '@typescript-eslint/types@7.18.0': {} - - '@typescript-eslint/types@8.7.0': {} - - '@typescript-eslint/typescript-estree@5.62.0(typescript@5.6.2)': - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.7 - globby: 11.1.0 - is-glob: 4.0.3 - semver: 7.6.3 - tsutils: 3.21.0(typescript@5.6.2) - optionalDependencies: - typescript: 5.6.2 - transitivePeerDependencies: - - supports-color + '@typescript-eslint/types@8.15.0': {} - '@typescript-eslint/typescript-estree@7.18.0(typescript@5.6.2)': + '@typescript-eslint/typescript-estree@8.15.0(typescript@5.6.2)': dependencies: - '@typescript-eslint/types': 7.18.0 - '@typescript-eslint/visitor-keys': 7.18.0 + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/visitor-keys': 8.15.0 debug: 4.3.7 - globby: 11.1.0 + fast-glob: 3.3.2 is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.6.3 @@ -2963,133 +3006,75 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/typescript-estree@8.7.0(typescript@5.6.2)': + '@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2)': dependencies: - '@typescript-eslint/types': 8.7.0 - '@typescript-eslint/visitor-keys': 8.7.0 - debug: 4.3.7 - fast-glob: 3.3.2 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.6.3 - ts-api-utils: 1.3.0(typescript@5.6.2) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.15.0(jiti@2.4.0)) + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.6.2) + eslint: 9.15.0(jiti@2.4.0) optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@5.62.0(eslint@9.15.0)(typescript@5.6.2)': - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.15.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 5.62.0 - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.6.2) - eslint: 9.15.0 - eslint-scope: 5.1.1 - semver: 7.6.3 - transitivePeerDependencies: - - supports-color - - typescript - - '@typescript-eslint/utils@7.18.0(eslint@9.15.0)(typescript@5.6.2)': - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.15.0) - '@typescript-eslint/scope-manager': 7.18.0 - '@typescript-eslint/types': 7.18.0 - '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.6.2) - eslint: 9.15.0 - transitivePeerDependencies: - - supports-color - - typescript - - '@typescript-eslint/utils@8.7.0(eslint@9.15.0)(typescript@5.6.2)': - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.15.0) - '@typescript-eslint/scope-manager': 8.7.0 - '@typescript-eslint/types': 8.7.0 - '@typescript-eslint/typescript-estree': 8.7.0(typescript@5.6.2) - eslint: 9.15.0 - transitivePeerDependencies: - - supports-color - - typescript - - '@typescript-eslint/visitor-keys@5.62.0': - dependencies: - '@typescript-eslint/types': 5.62.0 - eslint-visitor-keys: 3.4.3 - - '@typescript-eslint/visitor-keys@7.18.0': - dependencies: - '@typescript-eslint/types': 7.18.0 - eslint-visitor-keys: 3.4.3 - - '@typescript-eslint/visitor-keys@8.7.0': + '@typescript-eslint/visitor-keys@8.15.0': dependencies: - '@typescript-eslint/types': 8.7.0 - eslint-visitor-keys: 3.4.3 - - '@ungap/structured-clone@1.2.0': {} + '@typescript-eslint/types': 8.15.0 + eslint-visitor-keys: 4.2.0 - '@vitest/eslint-plugin@1.1.10(@typescript-eslint/utils@8.7.0(eslint@9.15.0)(typescript@5.6.2))(eslint@9.15.0)(typescript@5.6.2)(vitest@2.1.1(@types/node@22.7.4))': + '@vitest/eslint-plugin@1.1.10(@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2))(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2)(vitest@2.1.5(@types/node@22.7.4))': dependencies: - '@typescript-eslint/utils': 8.7.0(eslint@9.15.0)(typescript@5.6.2) - eslint: 9.15.0 + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + eslint: 9.15.0(jiti@2.4.0) optionalDependencies: typescript: 5.6.2 - vitest: 2.1.1(@types/node@22.7.4) + vitest: 2.1.5(@types/node@22.7.4) - '@vitest/expect@2.1.1': + '@vitest/expect@2.1.5': dependencies: - '@vitest/spy': 2.1.1 - '@vitest/utils': 2.1.1 - chai: 5.1.1 + '@vitest/spy': 2.1.5 + '@vitest/utils': 2.1.5 + chai: 5.1.2 tinyrainbow: 1.2.0 - '@vitest/mocker@2.1.1(@vitest/spy@2.1.1)(vite@5.4.8(@types/node@22.7.4))': + '@vitest/mocker@2.1.5(vite@5.4.8(@types/node@22.7.4))': dependencies: - '@vitest/spy': 2.1.1 + '@vitest/spy': 2.1.5 estree-walker: 3.0.3 - magic-string: 0.30.11 + magic-string: 0.30.13 optionalDependencies: vite: 5.4.8(@types/node@22.7.4) - '@vitest/pretty-format@2.1.1': + '@vitest/pretty-format@2.1.5': dependencies: tinyrainbow: 1.2.0 - '@vitest/runner@2.1.1': + '@vitest/runner@2.1.5': dependencies: - '@vitest/utils': 2.1.1 + '@vitest/utils': 2.1.5 pathe: 1.1.2 - '@vitest/snapshot@2.1.1': + '@vitest/snapshot@2.1.5': dependencies: - '@vitest/pretty-format': 2.1.1 - magic-string: 0.30.11 + '@vitest/pretty-format': 2.1.5 + magic-string: 0.30.13 pathe: 1.1.2 - '@vitest/spy@2.1.1': + '@vitest/spy@2.1.5': dependencies: tinyspy: 3.0.2 - '@vitest/utils@2.1.1': + '@vitest/utils@2.1.5': dependencies: - '@vitest/pretty-format': 2.1.1 - loupe: 3.1.1 + '@vitest/pretty-format': 2.1.5 + loupe: 3.1.2 tinyrainbow: 1.2.0 - acorn-jsx@5.3.2(acorn@8.12.0): - dependencies: - acorn: 8.12.0 - acorn-jsx@5.3.2(acorn@8.14.0): dependencies: acorn: 8.14.0 - acorn@8.12.0: {} - acorn@8.12.1: {} acorn@8.14.0: {} @@ -3150,6 +3135,7 @@ snapshots: es-errors: 1.3.0 es-object-atoms: 1.0.0 es-shim-unscopables: 1.0.2 + optional: true array.prototype.flat@1.3.2: dependencies: @@ -3202,6 +3188,8 @@ snapshots: dependencies: is-windows: 1.0.2 + birecord@0.1.1: {} + brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 @@ -3231,7 +3219,7 @@ snapshots: callsites@3.1.0: {} - chai@5.1.1: + chai@5.1.2: dependencies: assertion-error: 2.0.1 check-error: 2.1.1 @@ -3274,12 +3262,6 @@ snapshots: shebang-command: 1.2.0 which: 1.3.1 - cross-spawn@7.0.3: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -3319,10 +3301,6 @@ snapshots: dependencies: ms: 2.1.3 - debug@4.3.5: - dependencies: - ms: 2.1.2 - debug@4.3.7: dependencies: ms: 2.1.3 @@ -3446,6 +3424,8 @@ snapshots: iterator.prototype: 1.1.3 safe-array-concat: 1.1.2 + es-module-lexer@1.5.4: {} + es-object-atoms@1.0.0: dependencies: es-errors: 1.3.0 @@ -3494,44 +3474,11 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-compat-utils@0.5.1(eslint@9.15.0): + eslint-compat-utils@0.5.1(eslint@9.15.0(jiti@2.4.0)): dependencies: - eslint: 9.15.0 + eslint: 9.15.0(jiti@2.4.0) semver: 7.6.3 - eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.31.0)(eslint@9.15.0): - dependencies: - confusing-browser-globals: 1.0.11 - eslint: 9.15.0 - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0) - object.assign: 4.1.5 - object.entries: 1.1.8 - semver: 6.3.1 - - eslint-config-airbnb-typescript@18.0.0(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint@9.15.0)(typescript@5.6.2))(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint-plugin-import@2.31.0)(eslint@9.15.0): - dependencies: - '@typescript-eslint/eslint-plugin': 7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint@9.15.0)(typescript@5.6.2) - '@typescript-eslint/parser': 7.18.0(eslint@9.15.0)(typescript@5.6.2) - eslint: 9.15.0 - eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.31.0)(eslint@9.15.0) - transitivePeerDependencies: - - eslint-plugin-import - - eslint-config-airbnb@19.0.4(eslint-plugin-import@2.31.0)(eslint-plugin-jsx-a11y@6.10.2(eslint@9.15.0))(eslint-plugin-react-hooks@5.0.0(eslint@9.15.0))(eslint-plugin-react@7.37.2(eslint@9.15.0))(eslint@9.15.0): - dependencies: - eslint: 9.15.0 - eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.31.0)(eslint@9.15.0) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0) - eslint-plugin-jsx-a11y: 6.10.2(eslint@9.15.0) - eslint-plugin-react: 7.37.2(eslint@9.15.0) - eslint-plugin-react-hooks: 5.0.0(eslint@9.15.0) - object.assign: 4.1.5 - object.entries: 1.1.8 - - eslint-config-prettier@9.1.0(eslint@9.15.0): - dependencies: - eslint: 9.15.0 - eslint-import-resolver-node@0.3.9: dependencies: debug: 3.2.7 @@ -3540,37 +3487,55 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint-plugin-import@2.31.0)(eslint@9.15.0): + eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2))(eslint-plugin-import-x@4.4.3(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2))(eslint-plugin-import@2.31.0)(eslint@9.15.0(jiti@2.4.0)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.3.7 enhanced-resolve: 5.17.1 - eslint: 9.15.0 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0) + eslint: 9.15.0(jiti@2.4.0) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.0)) fast-glob: 3.3.2 get-tsconfig: 4.8.1 is-bun-module: 1.2.1 is-glob: 4.0.3 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.0)) + eslint-plugin-import-x: 4.4.3(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) transitivePeerDependencies: - '@typescript-eslint/parser' - eslint-import-resolver-node - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.0)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 7.18.0(eslint@9.15.0)(typescript@5.6.2) - eslint: 9.15.0 + '@typescript-eslint/parser': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + eslint: 9.15.0(jiti@2.4.0) + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2))(eslint-plugin-import-x@4.4.3(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2))(eslint-plugin-import@2.31.0)(eslint@9.15.0(jiti@2.4.0)) + transitivePeerDependencies: + - supports-color + + eslint-plugin-import-x@4.4.3(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2): + dependencies: + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + debug: 4.3.7 + doctrine: 3.0.0 + eslint: 9.15.0(jiti@2.4.0) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint-plugin-import@2.31.0)(eslint@9.15.0) + get-tsconfig: 4.8.1 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.3 + stable-hash: 0.0.4 + tslib: 2.7.0 transitivePeerDependencies: - supports-color + - typescript - eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.0)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -3579,9 +3544,9 @@ snapshots: array.prototype.flatmap: 1.3.2 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.15.0 + eslint: 9.15.0(jiti@2.4.0) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.0)) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3 @@ -3593,23 +3558,24 @@ snapshots: string.prototype.trimend: 1.0.8 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 7.18.0(eslint@9.15.0)(typescript@5.6.2) + '@typescript-eslint/parser': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color + optional: true - eslint-plugin-jest@28.9.0(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint@9.15.0)(typescript@5.6.2))(eslint@9.15.0)(typescript@5.6.2): + eslint-plugin-jest@28.9.0(@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2))(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2))(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2): dependencies: - '@typescript-eslint/utils': 8.7.0(eslint@9.15.0)(typescript@5.6.2) - eslint: 9.15.0 + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + eslint: 9.15.0(jiti@2.4.0) optionalDependencies: - '@typescript-eslint/eslint-plugin': 7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.15.0)(typescript@5.6.2))(eslint@9.15.0)(typescript@5.6.2) + '@typescript-eslint/eslint-plugin': 8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2))(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) transitivePeerDependencies: - supports-color - typescript - eslint-plugin-jsx-a11y@6.10.2(eslint@9.15.0): + eslint-plugin-jsx-a11y@6.10.2(eslint@9.15.0(jiti@2.4.0)): dependencies: aria-query: 5.3.2 array-includes: 3.1.8 @@ -3619,7 +3585,7 @@ snapshots: axobject-query: 4.1.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 9.15.0 + eslint: 9.15.0(jiti@2.4.0) hasown: 2.0.2 jsx-ast-utils: 3.3.5 language-tags: 1.0.9 @@ -3628,16 +3594,136 @@ snapshots: safe-regex-test: 1.0.3 string.prototype.includes: 2.0.1 - eslint-plugin-playwright@2.1.0(eslint@9.15.0): + eslint-plugin-playwright@2.1.0(eslint@9.15.0(jiti@2.4.0)): dependencies: - eslint: 9.15.0 + eslint: 9.15.0(jiti@2.4.0) globals: 13.24.0 - eslint-plugin-react-hooks@5.0.0(eslint@9.15.0): + eslint-plugin-react-debug@1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2): + dependencies: + '@eslint-react/ast': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/core': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/jsx': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/shared': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/tools': 1.16.2 + '@eslint-react/types': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/var': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/type-utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + eslint: 9.15.0(jiti@2.4.0) + string-ts: 2.2.0 + ts-pattern: 5.5.0 + optionalDependencies: + typescript: 5.6.2 + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-dom@1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2): + dependencies: + '@eslint-react/ast': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/core': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/jsx': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/shared': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/tools': 1.16.2 + '@eslint-react/types': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/var': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + eslint: 9.15.0(jiti@2.4.0) + ts-pattern: 5.5.0 + optionalDependencies: + typescript: 5.6.2 + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-hooks-extra@1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2): + dependencies: + '@eslint-react/ast': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/core': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/jsx': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/shared': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/tools': 1.16.2 + '@eslint-react/types': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/var': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/type-utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + eslint: 9.15.0(jiti@2.4.0) + ts-pattern: 5.5.0 + optionalDependencies: + typescript: 5.6.2 + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-hooks@5.0.0(eslint@9.15.0(jiti@2.4.0)): dependencies: - eslint: 9.15.0 + eslint: 9.15.0(jiti@2.4.0) - eslint-plugin-react@7.37.2(eslint@9.15.0): + eslint-plugin-react-naming-convention@1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2): + dependencies: + '@eslint-react/ast': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/core': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/jsx': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/shared': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/tools': 1.16.2 + '@eslint-react/types': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/type-utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + eslint: 9.15.0(jiti@2.4.0) + ts-pattern: 5.5.0 + optionalDependencies: + typescript: 5.6.2 + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-web-api@1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2): + dependencies: + '@eslint-react/ast': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/core': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/jsx': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/shared': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/tools': 1.16.2 + '@eslint-react/types': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/var': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + birecord: 0.1.1 + eslint: 9.15.0(jiti@2.4.0) + ts-pattern: 5.5.0 + optionalDependencies: + typescript: 5.6.2 + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-x@1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2): + dependencies: + '@eslint-react/ast': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/core': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/jsx': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/shared': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/tools': 1.16.2 + '@eslint-react/types': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@eslint-react/var': 1.16.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/type-utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + eslint: 9.15.0(jiti@2.4.0) + is-immutable-type: 5.0.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + ts-pattern: 5.5.0 + optionalDependencies: + typescript: 5.6.2 + transitivePeerDependencies: + - supports-color + + eslint-plugin-react@7.37.2(eslint@9.15.0(jiti@2.4.0)): dependencies: array-includes: 3.1.8 array.prototype.findlast: 1.2.5 @@ -3645,7 +3731,7 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.2.0 - eslint: 9.15.0 + eslint: 9.15.0(jiti@2.4.0) estraverse: 5.3.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 @@ -3659,12 +3745,12 @@ snapshots: string.prototype.matchall: 4.0.11 string.prototype.repeat: 1.0.0 - eslint-plugin-svelte@2.46.0(eslint@9.15.0)(svelte@4.2.19): + eslint-plugin-svelte@2.46.0(eslint@9.15.0(jiti@2.4.0))(svelte@4.2.19): dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.15.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.15.0(jiti@2.4.0)) '@jridgewell/sourcemap-codec': 1.5.0 - eslint: 9.15.0 - eslint-compat-utils: 0.5.1(eslint@9.15.0) + eslint: 9.15.0(jiti@2.4.0) + eslint-compat-utils: 0.5.1(eslint@9.15.0(jiti@2.4.0)) esutils: 2.0.3 known-css-properties: 0.35.0 postcss: 8.4.47 @@ -3678,19 +3764,15 @@ snapshots: transitivePeerDependencies: - ts-node - eslint-plugin-testing-library@6.5.0(eslint@9.15.0)(typescript@5.6.2): + eslint-plugin-testing-library@7.0.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2): dependencies: - '@typescript-eslint/utils': 5.62.0(eslint@9.15.0)(typescript@5.6.2) - eslint: 9.15.0 + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + eslint: 9.15.0(jiti@2.4.0) transitivePeerDependencies: - supports-color - typescript - eslint-scope@5.1.1: - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - eslint-scope@7.2.2: dependencies: esrecurse: 4.3.0 @@ -3705,52 +3787,9 @@ snapshots: eslint-visitor-keys@4.2.0: {} - eslint@8.57.0: - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint-community/regexpp': 4.10.1 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.5 - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.5.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 - ignore: 5.3.1 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - - eslint@9.15.0: + eslint@9.15.0(jiti@2.4.0): dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.15.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.15.0(jiti@2.4.0)) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.19.0 '@eslint/core': 0.9.0 @@ -3784,6 +3823,8 @@ snapshots: minimatch: 3.1.2 natural-compare: 1.4.0 optionator: 0.9.4 + optionalDependencies: + jiti: 2.4.0 transitivePeerDependencies: - supports-color @@ -3795,8 +3836,8 @@ snapshots: espree@9.6.1: dependencies: - acorn: 8.12.0 - acorn-jsx: 5.3.2(acorn@8.12.0) + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) eslint-visitor-keys: 3.4.3 esprima@4.0.1: {} @@ -3809,8 +3850,6 @@ snapshots: dependencies: estraverse: 5.3.0 - estraverse@4.3.0: {} - estraverse@5.3.0: {} estree-walker@3.0.3: @@ -3819,6 +3858,8 @@ snapshots: esutils@2.0.3: {} + expect-type@1.1.0: {} + extendable-error@0.1.7: {} external-editor@3.1.0: @@ -3845,9 +3886,9 @@ snapshots: dependencies: reusify: 1.0.4 - file-entry-cache@6.0.1: - dependencies: - flat-cache: 3.2.0 + fdir@6.4.2(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 file-entry-cache@8.0.0: dependencies: @@ -3871,12 +3912,6 @@ snapshots: locate-path: 6.0.0 path-exists: 4.0.0 - flat-cache@3.2.0: - dependencies: - flatted: 3.3.1 - keyv: 4.5.4 - rimraf: 3.0.2 - flat-cache@4.0.1: dependencies: flatted: 3.3.1 @@ -3900,8 +3935,6 @@ snapshots: jsonfile: 4.0.0 universalify: 0.1.2 - fs.realpath@1.0.0: {} - fsevents@2.3.3: optional: true @@ -3948,21 +3981,14 @@ snapshots: dependencies: is-glob: 4.0.3 - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - globals@13.24.0: dependencies: type-fest: 0.20.2 globals@14.0.0: {} + globals@15.12.0: {} + globalthis@1.0.4: dependencies: define-properties: 1.2.1 @@ -3977,14 +4003,6 @@ snapshots: merge2: 1.4.1 slash: 3.0.0 - globby@13.2.2: - dependencies: - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.2 - merge2: 1.4.1 - slash: 4.0.0 - gopd@1.0.1: dependencies: get-intrinsic: 1.2.4 @@ -4019,8 +4037,6 @@ snapshots: dependencies: safer-buffer: 2.1.2 - ignore@5.3.1: {} - ignore@5.3.2: {} import-fresh@3.3.0: @@ -4030,13 +4046,6 @@ snapshots: imurmurhash@0.1.4: {} - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - inherits@2.0.4: {} - internal-slot@1.0.7: dependencies: es-errors: 1.3.0 @@ -4093,6 +4102,16 @@ snapshots: dependencies: is-extglob: 2.1.1 + is-immutable-type@5.0.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2): + dependencies: + '@typescript-eslint/type-utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + eslint: 9.15.0(jiti@2.4.0) + ts-api-utils: 1.3.0(typescript@5.6.2) + ts-declaration-location: 1.0.4(typescript@5.6.2) + typescript: 5.6.2 + transitivePeerDependencies: + - supports-color + is-map@2.0.3: {} is-negative-zero@2.0.3: {} @@ -4103,8 +4122,6 @@ snapshots: is-number@7.0.0: {} - is-path-inside@3.0.3: {} - is-plain-obj@4.1.0: {} is-reference@3.0.2: @@ -4163,6 +4180,9 @@ snapshots: reflect.getprototypeof: 1.0.6 set-function-name: 2.0.2 + jiti@2.4.0: + optional: true + js-tokens@4.0.0: {} js-yaml@3.14.1: @@ -4183,6 +4203,7 @@ snapshots: json5@1.0.2: dependencies: minimist: 1.2.8 + optional: true jsonfile@4.0.0: optionalDependencies: @@ -4236,6 +4257,8 @@ snapshots: dependencies: get-func-name: 2.0.2 + loupe@3.1.2: {} + lru-cache@4.1.5: dependencies: pseudomap: 1.0.2 @@ -4245,6 +4268,10 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 + magic-string@0.30.13: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + mdn-data@2.0.30: {} merge2@1.4.1: {} @@ -4259,6 +4286,10 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 + minimatch@10.0.1: + dependencies: + brace-expansion: 2.0.1 + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 @@ -4267,12 +4298,11 @@ snapshots: dependencies: brace-expansion: 2.0.1 - minimist@1.2.8: {} + minimist@1.2.8: + optional: true mri@1.2.0: {} - ms@2.1.2: {} - ms@2.1.3: {} mvdan-sh@0.10.1: {} @@ -4312,6 +4342,7 @@ snapshots: call-bind: 1.0.7 define-properties: 1.2.1 es-abstract: 1.23.3 + optional: true object.values@1.2.0: dependencies: @@ -4319,10 +4350,6 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.0.0 - once@1.4.0: - dependencies: - wrappy: 1.0.2 - optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -4368,8 +4395,6 @@ snapshots: path-exists@4.0.0: {} - path-is-absolute@1.0.1: {} - path-key@3.1.1: {} path-parse@1.0.7: {} @@ -4390,6 +4415,8 @@ snapshots: picomatch@2.3.1: {} + picomatch@4.0.2: {} + pify@4.0.1: {} possible-typed-array-names@1.0.0: {} @@ -4427,10 +4454,10 @@ snapshots: prettier: 3.3.3 typescript: 5.6.2 - prettier-plugin-packagejson@2.5.2(prettier@3.3.3): + prettier-plugin-packagejson@2.5.6(prettier@3.3.3): dependencies: - sort-package-json: 2.10.1 - synckit: 0.9.1 + sort-package-json: 2.12.0 + synckit: 0.9.2 optionalDependencies: prettier: 3.3.3 @@ -4513,10 +4540,6 @@ snapshots: reusify@1.0.4: {} - rimraf@3.0.2: - dependencies: - glob: 7.2.3 - rollup@4.22.5: dependencies: '@types/estree': 1.0.6 @@ -4594,6 +4617,8 @@ snapshots: shebang-regex@3.0.0: {} + short-unique-id@5.2.0: {} + side-channel@1.0.6: dependencies: call-bind: 1.0.7 @@ -4607,20 +4632,18 @@ snapshots: slash@3.0.0: {} - slash@4.0.0: {} - sort-object-keys@1.1.3: {} - sort-package-json@2.10.1: + sort-package-json@2.12.0: dependencies: detect-indent: 7.0.1 detect-newline: 4.0.1 get-stdin: 9.0.0 git-hooks-list: 3.1.0 - globby: 13.2.2 is-plain-obj: 4.1.0 semver: 7.6.3 sort-object-keys: 1.1.3 + tinyglobby: 0.2.10 source-map-js@1.2.1: {} @@ -4631,9 +4654,13 @@ snapshots: sprintf-js@1.0.3: {} + stable-hash@0.0.4: {} + stackback@0.0.2: {} - std-env@3.7.0: {} + std-env@3.8.0: {} + + string-ts@2.2.0: {} string.prototype.includes@2.0.1: dependencies: @@ -4721,7 +4748,7 @@ snapshots: magic-string: 0.30.11 periscopic: 3.1.0 - synckit@0.9.1: + synckit@0.9.2: dependencies: '@pkgr/core': 0.1.1 tslib: 2.7.0 @@ -4730,11 +4757,14 @@ snapshots: term-size@2.2.1: {} - text-table@0.2.0: {} - tinybench@2.9.0: {} - tinyexec@0.3.0: {} + tinyexec@0.3.1: {} + + tinyglobby@0.2.10: + dependencies: + fdir: 6.4.2(picomatch@4.0.2) + picomatch: 4.0.2 tinypool@1.0.1: {} @@ -4754,22 +4784,23 @@ snapshots: dependencies: typescript: 5.6.2 + ts-declaration-location@1.0.4(typescript@5.6.2): + dependencies: + minimatch: 10.0.1 + typescript: 5.6.2 + + ts-pattern@5.5.0: {} + tsconfig-paths@3.15.0: dependencies: '@types/json5': 0.0.29 json5: 1.0.2 minimist: 1.2.8 strip-bom: 3.0.0 - - tslib@1.14.1: {} + optional: true tslib@2.7.0: {} - tsutils@3.21.0(typescript@5.6.2): - dependencies: - tslib: 1.14.1 - typescript: 5.6.2 - turbo-darwin-64@2.1.3: optional: true @@ -4835,6 +4866,17 @@ snapshots: is-typed-array: 1.1.13 possible-typed-array-names: 1.0.0 + typescript-eslint@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2): + dependencies: + '@typescript-eslint/eslint-plugin': 8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2))(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/parser': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.2) + eslint: 9.15.0(jiti@2.4.0) + optionalDependencies: + typescript: 5.6.2 + transitivePeerDependencies: + - supports-color + typescript@5.6.2: {} unbox-primitive@1.0.2: @@ -4855,10 +4897,11 @@ snapshots: util-deprecate@1.0.2: {} - vite-node@2.1.1(@types/node@22.7.4): + vite-node@2.1.5(@types/node@22.7.4): dependencies: cac: 6.7.14 debug: 4.3.7 + es-module-lexer: 1.5.4 pathe: 1.1.2 vite: 5.4.8(@types/node@22.7.4) transitivePeerDependencies: @@ -4881,26 +4924,27 @@ snapshots: '@types/node': 22.7.4 fsevents: 2.3.3 - vitest@2.1.1(@types/node@22.7.4): + vitest@2.1.5(@types/node@22.7.4): dependencies: - '@vitest/expect': 2.1.1 - '@vitest/mocker': 2.1.1(@vitest/spy@2.1.1)(vite@5.4.8(@types/node@22.7.4)) - '@vitest/pretty-format': 2.1.1 - '@vitest/runner': 2.1.1 - '@vitest/snapshot': 2.1.1 - '@vitest/spy': 2.1.1 - '@vitest/utils': 2.1.1 - chai: 5.1.1 + '@vitest/expect': 2.1.5 + '@vitest/mocker': 2.1.5(vite@5.4.8(@types/node@22.7.4)) + '@vitest/pretty-format': 2.1.5 + '@vitest/runner': 2.1.5 + '@vitest/snapshot': 2.1.5 + '@vitest/spy': 2.1.5 + '@vitest/utils': 2.1.5 + chai: 5.1.2 debug: 4.3.7 - magic-string: 0.30.11 + expect-type: 1.1.0 + magic-string: 0.30.13 pathe: 1.1.2 - std-env: 3.7.0 + std-env: 3.8.0 tinybench: 2.9.0 - tinyexec: 0.3.0 + tinyexec: 0.3.1 tinypool: 1.0.1 tinyrainbow: 1.2.0 vite: 5.4.8(@types/node@22.7.4) - vite-node: 2.1.1(@types/node@22.7.4) + vite-node: 2.1.5(@types/node@22.7.4) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.7.4 @@ -4968,8 +5012,6 @@ snapshots: word-wrap@1.2.5: {} - wrappy@1.0.2: {} - yallist@2.1.2: {} yaml@1.10.2: {} diff --git a/test/test-base/.eslintrc.js b/test/test-base/.eslintrc.js deleted file mode 100644 index ce89049..0000000 --- a/test/test-base/.eslintrc.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - root: true, - parserOptions: { - project: "./tsconfig.eslint.json", - }, - extends: ["@qlik/eslint-config", "@qlik/eslint-config/vitest"], - ignorePatterns: ["dist", "coverage"], -}; diff --git a/test/test-base/eslint.config.js b/test/test-base/eslint.config.js new file mode 100644 index 0000000..5241013 --- /dev/null +++ b/test/test-base/eslint.config.js @@ -0,0 +1,17 @@ +import qlik from "@qlik/eslint-config"; + +const config = qlik.compose( + // adds the base config for both JS and TS + ...qlik.configs.recommended, + ...qlik.configs.vitest, + { + rules: { + "no-undef": "off", + "no-console": "off", + "no-magic-numbers": "off", + "@typescript-eslint/no-magic-numbers": "off", + }, + }, +); + +export default config; diff --git a/test/test-base/package.json b/test/test-base/package.json index a76420e..6903b57 100644 --- a/test/test-base/package.json +++ b/test/test-base/package.json @@ -2,19 +2,16 @@ "name": "test-base", "private": true, "description": "Test project for react linting", - "scripts": { - "lint": "ESLINT_USE_FLAT_CONFIG=false eslint ." - }, + "type": "module", + "scripts": {}, "prettier": "@qlik/prettier-config", - "dependencies": { - "react": "^18.3.1" - }, + "dependencies": {}, "devDependencies": { "@qlik/eslint-config": "workspace:*", "@qlik/prettier-config": "workspace:*", "@qlik/tsconfig": "workspace:*", - "@types/react": "^18.3.10", - "eslint": "^8.57.0", - "vitest": "^2.1.1" + "@types/react": "^18.3.11", + "eslint": "^9.15.0", + "vitest": "^2.1.2" } } diff --git a/test/test-base/src/javascript/index.js b/test/test-base/src/javascript/index.js new file mode 100644 index 0000000..72d1773 --- /dev/null +++ b/test/test-base/src/javascript/index.js @@ -0,0 +1,6 @@ +// add some code here to test lint + +// eslint-disable-next-line no-var +var a = 1; + +console.log(a); diff --git a/test/test-base/src/javascript/rules/array-callback-return.js b/test/test-base/src/javascript/rules/array-callback-return.js new file mode 100644 index 0000000..151ed9e --- /dev/null +++ b/test/test-base/src/javascript/rules/array-callback-return.js @@ -0,0 +1,33 @@ +/* eslint-disable no-useless-return */ +/* eslint-disable no-else-return */ +/* eslint-disable consistent-return */ + +// testing array-callback-return rule + +// eslint-disable-next-line array-callback-return +const indexMap = [].reduce((acc, item, index) => { + acc[item] = index; +}, {}); + +console.log(indexMap); + +const nodes = []; + +// eslint-disable-next-line array-callback-return +const foo = Array.from(nodes, (node) => { + if (node.tagName === "DIV") { + return true; + } +}); + +const bar = foo.filter((x) => { + if (x) { + return true; + } else { + return; + } +}); + +console.log(bar); + +export {}; diff --git a/test/test-base/src/javascript/rules/camelcase.js b/test/test-base/src/javascript/rules/camelcase.js new file mode 100644 index 0000000..a9725ac --- /dev/null +++ b/test/test-base/src/javascript/rules/camelcase.js @@ -0,0 +1,52 @@ +/* eslint-disable no-shadow */ +/* eslint-disable no-unused-vars */ + +// eslint-disable-next-line camelcase +import { no_camelcased } from "./submodules/camelcased"; + +// eslint-disable-next-line camelcase +const my_favorite_color = "#112C85"; + +// eslint-disable-next-line camelcase +function do_something() { + // ... +} + +// eslint-disable-next-line camelcase +function foo({ no_camelcased }) { + // ... +} + +// eslint-disable-next-line camelcase +function bar({ isCamelcased: no_camelcased }) { + // ... +} + +// eslint-disable-next-line camelcase +function baz({ no_camelcased = "default value" }) { + // ... +} + +const obj = { + my_pref: 1, +}; + +obj.do_something = function named() { + // ... +}; + +const query = { + category_id: 15, +}; + +const quz = { + foo: 1, + q: query.category_id, +}; + +// eslint-disable-next-line camelcase +const { category_id = 1 } = query; +// eslint-disable-next-line camelcase +const { foo: snake_cased } = bar; +// eslint-disable-next-line camelcase +const { foo: bar_baz = 1 } = quz; diff --git a/test/test-base/src/javascript/rules/consistent-return.js b/test/test-base/src/javascript/rules/consistent-return.js new file mode 100644 index 0000000..b4e3bcb --- /dev/null +++ b/test/test-base/src/javascript/rules/consistent-return.js @@ -0,0 +1,35 @@ +/* eslint-disable no-useless-return */ +/* eslint-disable no-else-return */ +/* eslint-disable no-unused-vars */ + +function doSomething(condition) { + if (condition) { + return true; + } else { + // eslint-disable-next-line consistent-return + return; + } +} + +// eslint-disable-next-line consistent-return +function doSomethingElse(condition) { + if (condition) { + return true; + } +} + +function doSomething1(condition) { + if (condition) { + return true; + } else { + return false; + } +} + +function Foo2() { + if (!(this instanceof Foo2)) { + return new Foo2(); + } + + this.a = 0; +} diff --git a/test/test-base/src/javascript/rules/default-param-last.js b/test/test-base/src/javascript/rules/default-param-last.js new file mode 100644 index 0000000..dfb74ad --- /dev/null +++ b/test/test-base/src/javascript/rules/default-param-last.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line default-param-last +function f(a = 0, b) { + return a + b; +} + +// eslint-disable-next-line default-param-last +function g(a, b = 0, c) { + return a + b + c; +} + +f(2, 1); +g(2, 1); diff --git a/test/test-base/src/javascript/rules/eqeqeq.js b/test/test-base/src/javascript/rules/eqeqeq.js new file mode 100644 index 0000000..1aa5ae3 --- /dev/null +++ b/test/test-base/src/javascript/rules/eqeqeq.js @@ -0,0 +1,33 @@ +const x = 10; + +// eslint-disable-next-line eqeqeq +if (x == 42) { + console.log("Hello"); +} + +const text = "Hello"; +// eslint-disable-next-line no-shadow-restricted-names +const undefined = "World"; + +// eslint-disable-next-line eqeqeq +if (text == "") { + console.log("World"); +} + +const obj = { + stuff: "Hello", + getStuff() { + return this.stuff; + }, +}; + +// eslint-disable-next-line eqeqeq +if (obj.getStuff() != undefined) { + console.log("World"); +} + +const foo = undefined; + +if (foo === null) { + console.log("Hello"); +} diff --git a/test/test-base/src/javascript/rules/func-names.js b/test/test-base/src/javascript/rules/func-names.js new file mode 100644 index 0000000..5af2401 --- /dev/null +++ b/test/test-base/src/javascript/rules/func-names.js @@ -0,0 +1,13 @@ +// incorrect + +// eslint-disable-next-line func-names +const foo = function () { + console.log("foo"); +}; +foo(); + +// ok +const baz = () => { + console.log("baz"); +}; +baz(); diff --git a/test/test-base/src/javascript/rules/grouped-accessor-pairs.js b/test/test-base/src/javascript/rules/grouped-accessor-pairs.js new file mode 100644 index 0000000..3f5ee05 --- /dev/null +++ b/test/test-base/src/javascript/rules/grouped-accessor-pairs.js @@ -0,0 +1,54 @@ +/* eslint-disable max-classes-per-file */ +/* eslint-disable class-methods-use-this */ +/* eslint-disable no-unused-vars */ + +const foo = { + get a() { + return this.val; + }, + b: 1, + + // eslint-disable-next-line grouped-accessor-pairs + set a(value) { + this.val = value; + }, +}; + +const bar = { + set b(value) { + this.val = value; + }, + a: 1, + // eslint-disable-next-line grouped-accessor-pairs + get b() { + return this.val; + }, +}; + +console.log(foo, bar); + +class Foo { + set a(value) { + this.val = value; + } + b() { + console.log("b"); + } + // eslint-disable-next-line grouped-accessor-pairs + get a() { + return this.val; + } +} + +const Bar = class { + static get a() { + return this.val; + } + b() { + console.log("b"); + } + // eslint-disable-next-line grouped-accessor-pairs + static set a(value) { + this.val = value; + } +}; diff --git a/test/test-base/src/javascript/rules/new-cap.js b/test/test-base/src/javascript/rules/new-cap.js new file mode 100644 index 0000000..b08a540 --- /dev/null +++ b/test/test-base/src/javascript/rules/new-cap.js @@ -0,0 +1,8 @@ +/* eslint-disable no-unused-vars */ + +// incorrect +const colleague = Person(); +// eslint-disable-next-line new-cap +const friend = new person(); +// correct +const colleagues = new Person(); diff --git a/test/test-base/src/javascript/rules/no-array-constructor.js b/test/test-base/src/javascript/rules/no-array-constructor.js new file mode 100644 index 0000000..6e02fef --- /dev/null +++ b/test/test-base/src/javascript/rules/no-array-constructor.js @@ -0,0 +1,15 @@ +/* eslint-disable no-new */ + +// eslint-disable-next-line no-array-constructor +Array(); + +// eslint-disable-next-line no-array-constructor +Array(0, 1, 2); + +// eslint-disable-next-line no-array-constructor +new Array(0, 1, 2); + +// eslint-disable-next-line no-array-constructor +Array(...args); + +export default {}; diff --git a/test/test-base/src/javascript/rules/no-await-in-loop.js b/test/test-base/src/javascript/rules/no-await-in-loop.js new file mode 100644 index 0000000..b751c08 --- /dev/null +++ b/test/test-base/src/javascript/rules/no-await-in-loop.js @@ -0,0 +1,13 @@ +// no-await-in-loop + +async function returnsPromise() { + return "value"; +} +async function fn(arr) { + for (const item of arr) { + await Promise.resolve(item); // eslint-disable-line no-await-in-loop + } +} + +fn([1, 2, 3]); +returnsPromise(); diff --git a/test/test-base/src/javascript/rules/no-bitwise.js b/test/test-base/src/javascript/rules/no-bitwise.js new file mode 100644 index 0000000..9ffacd7 --- /dev/null +++ b/test/test-base/src/javascript/rules/no-bitwise.js @@ -0,0 +1,31 @@ +/* eslint-disable no-redeclare */ +/* eslint-disable no-var */ + +// eslint-disable-next-line no-bitwise +var x = y | z; +// eslint-disable-next-line no-bitwise +var x = y & z; +// eslint-disable-next-line no-bitwise +var x = y ^ z; +// eslint-disable-next-line no-bitwise +var x = ~z; +// eslint-disable-next-line no-bitwise +var x = y << z; +// eslint-disable-next-line no-bitwise +var x = y >> z; +// eslint-disable-next-line no-bitwise +var x = y >>> z; +// eslint-disable-next-line no-bitwise +x |= y; +// eslint-disable-next-line no-bitwise +x &= y; +// eslint-disable-next-line no-bitwise +x ^= y; +// eslint-disable-next-line no-bitwise +x <<= y; +// eslint-disable-next-line no-bitwise +x >>= y; +// eslint-disable-next-line no-bitwise +x >>>= y; + +console.log(x); diff --git a/test/test-base/src/javascript/rules/no-constructor-return.js b/test/test-base/src/javascript/rules/no-constructor-return.js new file mode 100644 index 0000000..43a845a --- /dev/null +++ b/test/test-base/src/javascript/rules/no-constructor-return.js @@ -0,0 +1,13 @@ +/* eslint-disable no-unused-vars */ +// no-constructor-return +class A { + constructor(a) { + this.a = a; + // eslint-disable-next-line no-constructor-return + return a; + } + + getA() { + return this.a; + } +} diff --git a/test/test-base/src/javascript/rules/no-duplicate-imports.js b/test/test-base/src/javascript/rules/no-duplicate-imports.js new file mode 100644 index 0000000..74dea8d --- /dev/null +++ b/test/test-base/src/javascript/rules/no-duplicate-imports.js @@ -0,0 +1,6 @@ +import { A } from "./submodules/module-alpha"; // eslint-disable-line import-x/no-duplicates +import { one } from "./submodules/module-num"; +/* prettier-disable */ +import { B } from "./submodules/module-alpha"; // eslint-disable-line import-x/no-duplicates + +console.log(A, one, B); diff --git a/test/test-base/src/javascript/rules/no-eval.js b/test/test-base/src/javascript/rules/no-eval.js new file mode 100644 index 0000000..bb8cd60 --- /dev/null +++ b/test/test-base/src/javascript/rules/no-eval.js @@ -0,0 +1,17 @@ +/* eslint-disable no-unused-vars */ + +const obj = { x: "foo" }; +const key = "x"; + +// eslint-disable-next-line no-eval +const value = eval(`obj.${key}`); + +// eslint-disable-next-line no-eval +(0, eval)("var a = 0"); + +// eslint-disable-next-line no-eval +const foo = eval; +foo("var a = 0"); + +// This `this` is the global object. +this.eval("var a = 0"); diff --git a/test/test-base/src/javascript/rules/no-extra-bind.js b/test/test-base/src/javascript/rules/no-extra-bind.js new file mode 100644 index 0000000..bc16e78 --- /dev/null +++ b/test/test-base/src/javascript/rules/no-extra-bind.js @@ -0,0 +1,38 @@ +/* eslint-disable func-names */ +/* eslint-disable no-unused-vars */ +/* eslint-disable no-redeclare */ +/* eslint-disable no-var */ + +var x = function () { + foo(); +}.bind(bar); // eslint-disable-line no-extra-bind + +var x = (() => { + foo(); +}).bind(bar); // eslint-disable-line no-extra-bind + +var x = (() => { + this.foo(); +}).bind(bar); // eslint-disable-line no-extra-bind + +var x = function () { + (function () { + this.foo(); + })(); +}.bind(bar); // eslint-disable-line no-extra-bind + +var x = function () { + function foo() { + this.bar(); + } +}.bind(baz); // eslint-disable-line no-extra-bind + +// correct + +var x = function () { + this.foo(); +}.bind(bar); + +var x = function (a) { + return a + 1; +}.bind(foo, bar); diff --git a/test/test-base/src/javascript/rules/no-extra-boolean-cast.js b/test/test-base/src/javascript/rules/no-extra-boolean-cast.js new file mode 100644 index 0000000..a0dc6ef --- /dev/null +++ b/test/test-base/src/javascript/rules/no-extra-boolean-cast.js @@ -0,0 +1,37 @@ +/* eslint-disable no-redeclare */ +/* eslint-disable no-unmodified-loop-condition */ +/* eslint-disable no-new-wrappers */ +/* eslint-disable no-var */ + +var foo = !!!bar; // eslint-disable-line no-extra-boolean-cast + +var foo = !!bar ? baz : bat; // eslint-disable-line no-extra-boolean-cast + +var foo = Boolean(!!bar); // eslint-disable-line no-extra-boolean-cast + +var foo = new Boolean(!!bar); // eslint-disable-line no-extra-boolean-cast + +// eslint-disable-next-line no-extra-boolean-cast +if (!!foo) { + // ... +} + +// eslint-disable-next-line no-extra-boolean-cast +if (Boolean(foo)) { + // ... +} + +// eslint-disable-next-line no-extra-boolean-cast +while (!!foo) { + // ... +} + +do { + // ... + // eslint-disable-next-line no-extra-boolean-cast +} while (Boolean(foo)); + +// eslint-disable-next-line no-extra-boolean-cast +for (; !!foo; ) { + // ... +} diff --git a/test/test-base/src/javascript/rules/no-multi-assign.js b/test/test-base/src/javascript/rules/no-multi-assign.js new file mode 100644 index 0000000..495a5eb --- /dev/null +++ b/test/test-base/src/javascript/rules/no-multi-assign.js @@ -0,0 +1,45 @@ +/* eslint-disable max-classes-per-file */ +/* eslint-disable no-unused-vars */ +/* eslint-disable block-scoped-var */ +/* eslint-disable prefer-const */ +/* eslint-disable no-var */ + +{ + // eslint-disable-next-line no-multi-assign + let a = (b = c = 5); + + // eslint-disable-next-line no-multi-assign + const foo = (bar = "baz"); + + // eslint-disable-next-line no-multi-assign + let d = (e = f); + + class Foo { + // eslint-disable-next-line no-multi-assign + a = (b = 10); + } + + // eslint-disable-next-line no-multi-assign + a = b = "quux"; +} + +// correct code +{ + var a = 5; + var b = 5; + var c = 5; + + const foo = "baz"; + const bar = "baz"; + + let d = c; + let e = c; + + class Foo { + a = 10; + b = 10; + } + + a = "quux"; + b = "quux"; +} diff --git a/test/test-base/src/javascript/rules/no-promise-executor-return.js b/test/test-base/src/javascript/rules/no-promise-executor-return.js new file mode 100644 index 0000000..9c3d5e3 --- /dev/null +++ b/test/test-base/src/javascript/rules/no-promise-executor-return.js @@ -0,0 +1,41 @@ +/* eslint-disable no-new */ +/* eslint-disable consistent-return */ + +const a = 1; + +function getSomething(cb) { + if (a === 2) { + cb(new Error("error"), null); + } + cb(null, 1); +} + +new Promise((resolve, reject) => { + if (a === 2) { + return 3; // eslint-disable-line no-promise-executor-return + } + getSomething((err, result) => { + if (err) { + reject(err); + } else { + resolve(result); + } + }); +}); + +new Promise((resolve, reject) => + // eslint-disable-next-line no-promise-executor-return + getSomething((err, data) => { + if (err) { + reject(err); + } else { + resolve(data); + } + }), +); + +new Promise(() => { + return 1; // eslint-disable-line no-promise-executor-return +}); + +new Promise((r) => r(1)); // eslint-disable-line no-promise-executor-return diff --git a/test/test-base/src/javascript/rules/no-redeclare.js b/test/test-base/src/javascript/rules/no-redeclare.js new file mode 100644 index 0000000..e9747e9 --- /dev/null +++ b/test/test-base/src/javascript/rules/no-redeclare.js @@ -0,0 +1,6 @@ +// @ts-nocheck +let x = "nisse"; + +console.log(x); + +let x = "kalle"; // eslint-disable-line no-redeclare diff --git a/test/test-base/src/javascript/rules/no-self-compare.js b/test/test-base/src/javascript/rules/no-self-compare.js new file mode 100644 index 0000000..6ddf9e7 --- /dev/null +++ b/test/test-base/src/javascript/rules/no-self-compare.js @@ -0,0 +1,7 @@ +let x = 10; + +// eslint-disable-next-line no-self-compare +if (x === x) { + x = 20; + console.log(x); +} diff --git a/test/test-base/src/javascript/rules/no-template-curly-in-string.js b/test/test-base/src/javascript/rules/no-template-curly-in-string.js new file mode 100644 index 0000000..e276fd5 --- /dev/null +++ b/test/test-base/src/javascript/rules/no-template-curly-in-string.js @@ -0,0 +1,10 @@ +const aName = "John"; + +// eslint-disable-next-line no-template-curly-in-string +console.log("Hello ${aName}!"); +// eslint-disable-next-line no-template-curly-in-string +console.log("Hello ${aName}!"); +// eslint-disable-next-line no-template-curly-in-string +console.log("Time: ${12 * 60 * 60 * 1000}"); + +console.log(`Hello ${aName}!`); diff --git a/test/test-base/src/javascript/rules/no-unmodified-loop-condition.js b/test/test-base/src/javascript/rules/no-unmodified-loop-condition.js new file mode 100644 index 0000000..223dd13 --- /dev/null +++ b/test/test-base/src/javascript/rules/no-unmodified-loop-condition.js @@ -0,0 +1,51 @@ +/* eslint-disable no-unmodified-loop-condition */ +/* eslint-disable no-var */ + +let node = "something"; + +while (node) { + doSomething(node); +} +node = other; + +for (let j = 0; j < 5; j++) { + doSomething(j); +} + +while (node !== root) { + doSomething(node); +} + +// correct + +while (node) { + doSomething(node); + node = node.parent; +} + +for (var j = 0; j < items.length; ++j) { + doSomething(items[j]); +} + +// OK, the result of this binary expression is changed in this loop. +while (node !== root) { + doSomething(node); + node = node.parent; +} + +// OK, the result of this ternary expression is changed in this loop. +while (node ? A : B) { + doSomething(node); + node = node.parent; +} + +// A property might be a getter which has side effect... +// Or "doSomething" can modify "obj.foo". +while (obj.foo) { + doSomething(obj); +} + +// A function call can return various values. +while (check(obj)) { + doSomething(obj); +} diff --git a/test/test-base/src/javascript/rules/no-unreachable-loop.js b/test/test-base/src/javascript/rules/no-unreachable-loop.js new file mode 100644 index 0000000..34b41e7 --- /dev/null +++ b/test/test-base/src/javascript/rules/no-unreachable-loop.js @@ -0,0 +1,135 @@ +/* eslint-disable no-restricted-syntax */ +/* eslint-disable no-continue */ +/* eslint-disable no-unmodified-loop-condition */ +/* eslint-disable no-else-return */ +// incorrect code + +function doSomething(foo) { + console.log(foo); +} + +let foo = true; + +// eslint-disable-next-line no-unreachable-loop +while (foo) { + doSomething(foo); + foo = foo.parent; + break; +} + +function verify(item) { + if (item) { + return true; + } else { + return false; + } +} + +function verifyList(head) { + const item = head; + // eslint-disable-next-line no-unreachable-loop + do { + if (verify(item)) { + return true; + } else { + return false; + } + } while (item); +} + +verifyList("head"); + +function isSomething(item) { + if (item) { + return true; + } else { + return false; + } +} + +function findSomething(arr) { + // eslint-disable-next-line no-unreachable-loop + for (let i = 0; i < arr.length; i++) { + if (isSomething(arr[i])) { + return arr[i]; + } else { + throw new Error("Doesn't exist."); + } + } + return 0; +} + +findSomething([]); + +const obj = {}; +const bar = {}; +let firstKey; +let firstValue; +const id = 1; + +// eslint-disable-next-line no-unreachable-loop +for (const key in obj) { + if (key.startsWith("_")) { + break; + } + firstKey = key; + firstValue = obj[key]; + break; +} + +// eslint-disable-next-line no-unreachable-loop +for (foo of bar) { + if (foo.id === id) { + doSomething(foo); + } + break; +} + +// correct code + +while (foo) { + doSomething(foo); + foo = foo.parent; +} + +function verifyList2(head) { + let item = head; + do { + if (verify(item)) { + item = item.next; + } else { + return false; + } + } while (item); + + return true; +} +verifyList2("head"); + +function findSomething2(arr) { + for (let i = 0; i < arr.length; i++) { + if (isSomething(arr[i])) { + return arr[i]; + } + } + throw new Error("Doesn't exist."); +} +findSomething2([]); + +for (const key in obj) { + if (key.startsWith("_")) { + continue; + } + firstKey = key; + firstValue = obj[key]; + break; +} + +for (foo of bar) { + if (foo.id === id) { + doSomething(foo); + break; + } +} + +console.log(firstKey, firstValue); diff --git a/test/test-base/src/javascript/rules/no-useless-assignment.js b/test/test-base/src/javascript/rules/no-useless-assignment.js new file mode 100644 index 0000000..1cd217d --- /dev/null +++ b/test/test-base/src/javascript/rules/no-useless-assignment.js @@ -0,0 +1,59 @@ +/* eslint-disable no-shadow */ +/* eslint-disable no-useless-return */ + +// TODO: remove this when eslint runs on 9 or higher +/* eslint no-useless-assignment: "error" */ + +function doSomething(v) { + console.log(v); +} + +const condition = true; + +function fn1() { + let v = "used"; + doSomething(v); + v = "unused"; // eslint-disable-line no-useless-assignment +} +fn1(); + +function fn2() { + let v = "used"; + if (condition) { + v = "unused"; // eslint-disable-line no-useless-assignment + return; + } + doSomething(v); +} +fn2(); + +function fn3() { + let v = "used"; + if (condition) { + doSomething(v); + } else { + v = "unused"; // eslint-disable-line no-useless-assignment + } +} +fn3(); + +function fn4() { + let v = "unused"; // eslint-disable-line no-useless-assignment + if (condition) { + v = "used"; + doSomething(v); + return; + } +} +fn4(); + +function fn5() { + const v = "used"; + if (condition) { + let v = "used"; + console.log(v); + v = "unused"; // eslint-disable-line no-useless-assignment + } + console.log(v); +} +fn5(); diff --git a/test/test-base/src/javascript/rules/no-useless-call.js b/test/test-base/src/javascript/rules/no-useless-call.js new file mode 100644 index 0000000..4e54e99 --- /dev/null +++ b/test/test-base/src/javascript/rules/no-useless-call.js @@ -0,0 +1,32 @@ +// These are same as `foo(1, 2, 3);` +// eslint-disable-next-line no-useless-call +foo.call(undefined, 1, 2, 3); +// eslint-disable-next-line no-useless-call +foo.apply(undefined, [1, 2, 3]); +// eslint-disable-next-line no-useless-call +foo.call(null, 1, 2, 3); +// eslint-disable-next-line no-useless-call +foo.apply(null, [1, 2, 3]); + +// These are same as `obj.foo(1, 2, 3);` +// eslint-disable-next-line no-useless-call +obj.foo.call(obj, 1, 2, 3); +// eslint-disable-next-line no-useless-call +obj.foo.apply(obj, [1, 2, 3]); + +// correct +// The `this` binding is different. +foo.call(obj, 1, 2, 3); +foo.apply(obj, [1, 2, 3]); +obj.foo.call(null, 1, 2, 3); +obj.foo.apply(null, [1, 2, 3]); +obj.foo.call(otherObj, 1, 2, 3); +obj.foo.apply(otherObj, [1, 2, 3]); + +// The argument list is variadic. +// Those are warned by the `prefer-spread` rule. +/* eslint-disable prefer-spread */ +foo.apply(undefined, args); +foo.apply(null, args); +obj.foo.apply(obj, args); +/* eslint-enable prefer-spread */ diff --git a/test/test-base/src/javascript/rules/no-var.js b/test/test-base/src/javascript/rules/no-var.js new file mode 100644 index 0000000..c6f8161 --- /dev/null +++ b/test/test-base/src/javascript/rules/no-var.js @@ -0,0 +1,14 @@ +// incorrect code +// eslint-disable-next-line no-var +var x = "y"; +// eslint-disable-next-line no-var +var CONFIG = {}; + +console.log(x, CONFIG); + +// correct code + +const x2 = "y"; +const CONFIG2 = {}; + +console.log(x2, CONFIG2); diff --git a/test/test-base/src/javascript/rules/prefer-const.js b/test/test-base/src/javascript/rules/prefer-const.js new file mode 100644 index 0000000..43c1527 --- /dev/null +++ b/test/test-base/src/javascript/rules/prefer-const.js @@ -0,0 +1,29 @@ +/* eslint-disable no-shadow */ +/* eslint-disable no-unused-vars */ +// it's initialized and never reassigned. +let a = 3; // eslint-disable-line prefer-const +console.log(a); + +let b; +b = 0; // eslint-disable-line prefer-const +console.log(b); + +class C { + static { + let a; + a = 0; // eslint-disable-line prefer-const + console.log(a); + } +} + +// `i` is redefined (not reassigned) on each loop step. +// eslint-disable-next-line prefer-const +for (let i of [1, 2, 3]) { + console.log(i); +} + +// `a` is redefined (not reassigned) on each loop step. +// eslint-disable-next-line prefer-const +for (let a of [1, 2, 3]) { + console.log(a); +} diff --git a/test/test-base/src/javascript/rules/prefer-for-of.js b/test/test-base/src/javascript/rules/prefer-for-of.js new file mode 100644 index 0000000..c0de6c5 --- /dev/null +++ b/test/test-base/src/javascript/rules/prefer-for-of.js @@ -0,0 +1,3 @@ +for (let i = 0; i < array.length; i++) { + console.log(array[i]); +} diff --git a/test/test-base/src/javascript/rules/require-atomic-updates.js b/test/test-base/src/javascript/rules/require-atomic-updates.js new file mode 100644 index 0000000..2adcfc6 --- /dev/null +++ b/test/test-base/src/javascript/rules/require-atomic-updates.js @@ -0,0 +1,89 @@ +/* eslint-disable new-cap */ + +// incorrect code + +const something = new Promise((resolve) => { + resolve(1); +}); + +const somethingElse = new Promise((resolve) => { + resolve(2); +}); + +function doSomething(foo) { + return foo; +} + +function initialize() { + return new Promise.resolve(3); +} + +{ + let result; + + async function foo() { + result += await something; // eslint-disable-line require-atomic-updates + } + foo(); + + async function bar() { + result += await something; // eslint-disable-line require-atomic-updates + } + bar(); + + async function baz() { + result += doSomething(await somethingElse); // eslint-disable-line require-atomic-updates + } + baz(); + + async function qux() { + if (!result) { + result = await initialize(); // eslint-disable-line require-atomic-updates + } + } + qux(); + + function* generator() { + result += yield; // eslint-disable-line require-atomic-updates + } + generator(); +} + +// correct code +{ + let result; + + async function foobar() { + result = (await something) + result; + } + foobar(); + + async function baz() { + const tmp = doSomething(await somethingElse); + result += tmp; + } + baz(); + + async function qux() { + if (!result) { + const tmp = await initialize(); + if (!result) { + result = tmp; + } + } + } + qux(); + + async function quux() { + let localVariable = 0; + console.log(localVariable); + localVariable += await something; + console.log(localVariable); + } + quux(); + + function* generator() { + result = (yield) + result; + } + generator(); +} diff --git a/test/test-base/src/javascript/rules/submodules/camelcased.js b/test/test-base/src/javascript/rules/submodules/camelcased.js new file mode 100644 index 0000000..b56a7a2 --- /dev/null +++ b/test/test-base/src/javascript/rules/submodules/camelcased.js @@ -0,0 +1,8 @@ +/* eslint-disable camelcase */ +export const no_camelcased = { + no_camelcased: { + message: "Identifier 'no_camelcased' is not in camel case.", + suggestion: "noCamelcased", + type: "suggestion", + }, +}; diff --git a/test/test-base/src/javascript/rules/submodules/module-alpha.js b/test/test-base/src/javascript/rules/submodules/module-alpha.js new file mode 100644 index 0000000..b0bf656 --- /dev/null +++ b/test/test-base/src/javascript/rules/submodules/module-alpha.js @@ -0,0 +1,2 @@ +export const A = "This is the A stirng"; +export const B = "This is the B stirng"; diff --git a/test/test-base/src/javascript/rules/submodules/module-num.js b/test/test-base/src/javascript/rules/submodules/module-num.js new file mode 100644 index 0000000..05bbf0d --- /dev/null +++ b/test/test-base/src/javascript/rules/submodules/module-num.js @@ -0,0 +1,2 @@ +export const one = 1; +export const two = 2; diff --git a/test/test-base/src/normal/submodule.ts b/test/test-base/src/normal/submodule.ts deleted file mode 100644 index 357a6c9..0000000 --- a/test/test-base/src/normal/submodule.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default function test() { - return "this is a test"; -} diff --git a/test/test-base/src/subfolder/submodule.ts b/test/test-base/src/subfolder/submodule.ts deleted file mode 100644 index 357a6c9..0000000 --- a/test/test-base/src/subfolder/submodule.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default function test() { - return "this is a test"; -} diff --git a/test/test-base/src/test-lint.js b/test/test-base/src/test-lint.js deleted file mode 100644 index 3a87192..0000000 --- a/test/test-base/src/test-lint.js +++ /dev/null @@ -1,29 +0,0 @@ -const parsed = { HEY: "HO" }; -const envKeys = parsed - ? Object.keys(parsed).reduce((prev, next) => { - prev[`process.env.${next}`] = JSON.stringify(parsed[next]); - return prev; - }, {}) - : {}; - -console.log(envKeys); // eslint-disable-line no-console - -const obj = { - one: "one", - two: 2, -}; - -const { one } = obj; - -let two; -if (one === "one") { - two = obj.two; -} - -console.log(one, two); // eslint-disable-line no-console - -async function returnsPromise() { - return "value"; -} - -returnsPromise(); diff --git a/test/test-base/src/test-lint.ts b/test/test-base/src/test-lint.ts deleted file mode 100644 index 1abd82b..0000000 --- a/test/test-base/src/test-lint.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* eslint-disable no-console */ -import mod from "~/subfolder/submodule"; -import otherMod from "./normal/submodule"; - -mod(); -otherMod(); - -const obj = { - one: "one", - two: 2, -}; - -const { one } = obj; - -let two; -if (one === "one") { - two = obj.two; -} - -console.log(one, two); - -// IIFE functions is ok for no-floating-promises -(async function returnsPromise() { - return "value"; -})(); - -// prefer-destructuring -const { one: renamed } = obj; -console.log(renamed); -const renamed2 = obj.one; -console.log(renamed2); diff --git a/test/test-base/src/typescript/index.ts b/test/test-base/src/typescript/index.ts new file mode 100644 index 0000000..72d1773 --- /dev/null +++ b/test/test-base/src/typescript/index.ts @@ -0,0 +1,6 @@ +// add some code here to test lint + +// eslint-disable-next-line no-var +var a = 1; + +console.log(a); diff --git a/test/test-base/src/typescript/rules/ban-ts-comment.ts b/test/test-base/src/typescript/rules/ban-ts-comment.ts new file mode 100644 index 0000000..4e08d2e --- /dev/null +++ b/test/test-base/src/typescript/rules/ban-ts-comment.ts @@ -0,0 +1,29 @@ +/* eslint-disable no-var */ +// incorrect + +const something = false; + +if (typeof something === "boolean") { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore: Unreachable code error + console.log("hello"); +} +if (typeof something === "boolean") { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + /* @ts-ignore: Unreachable code error */ + console.log("hello"); +} + +type FooType = { + bar: string; +}; + +// correct + +// Compiler warns about unreachable code error +// @ts-expect-error I know about this +var foo: FooType = {}; + +console.log(foo); + +export {}; diff --git a/test/test-base/src/typescript/rules/no-array-constructor.ts b/test/test-base/src/typescript/rules/no-array-constructor.ts new file mode 100644 index 0000000..049c5b3 --- /dev/null +++ b/test/test-base/src/typescript/rules/no-array-constructor.ts @@ -0,0 +1,12 @@ +/* eslint-disable no-new */ + +// eslint-disable-next-line @typescript-eslint/no-array-constructor +Array(); + +// eslint-disable-next-line @typescript-eslint/no-array-constructor +Array(0, 1, 2); + +// eslint-disable-next-line @typescript-eslint/no-array-constructor +new Array(0, 1, 2); + +export default {}; diff --git a/test/test-base/src/typescript/rules/no-non-null-asserted-nullish-coalescing.ts b/test/test-base/src/typescript/rules/no-non-null-asserted-nullish-coalescing.ts new file mode 100644 index 0000000..9d3bd95 --- /dev/null +++ b/test/test-base/src/typescript/rules/no-non-null-asserted-nullish-coalescing.ts @@ -0,0 +1,47 @@ +/* eslint-disable no-lone-blocks */ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +/* eslint-disable @typescript-eslint/no-unnecessary-condition */ +/* eslint-disable prefer-const */ +/* eslint-disable @typescript-eslint/no-unused-expressions */ + +const foo = { bazz: "" }; +const foolio = () => 3; +const bar = ""; + +// incorrect +{ + // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-nullish-coalescing + foo! ?? bar; + // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-nullish-coalescing + foo.bazz! ?? bar; + // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-nullish-coalescing + foo!.bazz! ?? bar; + // foo()! ?? bar; +} + +{ + let x!: string; + // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-nullish-coalescing + x! ?? ""; +} + +{ + let x = foolio(); + // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-nullish-coalescing + x! ?? ""; +} + +// correct +{ + foo ?? bar; + foo ?? bar!; + foo!.bazz ?? bar; + foo!.bazz ?? bar!; + foolio() ?? bar; + + // This is considered correct code because there's no way for the user to satisfy it. + let x: string; + x! ?? ""; +} + +export {}; diff --git a/test/test-base/src/typescript/rules/no-redeclare.ts b/test/test-base/src/typescript/rules/no-redeclare.ts new file mode 100644 index 0000000..ce844fa --- /dev/null +++ b/test/test-base/src/typescript/rules/no-redeclare.ts @@ -0,0 +1,9 @@ +// @ts-expect-error testing redeclare +let x = "nisse"; + +console.log(x); + +// @ts-expect-error testing redeclare +let x = "kalle"; // eslint-disable-line @typescript-eslint/no-redeclare + +export {}; diff --git a/test/test-base/src/typescript/rules/prefer-for-of.ts b/test/test-base/src/typescript/rules/prefer-for-of.ts new file mode 100644 index 0000000..36e320f --- /dev/null +++ b/test/test-base/src/typescript/rules/prefer-for-of.ts @@ -0,0 +1,13 @@ +const array = [1, 2, 3, 4, 5]; + +// classic loop should be ok +for (let i = 0; i < array.length; i++) { + console.log(array[i]); +} + +// eslint-disable-next-line no-restricted-syntax +for (const i in array) { + console.log(i); +} + +export {}; diff --git a/test/test-base/src/typescript/rules/return-await.ts b/test/test-base/src/typescript/rules/return-await.ts new file mode 100644 index 0000000..94e4d0b --- /dev/null +++ b/test/test-base/src/typescript/rules/return-await.ts @@ -0,0 +1,18 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ + +let doit = true; + +async function invalidInTryCatch1() { + if (doit) { + // eslint-disable-next-line @typescript-eslint/return-await + return await Promise.resolve("the trye"); + } + try { + doit = false; + // eslint-disable-next-line @typescript-eslint/return-await + return Promise.reject(new Error("try")); + } catch (e) { + // Doesn't execute due to missing await. + } + return "nothing"; +} diff --git a/test/test-base/tsconfig.eslint.json b/test/test-base/tsconfig.eslint.json index 8ebce2e..71c022b 100644 --- a/test/test-base/tsconfig.eslint.json +++ b/test/test-base/tsconfig.eslint.json @@ -1,4 +1,5 @@ { "extends": "./tsconfig.json", - "include": [".*", "./**/*"] + "include": [".*", "./**/*"], + "exclude": ["node_modules", "dist", "lib"] } diff --git a/test/test-base/tsconfig.json b/test/test-base/tsconfig.json index 1ca391b..e6b3bf5 100644 --- a/test/test-base/tsconfig.json +++ b/test/test-base/tsconfig.json @@ -1,10 +1,11 @@ { - "extends": "@qlik/tsconfig/react.json", - "include": ["src"], + "extends": "@qlik/tsconfig/recommended.json", "compilerOptions": { "baseUrl": "./", "paths": { "~/*": ["src/*"] } - } + }, + "include": [".*", "./**/*"], + "exclude": ["node_modules", "dist", "lib", ".turbo"] } diff --git a/test/test-react-svelte/.eslintrc.js b/test/test-react-svelte/.eslintrc.js deleted file mode 100644 index 51750ba..0000000 --- a/test/test-react-svelte/.eslintrc.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - root: true, - parserOptions: { - project: "./tsconfig.eslint.json", - }, - extends: ["@qlik/eslint-config/react-svelte"], - ignorePatterns: ["dist", "coverage"], -}; diff --git a/test/test-react-svelte/eslint.config.js b/test/test-react-svelte/eslint.config.js new file mode 100644 index 0000000..1af54ee --- /dev/null +++ b/test/test-react-svelte/eslint.config.js @@ -0,0 +1,17 @@ +import qlikEslint from "@qlik/eslint-config"; + +const config = qlikEslint.compose( + // adds the base config for both JS and TS + ...qlikEslint.configs.recommended, + ...qlikEslint.configs.vitest, + { + rules: { + "no-undef": "off", + "no-console": "off", + "no-magic-numbers": "off", + "@typescript-eslint/no-magic-numbers": "off", + }, + }, +); + +export default config; diff --git a/test/test-react-svelte/package.json b/test/test-react-svelte/package.json index 8e4364c..b30a7cd 100644 --- a/test/test-react-svelte/package.json +++ b/test/test-react-svelte/package.json @@ -1,10 +1,9 @@ { "name": "test-react-svelte", "private": true, + "type": "module", "description": "Test project for react-svelte linting", - "scripts": { - "lint": "ESLINT_USE_FLAT_CONFIG=false eslint ." - }, + "scripts": {}, "prettier": "@qlik/prettier-config", "dependencies": { "react": "^18.3.1", @@ -14,7 +13,7 @@ "@qlik/eslint-config": "workspace:*", "@qlik/prettier-config": "workspace:*", "@qlik/tsconfig": "workspace:*", - "@types/react": "^18.3.10", - "eslint": "^8.57.0" + "@types/react": "^18.3.11", + "eslint": "^9.15.0" } } diff --git a/test/test-react-svelte/tsconfig.eslint.json b/test/test-react-svelte/tsconfig.eslint.json deleted file mode 100644 index 8ebce2e..0000000 --- a/test/test-react-svelte/tsconfig.eslint.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "./tsconfig.json", - "include": [".*", "./**/*"] -} diff --git a/test/test-react-svelte/tsconfig.json b/test/test-react-svelte/tsconfig.json index 79337a6..e1ec5b5 100644 --- a/test/test-react-svelte/tsconfig.json +++ b/test/test-react-svelte/tsconfig.json @@ -4,5 +4,6 @@ "compilerOptions": { "jsx": "react-jsx" }, - "include": ["src"] + "include": [".*", "./**/*"], + "exclude": ["node_modules", "dist", "lib"] } diff --git a/test/test-react/.eslintrc.js b/test/test-react/.eslintrc.js deleted file mode 100644 index 60458f0..0000000 --- a/test/test-react/.eslintrc.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - root: true, - parserOptions: { - project: "./tsconfig.eslint.json", - }, - extends: ["@qlik/eslint-config/react"], - ignorePatterns: ["dist", "coverage"], -}; diff --git a/test/test-react/eslint.config.js b/test/test-react/eslint.config.js new file mode 100644 index 0000000..176cad7 --- /dev/null +++ b/test/test-react/eslint.config.js @@ -0,0 +1,8 @@ +import qlik from "@qlik/eslint-config"; + +export default qlik.compose(...qlik.configs.react, { + name: "test-react", + rules: { + // modify rules here + }, +}); diff --git a/test/test-react/package.json b/test/test-react/package.json index d33b2f0..d7c6499 100644 --- a/test/test-react/package.json +++ b/test/test-react/package.json @@ -2,9 +2,8 @@ "name": "test-react", "private": true, "description": "Test project for react linting", - "scripts": { - "lint": "ESLINT_USE_FLAT_CONFIG=false eslint ." - }, + "type": "module", + "scripts": {}, "prettier": "@qlik/prettier-config", "dependencies": { "react": "^18.3.1" @@ -13,7 +12,7 @@ "@qlik/eslint-config": "workspace:*", "@qlik/prettier-config": "workspace:*", "@qlik/tsconfig": "workspace:*", - "@types/react": "^18.3.10", - "eslint": "^8.57.0" + "@types/react": "^18.3.12", + "eslint": "^9.15.0" } } diff --git a/test/test-react/src/ReactComponent.tsx b/test/test-react/src/ReactComponent.tsx index fbae7ca..48c4c2c 100644 --- a/test/test-react/src/ReactComponent.tsx +++ b/test/test-react/src/ReactComponent.tsx @@ -6,4 +6,13 @@ const ReactComponent = ({ name }: ReactComponentProps): React.ReactNode => (
Props: {`{ this name: "${name}" }`}
); -export default ReactComponent; +const ReactComponent2 = ({ name }: ReactComponentProps): React.ReactNode => { + return
Props: {`{ this name: "${name}" }`}
; +}; + +function reactComponent({ name }: ReactComponentProps): React.ReactNode { + return
Props: {`{ this name: "${name}" }`}
; +} +var shouldUseFlatConfig = "hej"; + +export { ReactComponent, ReactComponent2, reactComponent }; diff --git a/test/test-react/src/file.ts b/test/test-react/src/file.ts new file mode 100644 index 0000000..d996cc4 --- /dev/null +++ b/test/test-react/src/file.ts @@ -0,0 +1,9 @@ +shouldUseFlatConfig; + +async (params: type) => { + asf; +}; + +let nisse = 3; + +export {}; diff --git a/test/test-react/src/normal/submodule.ts b/test/test-react/src/normal/submodule.ts deleted file mode 100644 index 357a6c9..0000000 --- a/test/test-react/src/normal/submodule.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default function test() { - return "this is a test"; -} diff --git a/test/test-react/src/subfolder/submodule.ts b/test/test-react/src/subfolder/submodule.ts deleted file mode 100644 index 357a6c9..0000000 --- a/test/test-react/src/subfolder/submodule.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default function test() { - return "this is a test"; -} diff --git a/test/test-react/src/test-lint.js b/test/test-react/src/test-lint.js deleted file mode 100644 index 3a87192..0000000 --- a/test/test-react/src/test-lint.js +++ /dev/null @@ -1,29 +0,0 @@ -const parsed = { HEY: "HO" }; -const envKeys = parsed - ? Object.keys(parsed).reduce((prev, next) => { - prev[`process.env.${next}`] = JSON.stringify(parsed[next]); - return prev; - }, {}) - : {}; - -console.log(envKeys); // eslint-disable-line no-console - -const obj = { - one: "one", - two: 2, -}; - -const { one } = obj; - -let two; -if (one === "one") { - two = obj.two; -} - -console.log(one, two); // eslint-disable-line no-console - -async function returnsPromise() { - return "value"; -} - -returnsPromise(); diff --git a/test/test-react/src/test-lint.ts b/test/test-react/src/test-lint.ts deleted file mode 100644 index c1327aa..0000000 --- a/test/test-react/src/test-lint.ts +++ /dev/null @@ -1,24 +0,0 @@ -import mod from "~/subfolder/submodule"; -import otherMod from "./normal/submodule"; - -mod(); -otherMod(); - -const obj = { - one: "one", - two: 2, -}; - -const { one } = obj; - -let two; -if (one === "one") { - two = obj.two; -} - -console.log(one, two); // eslint-disable-line no-console - -// IIFE functions is ok for no-floating-promises -(async function returnsPromise() { - return "value"; -})(); diff --git a/test/test-react/tsconfig.eslint.json b/test/test-react/tsconfig.eslint.json index 8ebce2e..71c022b 100644 --- a/test/test-react/tsconfig.eslint.json +++ b/test/test-react/tsconfig.eslint.json @@ -1,4 +1,5 @@ { "extends": "./tsconfig.json", - "include": [".*", "./**/*"] + "include": [".*", "./**/*"], + "exclude": ["node_modules", "dist", "lib"] } diff --git a/test/test-react/tsconfig.json b/test/test-react/tsconfig.json index 1ca391b..dab92c2 100644 --- a/test/test-react/tsconfig.json +++ b/test/test-react/tsconfig.json @@ -1,6 +1,6 @@ { "extends": "@qlik/tsconfig/react.json", - "include": ["src"], + "include": [".*", "./**/*"], "compilerOptions": { "baseUrl": "./", "paths": {