diff --git a/package.json b/package.json index 36fa80652b3014..f19b7cacd9b99e 100644 --- a/package.json +++ b/package.json @@ -93,6 +93,8 @@ "@microsoft/loader-load-themed-styles": "2.0.17", "@microsoft/tsdoc": "0.14.1", "@nx/devkit": "17.2.8", + "@nx/eslint": "17.2.8", + "@nx/eslint-plugin": "17.2.8", "@nx/jest": "17.2.8", "@nx/js": "17.2.8", "@nx/node": "17.2.8", diff --git a/tools/eslint-rules/README.md b/tools/eslint-rules/README.md new file mode 100644 index 00000000000000..fe88290640fe38 --- /dev/null +++ b/tools/eslint-rules/README.md @@ -0,0 +1,31 @@ +# eslint-rules + +Set of internal workspace eslint rules. + +> _NOTE:_ +> +> Under the hood this leverages nx workspace lint rule registration which happens within `@nx/eslint-plugin` registration. +> With that said to be able to use these rules `@nx` eslint plugin needs to be registered within our eslint config chain ( plugins setup ) + +## Usage: + +Let's say we implement custom lint rule named `uppercase-const`. + +Following rule declaration will enable it for particular lint config: + +```jsonc +/* @filename /.eslintrc */ +{ + "extends:" ["../../.eslintrc"], + "rules": { + /* pattern: <@nx/workspace>- */ + "@nx/workspace-uppercase-const": "error" + } +} +``` + +## Adding new rule: + +```sh +npx nx g @fluentui/workspace-plugin:eslint-rule +``` diff --git a/tools/eslint-rules/index.ts b/tools/eslint-rules/index.ts new file mode 100644 index 00000000000000..c5d9c0f7e0ad7e --- /dev/null +++ b/tools/eslint-rules/index.ts @@ -0,0 +1,27 @@ +/** + * Import your custom workspace rules at the top of this file. + * + * For example: + * + * import { RULE_NAME as myCustomRuleName, rule as myCustomRule } from './rules/my-custom-rule'; + * + * In order to quickly get started with writing rules you can use the + * following generator command and provide your desired rule name: + * + * ```sh + * npx nx g nx g @fluentui/workspace-plugin:eslint-rule {{ NEW_RULE_NAME }} + * ``` + */ + +module.exports = { + /** + * Apply the imported custom rules here. + * + * For example (using the example import above): + * + * rules: { + * [myCustomRuleName]: myCustomRule + * } + */ + rules: {}, +}; diff --git a/tools/eslint-rules/jest.config.ts b/tools/eslint-rules/jest.config.ts new file mode 100644 index 00000000000000..360578d5d5ed06 --- /dev/null +++ b/tools/eslint-rules/jest.config.ts @@ -0,0 +1,17 @@ +/* eslint-disable */ +export default { + displayName: 'eslint-rules', + preset: '../../jest.preset.js', + transform: { + '^.+\\.[tj]s$': [ + 'ts-jest', + { + diagnostics: false, + isolatedModules: true, + tsconfig: '/tsconfig.spec.json', + }, + ], + }, + moduleFileExtensions: ['ts', 'js', 'html'], + coverageDirectory: '../../coverage/tools/eslint-rules', +}; diff --git a/tools/eslint-rules/package.json b/tools/eslint-rules/package.json new file mode 100644 index 00000000000000..f6f3f43ed83d50 --- /dev/null +++ b/tools/eslint-rules/package.json @@ -0,0 +1,5 @@ +{ + "name": "eslint-rules", + "version": "0.0.0", + "private": true +} diff --git a/tools/eslint-rules/project.json b/tools/eslint-rules/project.json new file mode 100644 index 00000000000000..343a91d89096a2 --- /dev/null +++ b/tools/eslint-rules/project.json @@ -0,0 +1,14 @@ +{ + "name": "eslint-rules", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "tools/eslint-rules", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "tools/eslint-rules/jest.config.ts" + } + } + } +} diff --git a/tools/eslint-rules/tsconfig.json b/tools/eslint-rules/tsconfig.json new file mode 100644 index 00000000000000..6205fc3437decb --- /dev/null +++ b/tools/eslint-rules/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "module": "ESNext" + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lint.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/tools/eslint-rules/tsconfig.lint.json b/tools/eslint-rules/tsconfig.lint.json new file mode 100644 index 00000000000000..bb717c5e289e34 --- /dev/null +++ b/tools/eslint-rules/tsconfig.lint.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": ["node"] + }, + "exclude": ["**/*.spec.ts"], + "include": ["**/*.ts"] +} diff --git a/tools/eslint-rules/tsconfig.spec.json b/tools/eslint-rules/tsconfig.spec.json new file mode 100644 index 00000000000000..4d92465f462b6b --- /dev/null +++ b/tools/eslint-rules/tsconfig.spec.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": ["jest", "node"] + }, + "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] +} diff --git a/yarn.lock b/yarn.lock index a2a342ab508c81..d0f2d0da039989 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1859,7 +1859,7 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.11.tgz#a5d300008960bb39677c46bf16f53ec70d8dee04" integrity sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw== -"@eslint-community/eslint-utils@^4.2.0": +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== @@ -2912,6 +2912,13 @@ dependencies: "@nx/devkit" "17.2.8" +"@nrwl/eslint-plugin-nx@17.2.8": + version "17.2.8" + resolved "https://registry.yarnpkg.com/@nrwl/eslint-plugin-nx/-/eslint-plugin-nx-17.2.8.tgz#bf3a3c0820eb9a6bf42355ec1012799136595801" + integrity sha512-g76ZzBvJ7jenvLXQuXdBUs7p3KP2vr00u7TV4A/J01eDJMFHYVZhYfQNjLhr4nnE4NvNRr8WdrMD2KeGYtdycQ== + dependencies: + "@nx/eslint-plugin" "17.2.8" + "@nrwl/jest@17.2.8": version "17.2.8" resolved "https://registry.yarnpkg.com/@nrwl/jest/-/jest-17.2.8.tgz#188644e3177c47e1160cb135662b7697bb152467" @@ -2968,6 +2975,22 @@ tmp "~0.2.1" tslib "^2.3.0" +"@nx/eslint-plugin@17.2.8": + version "17.2.8" + resolved "https://registry.yarnpkg.com/@nx/eslint-plugin/-/eslint-plugin-17.2.8.tgz#bb190ce2152fc4a1999b7fa3b5a0930b87d22a5d" + integrity sha512-SOF/Q1g9SNZnwPpwcZNCYeYU670s1X1hgwHCWisw3jGPTYHvpAMQVGwPyU28OyY4PBrqEOVqLTWsuWQYpUjLOw== + dependencies: + "@nrwl/eslint-plugin-nx" "17.2.8" + "@nx/devkit" "17.2.8" + "@nx/js" "17.2.8" + "@typescript-eslint/type-utils" "^6.9.1" + "@typescript-eslint/utils" "^6.9.1" + chalk "^4.1.0" + confusing-browser-globals "^1.0.9" + jsonc-eslint-parser "^2.1.0" + semver "7.5.3" + tslib "^2.3.0" + "@nx/eslint@17.2.8": version "17.2.8" resolved "https://registry.yarnpkg.com/@nx/eslint/-/eslint-17.2.8.tgz#426010f88aa5518454311b2c7d194444a973e662" @@ -5392,10 +5415,10 @@ "@types/tough-cookie" "*" parse5 "^7.0.0" -"@types/json-schema@*", "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": - version "7.0.10" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.10.tgz#9b05b7896166cd00e9cbd59864853abf65d9ac23" - integrity sha512-BLO9bBq59vW3fxCpD4o0N4U+DXsvwvIcl+jofw0frQo/GrBFC+/jRZj1E7kgp6dvTyNmA4y6JCV5Id/r3mNP5A== +"@types/json-schema@*", "@types/json-schema@^7.0.12", "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== "@types/json5@^0.0.29": version "0.0.29" @@ -5732,10 +5755,10 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.2.3.tgz#5798ecf1bec94eaa64db39ee52808ec0693315aa" integrity sha512-KQf+QAMWKMrtBMsB8/24w53tEsxllMj6TuA80TT/5igJalLI/zm0L3oXRbIAl4Ohfc85gyHX/jhMwsVkmhLU4A== -"@types/semver@^7.3.12": - version "7.3.13" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" - integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== +"@types/semver@^7.3.12", "@types/semver@^7.5.0": + version "7.5.6" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.6.tgz#c65b2bfce1bec346582c07724e3f8c1017a20339" + integrity sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A== "@types/serve-index@^1.9.1": version "1.9.1" @@ -6022,6 +6045,24 @@ "@typescript-eslint/types" "5.59.1" "@typescript-eslint/visitor-keys" "5.59.1" +"@typescript-eslint/scope-manager@6.18.1": + version "6.18.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz#28c31c60f6e5827996aa3560a538693cb4bd3848" + integrity sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw== + dependencies: + "@typescript-eslint/types" "6.18.1" + "@typescript-eslint/visitor-keys" "6.18.1" + +"@typescript-eslint/type-utils@^6.9.1": + version "6.18.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.18.1.tgz#115cf535f8b39db8301677199ce51151e2daee96" + integrity sha512-wyOSKhuzHeU/5pcRDP2G2Ndci+4g653V43gXTpt4nbyoIOAASkGDA9JIAgbQCdCkcr1MvpSYWzxTz0olCn8+/Q== + dependencies: + "@typescript-eslint/typescript-estree" "6.18.1" + "@typescript-eslint/utils" "6.18.1" + debug "^4.3.4" + ts-api-utils "^1.0.1" + "@typescript-eslint/types@4.22.0": version "4.22.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.22.0.tgz#0ca6fde5b68daf6dba133f30959cc0688c8dd0b6" @@ -6032,6 +6073,11 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.1.tgz#03f3fedd1c044cb336ebc34cc7855f121991f41d" integrity sha512-dg0ICB+RZwHlysIy/Dh1SP+gnXNzwd/KS0JprD3Lmgmdq+dJAJnUPe1gNG34p0U19HvRlGX733d/KqscrGC1Pg== +"@typescript-eslint/types@6.18.1": + version "6.18.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.18.1.tgz#91617d8080bcd99ac355d9157079970d1d49fefc" + integrity sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw== + "@typescript-eslint/typescript-estree@4.22.0": version "4.22.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.22.0.tgz#b5d95d6d366ff3b72f5168c75775a3e46250d05c" @@ -6058,6 +6104,33 @@ semver "^7.3.7" tsutils "^3.21.0" +"@typescript-eslint/typescript-estree@6.18.1": + version "6.18.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz#a12b6440175b4cbc9d09ab3c4966c6b245215ab4" + integrity sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA== + dependencies: + "@typescript-eslint/types" "6.18.1" + "@typescript-eslint/visitor-keys" "6.18.1" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + minimatch "9.0.3" + semver "^7.5.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/utils@6.18.1", "@typescript-eslint/utils@^6.9.1": + version "6.18.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.18.1.tgz#3451cfe2e56babb6ac657e10b6703393d4b82955" + integrity sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@types/json-schema" "^7.0.12" + "@types/semver" "^7.5.0" + "@typescript-eslint/scope-manager" "6.18.1" + "@typescript-eslint/types" "6.18.1" + "@typescript-eslint/typescript-estree" "6.18.1" + semver "^7.5.4" + "@typescript-eslint/utils@^5.47.0": version "5.59.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.59.1.tgz#d89fc758ad23d2157cfae53f0b429bdf15db9473" @@ -6088,6 +6161,14 @@ "@typescript-eslint/types" "5.59.1" eslint-visitor-keys "^3.3.0" +"@typescript-eslint/visitor-keys@6.18.1": + version "6.18.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz#704d789bda2565a15475e7d22f145b8fe77443f4" + integrity sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA== + dependencies: + "@typescript-eslint/types" "6.18.1" + eslint-visitor-keys "^3.4.1" + "@uifabric/set-version@^7.0.23": version "7.0.23" resolved "https://registry.yarnpkg.com/@uifabric/set-version/-/set-version-7.0.23.tgz#bfe10b6ba17a2518704cca856bdba8adbc11ffb0" @@ -9455,10 +9536,10 @@ configstore@^3.0.0: write-file-atomic "^2.0.0" xdg-basedir "^3.0.0" -confusing-browser-globals@^1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz#30d1e7f3d1b882b25ec4933d1d1adac353d20a59" - integrity sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA== +confusing-browser-globals@^1.0.10, confusing-browser-globals@^1.0.9: + version "1.0.11" + resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" + integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA== connect-history-api-fallback@1.6.0, connect-history-api-fallback@^1.6.0: version "1.6.0" @@ -16517,7 +16598,7 @@ json5@^2.1.0, json5@^2.1.2, json5@^2.1.3, json5@^2.2.1, json5@^2.2.2, json5@^2.2 resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== -jsonc-eslint-parser@2.3.0: +jsonc-eslint-parser@2.3.0, jsonc-eslint-parser@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/jsonc-eslint-parser/-/jsonc-eslint-parser-2.3.0.tgz#7c2de97d01bff7227cbef2f25d1025d42a36198b" integrity sha512-9xZPKVYp9DxnM3sd1yAsh/d59iIaswDkai8oTxbursfKYbg/ibjX0IzFt35+VZ8iEW453TVTXztnRvYUQlAfUQ== @@ -18346,6 +18427,13 @@ minimatch@9.0.1: dependencies: brace-expansion "^2.0.1" +minimatch@9.0.3, minimatch@^9.0.0, minimatch@^9.0.1, minimatch@^9.0.3: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + minimatch@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" @@ -18360,13 +18448,6 @@ minimatch@^8.0.2: dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.0, minimatch@^9.0.1, minimatch@^9.0.3: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - minimist-options@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" @@ -24619,6 +24700,11 @@ truncate-utf8-bytes@^1.0.0: dependencies: utf8-byte-length "^1.0.1" +ts-api-utils@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" + integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg== + ts-dedent@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5"