From cd261735b9e045e0ca547a8347cbc515281ba7d8 Mon Sep 17 00:00:00 2001 From: Bryan Mishkin <698306+bmish@users.noreply.github.com> Date: Thu, 5 Dec 2024 16:42:39 -0500 Subject: [PATCH] Stricter linting (#713) --- eslint.config.js | 106 +++++++++++++++++++++++++++++++++---- lib/dependency-versions.ts | 8 +-- lib/output.ts | 10 ++-- 3 files changed, 104 insertions(+), 20 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 26a91e8..471084b 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -18,19 +18,12 @@ export default tseslint.config( eslintPluginN.configs['flat/recommended'], eslintPluginPrettierRecommended, eslintPluginUnicorn.configs['flat/recommended'], - ...tseslint.configs.recommendedTypeChecked, + ...tseslint.configs.strictTypeChecked, // Individual rules: { rules: { - 'import/extensions': ['error', 'always'], - 'import/no-unresolved': 'off', - 'n/no-missing-import': 'off', // bug with recognizing node: prefix https://github.com/mysticatea/eslint-plugin-node/issues/275 - 'n/no-unsupported-features/es-syntax': [ - 'error', - { ignores: ['modules'] }, - ], 'prettier/prettier': [ 'error', @@ -39,11 +32,102 @@ export default tseslint.config( }, ], + // unicorn rules: 'unicorn/import-style': 'off', 'unicorn/no-useless-undefined': 'off', // We use a lot of `return undefined` to satisfy the `consistent-return` rule. + // typescript-eslint rules: '@typescript-eslint/prefer-readonly': 'error', '@typescript-eslint/require-array-sort-compare': 'error', + + // Optional eslint rules: + 'array-callback-return': 'error', + 'block-scoped-var': 'error', + complexity: 'error', + 'consistent-return': 'error', + curly: 'error', + 'default-case': 'error', + eqeqeq: 'error', + 'func-style': ['error', 'declaration'], + 'new-parens': 'error', + 'no-async-promise-executor': 'error', + 'no-eval': 'error', + 'no-extend-native': 'error', + 'no-extra-bind': 'error', + 'no-implicit-coercion': 'error', + 'no-implied-eval': 'error', + 'no-lone-blocks': 'error', + 'no-multiple-empty-lines': 'error', + 'no-new-func': 'error', + 'no-new-wrappers': 'error', + 'no-octal-escape': 'error', + 'no-param-reassign': ['error', { props: true }], + 'no-return-assign': 'error', + 'no-return-await': 'error', + 'no-self-compare': 'error', + 'no-sequences': 'error', + 'no-shadow-restricted-names': 'error', + 'no-template-curly-in-string': 'error', + 'no-throw-literal': 'error', + 'no-unused-expressions': [ + 'error', + { allowShortCircuit: true, allowTernary: true }, + ], + 'no-use-before-define': ['error', 'nofunc'], + 'no-useless-call': 'error', + 'no-useless-catch': 'error', + 'no-useless-computed-key': 'error', + 'no-useless-concat': 'error', + 'no-useless-constructor': 'error', + 'no-useless-escape': 'error', + 'no-useless-rename': 'error', + 'no-useless-return': 'error', + 'no-var': 'error', + 'no-void': 'error', + 'no-with': 'error', + 'object-shorthand': 'error', + 'prefer-const': 'error', + 'prefer-numeric-literals': 'error', + 'prefer-promise-reject-errors': 'error', + 'prefer-rest-params': 'error', + 'prefer-spread': 'error', + 'prefer-template': 'error', + quotes: [ + 'error', + 'single', // Must match quote style enforced by prettier. + // Disallow unnecessary template literals. + { avoidEscape: true, allowTemplateLiterals: false }, + ], + radix: 'error', + 'require-atomic-updates': 'error', + 'require-await': 'error', + 'spaced-comment': ['error', 'always', { markers: ['*', '!'] }], + 'sort-vars': 'error', + yoda: 'error', + + // import rules: + 'import/default': 'error', + 'import/export': 'error', + 'import/extensions': ['error', 'always'], + 'import/first': 'error', + 'import/named': 'error', + 'import/namespace': 'error', + 'import/newline-after-import': 'error', + 'import/no-absolute-path': 'error', + 'import/no-cycle': 'error', + 'import/no-deprecated': 'error', + 'import/no-duplicates': 'error', + 'import/no-dynamic-require': 'error', + 'import/no-mutable-exports': 'error', + 'import/no-named-as-default': 'error', + 'import/no-named-as-default-member': 'error', + 'import/no-named-default': 'error', + 'import/no-self-import': 'error', + 'import/no-unassigned-import': 'error', + 'import/no-unresolved': 'off', + 'import/no-unused-modules': 'error', + 'import/no-useless-path-segments': 'error', + 'import/no-webpack-loader-syntax': 'error', }, // typescript-eslint parser options: @@ -53,6 +137,10 @@ export default tseslint.config( tsconfigRootDir: import.meta.dirname, }, }, + + linterOptions: { + reportUnusedDisableDirectives: 'error', + }, }, // Disabling type-checking for JS files: @@ -67,7 +155,7 @@ export default tseslint.config( // compiled output 'dist/**', - // coverage + // test coverage 'coverage/**', ], }, diff --git a/lib/dependency-versions.ts b/lib/dependency-versions.ts index 59274cd..0c6cbdb 100644 --- a/lib/dependency-versions.ts +++ b/lib/dependency-versions.ts @@ -59,6 +59,7 @@ export function calculateVersionsForEachDependency( return dependenciesToVersionsSeen; } +// eslint-disable-next-line complexity function recordDependencyVersionsForPackageJson( dependenciesToVersionsSeen: DependenciesToVersionsSeen, package_: Package, @@ -190,12 +191,6 @@ export function calculateDependenciesAndVersions( return [...dependencyVersions.entries()] .sort((a, b) => a[0].localeCompare(b[0])) .flatMap(([dependency, versionObjectsForDep]) => { - /* istanbul ignore if */ - if (!versionObjectsForDep) { - // Should always exist at this point, this if statement is just to please TypeScript. - return []; - } - // Check what versions we have seen for this dependency. let versions = versionObjectsForDep .filter((versionObject) => !versionObject.isLocalPackageVersion) @@ -335,6 +330,7 @@ function writeDependencyVersion( ); } +// eslint-disable-next-line complexity export function fixVersionsMismatching( packages: readonly Package[], mismatchingVersions: readonly DependencyAndVersions[], diff --git a/lib/output.ts b/lib/output.ts index cb085d2..842f580 100644 --- a/lib/output.ts +++ b/lib/output.ts @@ -41,9 +41,9 @@ export function dependenciesToMismatchSummary( ); const packageListSentence = usageCount > 3 - ? `${packageNames.slice(0, 3).join(', ')}, and ${ - usageCount - 3 - } other${usageCount - 3 === 1 ? '' : 's'}` + ? `${packageNames.slice(0, 3).join(', ')}, and ${String( + usageCount - 3, + )} other${usageCount - 3 === 1 ? '' : 's'}` : packageNames.join(', '); return [ chalk.redBright(versionObject.version), @@ -59,7 +59,7 @@ export function dependenciesToMismatchSummary( .join(''); return [ - `Found ${mismatchingDependencyVersions.length} ${ + `Found ${String(mismatchingDependencyVersions.length)} ${ mismatchingDependencyVersions.length === 1 ? 'dependency' : 'dependencies' } with mismatching versions across the workspace. Fix with \`--fix\`.`, tables, @@ -95,7 +95,7 @@ export function dependenciesToFixedSummary(dependencies: Dependencies): string { }) .sort((a, b) => a.dependency.localeCompare(b.dependency)); - return `Fixed versions for ${dependenciesAndFixedVersions.length} ${ + return `Fixed versions for ${String(dependenciesAndFixedVersions.length)} ${ dependenciesAndFixedVersions.length === 1 ? 'dependency' : 'dependencies' }: ${dependenciesAndFixedVersions .map((object) => `${object.dependency}@${object.version}`)