From 36050454d3dad9276910c6bec38b5aa4f21caf39 Mon Sep 17 00:00:00 2001 From: Shinigami92 Date: Mon, 8 Apr 2024 17:06:54 +0200 Subject: [PATCH] migrate config --- .eslintrc.cjs | 201 ----------------------------- docs/.vitepress/versions.ts | 4 + eslint.config.js | 248 ++++++++++++++++++++++++++++++++++++ package.json | 6 +- pnpm-lock.yaml | 36 ++++-- test/all-functional.spec.ts | 4 +- 6 files changed, 284 insertions(+), 215 deletions(-) delete mode 100644 .eslintrc.cjs create mode 100644 eslint.config.js diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index 61553e1ffc4..00000000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,201 +0,0 @@ -// @ts-check -const { defineConfig } = require('eslint-define-config'); -const { readGitignoreFiles } = require('eslint-gitignore'); - -/// -/// -/// -/// -/// - -module.exports = defineConfig({ - ignorePatterns: [ - ...readGitignoreFiles(), - '.eslintrc.cjs', // Skip self linting - ], - root: true, - env: { - browser: true, - node: true, - }, - reportUnusedDisableDirectives: true, - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/strict-type-checked', - 'plugin:prettier/recommended', - 'plugin:deprecation/recommended', - 'plugin:jsdoc/recommended-typescript-error', - 'plugin:unicorn/recommended', - ], - parserOptions: { - project: ['./tsconfig.json'], - warnOnUnsupportedTypeScriptVersion: false, - }, - rules: { - eqeqeq: ['error', 'always', { null: 'ignore' }], - 'logical-assignment-operators': 'error', - 'no-else-return': 'error', - 'no-restricted-globals': ['error', 'Intl'], - 'prefer-exponentiation-operator': 'error', - 'prefer-template': 'error', - - 'unicorn/no-array-callback-reference': 'off', // reduces readability - 'unicorn/no-nested-ternary': 'off', // incompatible with prettier - 'unicorn/no-null': 'off', // incompatible with TypeScript - 'unicorn/no-zero-fractions': 'off', // deactivated to raise awareness of floating operations - 'unicorn/number-literal-case': 'off', // incompatible with prettier - 'unicorn/prefer-ternary': 'off', // ternaries aren't always better - - // TODO @Shinigami92 2023-09-23: The following rules currently conflict with our code. - // Each rule should be checked whether it should be enabled/configured and the problems fixed, or stay disabled permanently. - 'unicorn/better-regex': 'off', - 'unicorn/consistent-function-scoping': 'off', - 'unicorn/import-style': 'off', - 'unicorn/no-await-expression-member': 'off', - 'unicorn/no-object-as-default-parameter': 'off', - 'unicorn/numeric-separators-style': 'off', - 'unicorn/prefer-export-from': 'off', - 'unicorn/prefer-string-slice': 'off', - 'unicorn/prevent-abbreviations': 'off', - 'unicorn/require-array-join-separator': 'off', - - '@typescript-eslint/array-type': [ - 'error', - { default: 'array-simple', readonly: 'generic' }, - ], - '@typescript-eslint/consistent-type-exports': 'error', - '@typescript-eslint/consistent-type-imports': 'error', - '@typescript-eslint/explicit-module-boundary-types': 'error', - '@typescript-eslint/naming-convention': [ - 'error', - { - format: ['PascalCase'], - selector: ['class', 'interface', 'typeAlias', 'enumMember'], - leadingUnderscore: 'forbid', - trailingUnderscore: 'forbid', - }, - { - format: ['PascalCase'], - selector: ['typeParameter'], - prefix: ['T'], - leadingUnderscore: 'forbid', - trailingUnderscore: 'forbid', - }, - ], - '@typescript-eslint/no-inferrable-types': [ - 'error', - { ignoreParameters: true }, - ], - '@typescript-eslint/no-unnecessary-condition': 'off', // requires `strictNullChecks` to be enabled - '@typescript-eslint/no-unsafe-assignment': 'off', - '@typescript-eslint/no-unsafe-call': 'off', - '@typescript-eslint/no-unsafe-member-access': 'off', - '@typescript-eslint/padding-line-between-statements': [ - 'error', - { blankLine: 'always', prev: 'block-like', next: '*' }, - ], - '@typescript-eslint/prefer-regexp-exec': 'error', - '@typescript-eslint/restrict-plus-operands': [ - 'error', - { - allowAny: false, - allowBoolean: false, - allowNullish: false, - allowNumberAndString: true, - allowRegExp: false, - }, - ], - '@typescript-eslint/restrict-template-expressions': [ - 'error', - { allowNumber: true, allowBoolean: true }, - ], - '@typescript-eslint/switch-exhaustiveness-check': [ - 'error', - { requireDefaultForNonUnion: true }, - ], - '@typescript-eslint/unbound-method': 'off', - '@typescript-eslint/unified-signatures': 'off', // incompatible with our api docs generation - - // TODO @ST-DDT 2023-10-10: The following rules currently conflict with our code. - // Each rule should be checked whether it should be enabled/configured and the problems fixed, or stay disabled permanently. - '@typescript-eslint/no-confusing-void-expression': 'off', - - 'jsdoc/require-jsdoc': 'off', // Enabled only for src/**/*.ts - 'jsdoc/require-returns': 'off', - 'jsdoc/sort-tags': [ - 'error', - { - tagSequence: [ - { tags: ['template'] }, - { tags: ['internal'] }, - { tags: ['param'] }, - { tags: ['returns'] }, - { tags: ['throws'] }, - { tags: ['see'] }, - { tags: ['example'] }, - { tags: ['since'] }, - { tags: ['default'] }, - { tags: ['deprecated'] }, - ], - }, - ], - 'jsdoc/tag-lines': 'off', - }, - settings: { - jsdoc: { - mode: 'typescript', - }, - }, - overrides: [ - { - files: ['src/**/*.ts'], - rules: { - 'jsdoc/require-jsdoc': 'error', - }, - }, - { - files: ['src/locale/**/*.ts'], - rules: { - 'unicorn/filename-case': 'off', // our locale files have a custom naming scheme - }, - }, - { - files: ['src/definitions/**/*.ts', 'src/locales/**/*.ts'], - rules: { - 'unicorn/filename-case': [ - 'error', - { - case: 'snakeCase', - // TODO @ST-DDT 2023-10-21: rename the definitions in v9 - ignore: [ - /chemicalElement\.ts$/, - /directoryPaths\.ts$/, - /mimeTypes\.ts$/, - ], - }, - ], - 'unicorn/text-encoding-identifier-case': 'off', - }, - }, - { - files: ['test/**/*.spec.ts'], - extends: ['plugin:vitest/recommended'], - rules: { - 'deprecation/deprecation': 'off', - - '@typescript-eslint/restrict-template-expressions': [ - 'error', - { - allowNumber: true, - allowBoolean: true, - allowAny: true, - }, - ], - - 'vitest/expect-expect': 'off', - 'vitest/prefer-each': 'error', - 'vitest/valid-expect': ['error', { maxArgs: 2 }], - }, - }, - ], -}); diff --git a/docs/.vitepress/versions.ts b/docs/.vitepress/versions.ts index a44b65c39ba..8124a66b2b2 100644 --- a/docs/.vitepress/versions.ts +++ b/docs/.vitepress/versions.ts @@ -20,6 +20,7 @@ function readOtherLatestReleaseTagNames(): string[] { const majorVersion = semver.major(tag); return majorVersion >= 6 && majorVersion !== currentMajorVersion; }) + // eslint-disable-next-line unicorn/no-array-reduce .reduce>((latestTagByMajor, tag) => { const majorVersion = semver.major(tag); @@ -50,12 +51,15 @@ export const versionBannerInfix: string | null = (() => { if (deployContext === 'production') { return null; } + if (isReleaseBranch) { return '"an old version"'; } + if (branchName === 'next') { return '"the next (unreleased) version"'; } + return '"a development version"'; })(); diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 00000000000..08f2489b4ad --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,248 @@ +// @ts-check +import eslint from '@eslint/js'; +import { readGitignoreFiles } from 'eslint-gitignore'; +import eslintPluginJsdoc from 'eslint-plugin-jsdoc'; +import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'; +import eslintPluginUnicorn from 'eslint-plugin-unicorn'; +import tseslint from 'typescript-eslint'; + +export default tseslint.config( + //#region global + { + ignores: [ + ...readGitignoreFiles(), + // Skip self linting + 'eslint.config.js', + // Skip some files that don't need linting right now + '.github/workflows/commentCodeGeneration.ts', + '.prettierrc.js', + 'docs/.vitepress/components/shims.d.ts', + 'docs/.vitepress/shared/utils/slugify.ts', + 'docs/.vitepress/theme/index.ts', + ], + linterOptions: { + reportUnusedDisableDirectives: 'error', + }, + }, + //#endregion + + //#region eslint (js) + eslint.configs.recommended, + { + rules: { + eqeqeq: ['error', 'always', { null: 'ignore' }], + 'logical-assignment-operators': 'error', + 'no-else-return': 'error', + 'no-restricted-globals': ['error', 'Intl'], + 'prefer-exponentiation-operator': 'error', + 'prefer-template': 'error', + }, + }, + //#endregion + + //#region typescript-eslint + ...tseslint.configs.strictTypeChecked, + { + plugins: { + '@typescript-eslint': tseslint.plugin, + }, + languageOptions: { + parser: tseslint.parser, + parserOptions: { + project: true, + warnOnUnsupportedTypeScriptVersion: false, + }, + }, + rules: { + '@typescript-eslint/array-type': [ + 'error', + { default: 'array-simple', readonly: 'generic' }, + ], + '@typescript-eslint/consistent-type-exports': 'error', + '@typescript-eslint/consistent-type-imports': 'error', + '@typescript-eslint/explicit-module-boundary-types': 'error', + '@typescript-eslint/naming-convention': [ + 'error', + { + format: ['PascalCase'], + selector: ['class', 'interface', 'typeAlias', 'enumMember'], + leadingUnderscore: 'forbid', + trailingUnderscore: 'forbid', + }, + { + format: ['PascalCase'], + selector: ['typeParameter'], + prefix: ['T'], + leadingUnderscore: 'forbid', + trailingUnderscore: 'forbid', + }, + ], + '@typescript-eslint/no-inferrable-types': [ + 'error', + { ignoreParameters: true }, + ], + '@typescript-eslint/no-unnecessary-condition': 'off', // requires `strictNullChecks` to be enabled + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-unsafe-call': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/padding-line-between-statements': [ + 'error', + { blankLine: 'always', prev: 'block-like', next: '*' }, + ], + '@typescript-eslint/prefer-regexp-exec': 'error', + '@typescript-eslint/restrict-plus-operands': [ + 'error', + { + allowAny: false, + allowBoolean: false, + allowNullish: false, + allowNumberAndString: true, + allowRegExp: false, + }, + ], + '@typescript-eslint/restrict-template-expressions': [ + 'error', + { allowNumber: true, allowBoolean: true }, + ], + '@typescript-eslint/switch-exhaustiveness-check': [ + 'error', + { requireDefaultForNonUnion: true }, + ], + '@typescript-eslint/unbound-method': 'off', + '@typescript-eslint/unified-signatures': 'off', // incompatible with our api docs generation + + // TODO @ST-DDT 2023-10-10: The following rules currently conflict with our code. + // Each rule should be checked whether it should be enabled/configured and the problems fixed, or stay disabled permanently. + '@typescript-eslint/no-confusing-void-expression': 'off', + }, + }, + //#endregion + + //#region deprecation + // TODO @Shinigami92 2024-04-08: Add eslint-plugin-deprecation later + // https://github.com/gund/eslint-plugin-deprecation/issues/78 + //#endregion + + //#region unicorn + // @ts-expect-error: Ignore for now + eslintPluginUnicorn.configs['flat/recommended'], + { + rules: { + 'unicorn/no-array-callback-reference': 'off', // reduces readability + 'unicorn/no-nested-ternary': 'off', // incompatible with prettier + 'unicorn/no-null': 'off', // incompatible with TypeScript + 'unicorn/no-zero-fractions': 'off', // deactivated to raise awareness of floating operations + 'unicorn/number-literal-case': 'off', // incompatible with prettier + 'unicorn/prefer-ternary': 'off', // ternaries aren't always better + + // TODO @Shinigami92 2023-09-23: The following rules currently conflict with our code. + // Each rule should be checked whether it should be enabled/configured and the problems fixed, or stay disabled permanently. + 'unicorn/better-regex': 'off', + 'unicorn/consistent-function-scoping': 'off', + 'unicorn/import-style': 'off', + 'unicorn/no-await-expression-member': 'off', + 'unicorn/no-object-as-default-parameter': 'off', + 'unicorn/numeric-separators-style': 'off', + 'unicorn/prefer-export-from': 'off', + 'unicorn/prefer-string-slice': 'off', + 'unicorn/prevent-abbreviations': 'off', + 'unicorn/require-array-join-separator': 'off', + }, + }, + //#endregion + + //#region jsdoc + eslintPluginJsdoc.configs['flat/recommended-typescript-error'], + { + rules: { + 'jsdoc/require-jsdoc': 'off', // Enabled only for src/**/*.ts + 'jsdoc/require-returns': 'off', + 'jsdoc/sort-tags': [ + 'error', + { + tagSequence: [ + { tags: ['template'] }, + { tags: ['internal'] }, + { tags: ['param'] }, + { tags: ['returns'] }, + { tags: ['throws'] }, + { tags: ['see'] }, + { tags: ['example'] }, + { tags: ['since'] }, + { tags: ['default'] }, + { tags: ['deprecated'] }, + ], + }, + ], + 'jsdoc/tag-lines': 'off', + }, + settings: { + jsdoc: { + mode: 'typescript', + }, + }, + }, + //#endregion + + //#region vitest + // TODO @Shinigami92 2024-04-08: Add vitest later + // https://github.com/veritem/eslint-plugin-vitest/issues/413 + //#endregion + + //#region prettier + eslintPluginPrettierRecommended, + //#endregion, + + //#region overrides + { + files: ['src/**/*.ts'], + rules: { + 'jsdoc/require-jsdoc': 'error', + }, + }, + { + files: ['src/locale/**/*.ts'], + rules: { + 'unicorn/filename-case': 'off', // our locale files have a custom naming scheme + }, + }, + { + files: ['src/definitions/**/*.ts', 'src/locales/**/*.ts'], + rules: { + 'unicorn/filename-case': [ + 'error', + { + case: 'snakeCase', + // TODO @ST-DDT 2023-10-21: rename the definitions in v9 + ignore: [ + /chemicalElement\.ts$/, + /directoryPaths\.ts$/, + /mimeTypes\.ts$/, + ], + }, + ], + 'unicorn/text-encoding-identifier-case': 'off', + }, + }, + { + files: ['test/**/*.spec.ts'], + // extends: ['plugin:vitest/recommended'], + rules: { + 'deprecation/deprecation': 'off', + + '@typescript-eslint/restrict-template-expressions': [ + 'error', + { + allowNumber: true, + allowBoolean: true, + allowAny: true, + }, + ], + + // 'vitest/expect-expect': 'off', + // 'vitest/prefer-each': 'error', + // 'vitest/valid-expect': ['error', { maxArgs: 2 }], + }, + } + //#endregion +); diff --git a/package.json b/package.json index b6139cf0abc..aae2f23bac3 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "docs:serve": "vitepress serve docs --port 5173", "docs:diff": "tsx ./scripts/diff.ts", "format": "prettier --cache --write .", - "lint": "eslint --cache --cache-strategy content --report-unused-disable-directives .", + "lint": "eslint --cache --cache-strategy content .", "ts-check": "tsc", "test": "vitest", "test:update-snapshots": "vitest run -u", @@ -96,12 +96,11 @@ "@eslint-types/prettier": "5.1.3", "@eslint-types/typescript-eslint": "7.5.0", "@eslint-types/unicorn": "52.0.0", + "@eslint/js": "~9.0.0", "@types/node": "20.12.5", "@types/sanitize-html": "2.11.0", "@types/semver": "7.5.8", "@types/validator": "13.11.9", - "@typescript-eslint/eslint-plugin": "7.5.0", - "@typescript-eslint/parser": "7.5.0", "@vitest/coverage-v8": "1.4.0", "@vitest/ui": "1.4.0", "@vueuse/core": "10.9.0", @@ -128,6 +127,7 @@ "tsup": "8.0.2", "tsx": "4.7.2", "typescript": "5.4.4", + "typescript-eslint": "~7.5.0", "validator": "13.11.0", "vite": "5.2.8", "vitepress": "1.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2bdc5345ef7..c7d913f3982 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,9 @@ devDependencies: '@eslint-types/unicorn': specifier: 52.0.0 version: 52.0.0 + '@eslint/js': + specifier: ~9.0.0 + version: 9.0.0 '@types/node': specifier: 20.12.5 version: 20.12.5 @@ -38,12 +41,6 @@ devDependencies: '@types/validator': specifier: 13.11.9 version: 13.11.9 - '@typescript-eslint/eslint-plugin': - specifier: 7.5.0 - version: 7.5.0(@typescript-eslint/parser@7.5.0)(eslint@9.0.0)(typescript@5.4.4) - '@typescript-eslint/parser': - specifier: 7.5.0 - version: 7.5.0(eslint@9.0.0)(typescript@5.4.4) '@vitest/coverage-v8': specifier: 1.4.0 version: 1.4.0(vitest@1.4.0) @@ -85,7 +82,7 @@ devDependencies: version: 52.0.0(eslint@9.0.0) eslint-plugin-vitest: specifier: 0.4.1 - version: 0.4.1(@typescript-eslint/eslint-plugin@7.5.0)(eslint@9.0.0)(typescript@5.4.4)(vitest@1.4.0) + version: 0.4.1(eslint@9.0.0)(typescript@5.4.4)(vitest@1.4.0) glob: specifier: 10.3.12 version: 10.3.12 @@ -122,6 +119,9 @@ devDependencies: typescript: specifier: 5.4.4 version: 5.4.4 + typescript-eslint: + specifier: ~7.5.0 + version: 7.5.0(eslint@9.0.0)(typescript@5.4.4) validator: specifier: 13.11.0 version: 13.11.0 @@ -3307,7 +3307,7 @@ packages: - supports-color dev: true - /eslint-plugin-vitest@0.4.1(@typescript-eslint/eslint-plugin@7.5.0)(eslint@9.0.0)(typescript@5.4.4)(vitest@1.4.0): + /eslint-plugin-vitest@0.4.1(eslint@9.0.0)(typescript@5.4.4)(vitest@1.4.0): resolution: {integrity: sha512-+PnZ2u/BS+f5FiuHXz4zKsHPcMKHie+K+1Uvu/x91ovkCMEOJqEI8E9Tw1Wzx2QRz4MHOBHYf1ypO8N1K0aNAA==} engines: {node: ^18.0.0 || >= 20.0.0} peerDependencies: @@ -3320,7 +3320,6 @@ packages: vitest: optional: true dependencies: - '@typescript-eslint/eslint-plugin': 7.5.0(@typescript-eslint/parser@7.5.0)(eslint@9.0.0)(typescript@5.4.4) '@typescript-eslint/utils': 7.5.0(eslint@9.0.0)(typescript@5.4.4) eslint: 9.0.0 vitest: 1.4.0(@types/node@20.12.5)(@vitest/ui@1.4.0) @@ -6359,6 +6358,25 @@ packages: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} dev: true + /typescript-eslint@7.5.0(eslint@9.0.0)(typescript@5.4.4): + resolution: {integrity: sha512-eKhF39LRi2xYvvXh3h3S+mCxC01dZTIZBlka25o39i81VeQG+OZyfC4i2GEDspNclMRdXkg9uGhmvWMhjph2XQ==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/eslint-plugin': 7.5.0(@typescript-eslint/parser@7.5.0)(eslint@9.0.0)(typescript@5.4.4) + '@typescript-eslint/parser': 7.5.0(eslint@9.0.0)(typescript@5.4.4) + '@typescript-eslint/utils': 7.5.0(eslint@9.0.0)(typescript@5.4.4) + eslint: 9.0.0 + typescript: 5.4.4 + transitivePeerDependencies: + - supports-color + dev: true + /typescript@5.4.4: resolution: {integrity: sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==} engines: {node: '>=14.17'} diff --git a/test/all-functional.spec.ts b/test/all-functional.spec.ts index 12b69ba1fb7..7e456191f8e 100644 --- a/test/all-functional.spec.ts +++ b/test/all-functional.spec.ts @@ -114,7 +114,7 @@ describe('functional tests', () => { } describe.each(Object.entries(modules))('%s', (module, methods) => { - // eslint-disable-next-line vitest/prefer-each -- need to dynamically succeed/fail + //# eslint-disable-next-line vitest/prefer-each -- need to dynamically succeed/fail for (const meth of methods) { const testAssertion = () => { // TODO @ST-DDT 2022-03-28: Use random seed once there are no more failures @@ -150,7 +150,7 @@ describe('faker.helpers.fake functional tests', () => { } describe.each(Object.entries(modules))('%s', (module, methods) => { - // eslint-disable-next-line vitest/prefer-each -- need to dynamically succeed/fail + //# eslint-disable-next-line vitest/prefer-each -- need to dynamically succeed/fail for (const meth of methods) { const testAssertion = () => { // TODO @ST-DDT 2022-03-28: Use random seed once there are no more failures