From b586705668df461b7d62545bb95d195548507ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Smestad?= Date: Mon, 11 Nov 2024 16:03:14 +0100 Subject: [PATCH 1/2] Prepare for new release * Big dependency update, ESLint 9, typescript-eslint 8, +++ * Drop XO as we do not want the Stylistic rules (we use Prettier for that) * New rules include: alphabetical sorting of switch cases --- CHANGELOG.md | 5 ++ index.js | 18 ----- package-lock.json | 149 +-------------------------------------- package.json | 3 +- rule-sets/base.js | 44 +++++++++--- test/cases/nice-sort.tsx | 22 ++++++ test/cases/ugly-sort.tsx | 5 ++ 7 files changed, 69 insertions(+), 177 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81f4d2a..77117e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 4.0.0 +* Big dependency update, ESLint 9, typescript-eslint 8, +++ +* Drop XO as we do not want the Stylistic rules (we use Prettier for that) +* New rules include: alphabetical sorting of switch cases + ## 3.2.0 * Update dependencies diff --git a/index.js b/index.js index 26b2e71..4035ca7 100644 --- a/index.js +++ b/index.js @@ -1,11 +1,5 @@ -import path from 'path'; -import { fileURLToPath } from 'url'; - -import { FlatCompat } from '@eslint/eslintrc'; import js from '@eslint/js'; import eslintConfigPrettier from 'eslint-config-prettier'; -import xoBrowser from 'eslint-config-xo/browser'; -import perfectionist from 'eslint-plugin-perfectionist'; import { baseRuleSet } from './rule-sets/base.js'; import { cypressRuleSet } from './rule-sets/cypress.js'; @@ -14,23 +8,11 @@ import { nodeRuleSet } from './rule-sets/node.js'; import { storybookRuleSet } from './rule-sets/storybook.js'; import { unitTestRuleSet } from './rule-sets/unit-test.js'; -// mimic CommonJS variables (in ESM) -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -const compat = new FlatCompat({ - baseDirectory: __dirname, -}); - /** @type { import("eslint").Linter.Config[] } */ // eslint-disable-next-line import/no-default-export export default [ js.configs.recommended, - ...xoBrowser, - compat.extends('eslint-config-xo-react')[0], eslintConfigPrettier, - // @ts-expect-error types are missing - perfectionist.configs['recommended-natural'], // Base Tidal rule set: baseRuleSet, // Following are some file type specific overrides: diff --git a/package-lock.json b/package-lock.json index 9880f64..61f8c14 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,8 +19,6 @@ "confusing-browser-globals": "1.0.11", "eslint": "9.14.0", "eslint-config-prettier": "9.1.0", - "eslint-config-xo": "0.46.0", - "eslint-config-xo-react": "0.27.0", "eslint-import-resolver-typescript": "3.6.3", "eslint-plugin-cypress": "4.1.0", "eslint-plugin-import": "2.31.0", @@ -1076,119 +1074,11 @@ "type-fest": "^2.19.0" } }, - "node_modules/@stylistic/eslint-plugin": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.6.1.tgz", - "integrity": "sha512-UT0f4t+3sQ/GKW7875NiIIjZJ1Bh4gd7JNfoIkwIQyWqO7wGd0Pqzu0Ho30Ka8MNF5lm++SkVeqAk26vGxoUpg==", - "license": "MIT", - "dependencies": { - "@stylistic/eslint-plugin-js": "2.6.1", - "@stylistic/eslint-plugin-jsx": "2.6.1", - "@stylistic/eslint-plugin-plus": "2.6.1", - "@stylistic/eslint-plugin-ts": "2.6.1", - "@types/eslint": "^9.6.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "peerDependencies": { - "eslint": ">=8.40.0" - } - }, - "node_modules/@stylistic/eslint-plugin-js": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-2.6.1.tgz", - "integrity": "sha512-iLOiVzcvqzDGD9U0EuVOX680v+XOPiPAjkxWj+Q6iV2GLOM5NB27tKVOpJY7AzBhidwpRbaLTgg3T4UzYx09jw==", - "license": "MIT", - "dependencies": { - "@types/eslint": "^9.6.0", - "acorn": "^8.12.1", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "peerDependencies": { - "eslint": ">=8.40.0" - } - }, - "node_modules/@stylistic/eslint-plugin-js/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@stylistic/eslint-plugin-jsx": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-2.6.1.tgz", - "integrity": "sha512-5qHLXqxfY6jubAQfDqrifv41fx7gaqA9svDaChxMI6JiHpEBfh+PXxmm3g+B8gJCYVBTC62Rjl0Ny5QabK58bw==", - "license": "MIT", - "dependencies": { - "@stylistic/eslint-plugin-js": "^2.6.1", - "@types/eslint": "^9.6.0", - "estraverse": "^5.3.0", - "picomatch": "^4.0.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "peerDependencies": { - "eslint": ">=8.40.0" - } - }, - "node_modules/@stylistic/eslint-plugin-jsx/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/@stylistic/eslint-plugin-plus": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-2.6.1.tgz", - "integrity": "sha512-z/IYu/q8ipApzNam5utSU+BrXg4pK/Gv9xNbr4eWv/bZppvTWJU62xCO4nw/6r2dHNPnqc7uCHEC7GMlBnPY0A==", - "license": "MIT", - "dependencies": { - "@types/eslint": "^9.6.0", - "@typescript-eslint/utils": "^8.0.0" - }, - "peerDependencies": { - "eslint": "*" - } - }, - "node_modules/@stylistic/eslint-plugin-ts": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-2.6.1.tgz", - "integrity": "sha512-Mxl1VMorEG1Hc6oBYPD0+KIJOWkjEF1R0liL7wWgKfwpqOkgmnh5lVdZBrYyfRKOE4RlGcwEFTNai1IW6orgVg==", - "license": "MIT", - "dependencies": { - "@stylistic/eslint-plugin-js": "2.6.1", - "@types/eslint": "^9.6.0", - "@typescript-eslint/utils": "^8.0.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "peerDependencies": { - "eslint": ">=8.40.0" - } - }, "node_modules/@types/eslint": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "devOptional": true, "license": "MIT", "dependencies": { "@types/estree": "*", @@ -3042,43 +2932,6 @@ "eslint": ">=7.0.0" } }, - "node_modules/eslint-config-xo": { - "version": "0.46.0", - "resolved": "https://registry.npmjs.org/eslint-config-xo/-/eslint-config-xo-0.46.0.tgz", - "integrity": "sha512-mjQUhdTCLQwHUFKf1hhSx1FFhm2jllr4uG2KjaW7gZHGAbjKoSypvo1eQvFk17lHx3bztYjZDDXQmkAZyaSlAg==", - "license": "MIT", - "dependencies": { - "@stylistic/eslint-plugin": "^2.6.1", - "confusing-browser-globals": "1.0.11", - "globals": "^15.3.0" - }, - "engines": { - "node": ">=18.18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - }, - "peerDependencies": { - "eslint": ">=9.8.0" - } - }, - "node_modules/eslint-config-xo-react": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/eslint-config-xo-react/-/eslint-config-xo-react-0.27.0.tgz", - "integrity": "sha512-wiV215xQIn71XZyyVfaOXHaFpR1B14IJttwOjMi/eqUK1s+ojJdHr7eHqTLaGUfh6FKgWha1QNwePlIXx7mBUg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - }, - "peerDependencies": { - "eslint": ">=8.6.0", - "eslint-plugin-react": ">=7.29.0", - "eslint-plugin-react-hooks": ">=4.3.0" - } - }, "node_modules/eslint-import-resolver-node": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", diff --git a/package.json b/package.json index ce13306..6e7ff8e 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "main": "index.js", "scripts": { "test": "ava test/test.js", + "type-check": "tsc", "lint": "eslint --report-unused-disable-directives ." }, "repository": { @@ -71,8 +72,6 @@ "confusing-browser-globals": "1.0.11", "eslint": "9.14.0", "eslint-config-prettier": "9.1.0", - "eslint-config-xo": "0.46.0", - "eslint-config-xo-react": "0.27.0", "eslint-import-resolver-typescript": "3.6.3", "eslint-plugin-cypress": "4.1.0", "eslint-plugin-import": "2.31.0", diff --git a/rule-sets/base.js b/rule-sets/base.js index 792442c..babca84 100644 --- a/rule-sets/base.js +++ b/rule-sets/base.js @@ -7,7 +7,10 @@ import confusingBrowserGlobals from 'confusing-browser-globals'; import importPlugin from 'eslint-plugin-import'; import jsxA11yPlugin from 'eslint-plugin-jsx-a11y'; import noOnlyTestsPlugin from 'eslint-plugin-no-only-tests'; +import perfectionist from 'eslint-plugin-perfectionist'; import prettier from 'eslint-plugin-prettier'; +import react from 'eslint-plugin-react'; +import reactHooks from 'eslint-plugin-react-hooks'; import globals from 'globals'; import { internalRules } from '../internal-rules/index.js'; @@ -21,7 +24,7 @@ export const baseRuleSet = { parser: tsParser, parserOptions: { ecmaVersion: 'latest', - project: true, + projectService: true, sourceType: 'module', }, }, @@ -33,7 +36,10 @@ export const baseRuleSet = { 'internal-rules': internalRules, 'jsx-a11y': jsxA11yPlugin, 'no-only-tests': noOnlyTestsPlugin, + perfectionist, prettier, + react, + 'react-hooks': reactHooks, }, rules: { ...tsPlugin.configs['recommended-type-checked'].rules, @@ -41,16 +47,9 @@ export const baseRuleSet = { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access ...importPlugin.configs.typescript.rules, ...jsxA11yPlugin.configs.recommended.rules, + ...perfectionist.configs['recommended-natural'].rules, '@jambit/typed-redux-saga/delegate-effects': 'error', '@jambit/typed-redux-saga/use-typed-effects': ['error', 'macro'], - '@stylistic/comma-dangle': 'off', - '@stylistic/function-paren-newline': 'off', - '@stylistic/indent': 'off', - '@stylistic/jsx-quotes': 'off', - '@stylistic/object-curly-spacing': 'off', - '@stylistic/padding-line-between-statements': 'off', - '@stylistic/semi': 'off', - '@stylistic/space-before-blocks': 'off', '@typescript-eslint/array-type': ['error', { default: 'generic' }], '@typescript-eslint/await-thenable': 'error', '@typescript-eslint/ban-ts-comment': 'error', @@ -206,9 +205,32 @@ export const baseRuleSet = { 'no-shadow': 'off', 'no-undef': 'off', 'no-unused-vars': 'off', + 'no-var': 'error', 'no-warning-comments': 'off', + 'object-shorthand': 'error', // TODO: consider switching from 'import/order' to this one? 'perfectionist/sort-imports': 'off', + 'perfectionist/sort-intersection-types': [ + 'error', + { + groups: [ + [ + 'conditional', + 'function', + 'import', + 'intersection', + 'keyword', + 'literal', + 'named', + 'operator', + 'tuple', + 'union', + ], + ['object'], + ['nullish'], + ], + }, + ], 'prettier/prettier': [ 'error', { @@ -245,6 +267,10 @@ export const baseRuleSet = { 'import/resolver': { typescript: {}, }, + perfectionist: { + ignoreCase: false, + type: 'natural', + }, react: { version: '18.2.0', }, diff --git a/test/cases/nice-sort.tsx b/test/cases/nice-sort.tsx index 456c70a..ed826d3 100644 --- a/test/cases/nice-sort.tsx +++ b/test/cases/nice-sort.tsx @@ -36,6 +36,11 @@ export function ProfileImageRepresentation({ desiredWidth, resourceId, width, +}: { + className: string; + desiredWidth: number; + resourceId: string; + width: number; }) { const style = { height: (() => {})(), @@ -53,3 +58,20 @@ export function ProfileImageRepresentation({ /> ); } + +export type SortDirection = 'ASC' | 'DESC'; + +export type SortOrderAndDirection = [ + OnboardingStepName | null | undefined, + SortDirection | null | undefined, +]; + +export type Playlist = ClientApplication & + SortOrderAndDirection & { + readonly contentType: 'folderPlaylist' | 'playlist'; + readonly parent?: { + readonly id: string; + readonly name: string; + }; + readonly trn?: string; + }; diff --git a/test/cases/ugly-sort.tsx b/test/cases/ugly-sort.tsx index d850c0c..2c64991 100644 --- a/test/cases/ugly-sort.tsx +++ b/test/cases/ugly-sort.tsx @@ -32,6 +32,11 @@ export function ProfileImageRepresentation({ className, desiredWidth, resourceId, +}: { + width: number; + className: string; + desiredWidth: number; + resourceId: string; }) { const style = { height: (() => {})(), From 88439763d473d38efb57923ebb014b9955ec6a71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Smestad?= Date: Mon, 11 Nov 2024 16:07:58 +0100 Subject: [PATCH 2/2] Update test --- test/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test.js b/test/test.js index 85c9f6a..b5a02db 100644 --- a/test/test.js +++ b/test/test.js @@ -88,7 +88,7 @@ test('Fails on unsorted file', async t => { t.is(unexpectedErrorsFound.length, 0); // Total number of seen errors: - t.is(errors.length, 10); + t.is(errors.length, 11); }); test('Success on sorted file', async t => {