chore(ws): show ESLint errors from local rules on IDE (#439)
Signed-off-by: Guilherme Caponetto <638737+caponetto@users.noreply.github.com>
This commit is contained in:
parent
c0b8f7b300
commit
eb8d3acb93
|
|
@ -1,5 +1,3 @@
|
|||
const noReactHookNamespace = require('./eslint-local-rules/no-react-hook-namespace');
|
||||
|
||||
module.exports = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
env: {
|
||||
|
|
@ -13,7 +11,7 @@ module.exports = {
|
|||
js: true,
|
||||
useJSXTextNode: true,
|
||||
project: './tsconfig.json',
|
||||
tsconfigRootDir: '.',
|
||||
tsconfigRootDir: __dirname,
|
||||
},
|
||||
// includes the typescript specific rules found here: https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#supported-rules
|
||||
plugins: [
|
||||
|
|
@ -24,6 +22,7 @@ module.exports = {
|
|||
'no-only-tests',
|
||||
'no-relative-import-paths',
|
||||
'prettier',
|
||||
'local-rules',
|
||||
],
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
|
|
@ -200,6 +199,17 @@ module.exports = {
|
|||
'no-lone-blocks': 'error',
|
||||
'no-lonely-if': 'error',
|
||||
'no-promise-executor-return': 'error',
|
||||
'no-restricted-imports': [
|
||||
'error',
|
||||
{
|
||||
paths: [
|
||||
{
|
||||
name: 'react-router',
|
||||
message: 'Use react-router-dom instead.',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
'no-restricted-globals': [
|
||||
'error',
|
||||
{
|
||||
|
|
@ -221,7 +231,8 @@ module.exports = {
|
|||
'symbol-description': 'error',
|
||||
yoda: 'error',
|
||||
'func-names': 'warn',
|
||||
'no-react-hook-namespace': 'error',
|
||||
'local-rules/no-react-hook-namespace': 'error',
|
||||
'local-rules/no-raw-react-router-hook': 'error',
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
|
|
@ -270,7 +281,20 @@ module.exports = {
|
|||
{
|
||||
files: ['**/*.{js,jsx,ts,tsx}'],
|
||||
rules: {
|
||||
'no-react-hook-namespace': 'error',
|
||||
'local-rules/no-react-hook-namespace': 'error',
|
||||
'local-rules/no-raw-react-router-hook': 'error',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['.eslintrc.js'],
|
||||
parserOptions: {
|
||||
project: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['eslint-local-rules/**/*.js'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-require-imports': 'off',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
module.exports = {
|
||||
'no-react-hook-namespace': require('./no-react-hook-namespace'),
|
||||
'no-raw-react-router-hook': require('./no-raw-react-router-hook'),
|
||||
};
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
module.exports = {
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'Disallow use of raw react-router-dom hooks. Use typed wrappers instead.',
|
||||
},
|
||||
messages: {
|
||||
avoidRawHook:
|
||||
'Use "{{typedHook}}" from `~/app/routerHelper` instead of raw React Router hook "{{rawHook}}".',
|
||||
},
|
||||
schema: [],
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const forbiddenHooks = {
|
||||
useNavigate: 'useTypedNavigate',
|
||||
useParams: 'useTypedParams',
|
||||
useSearchParams: 'useTypedSearchParams',
|
||||
useLocation: 'useTypedLocation',
|
||||
};
|
||||
|
||||
return {
|
||||
ImportDeclaration(node) {
|
||||
if (node.source.value !== 'react-router-dom') {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const specifier of node.specifiers) {
|
||||
if (
|
||||
specifier.type === 'ImportSpecifier' &&
|
||||
Object.prototype.hasOwnProperty.call(forbiddenHooks, specifier.imported.name)
|
||||
) {
|
||||
context.report({
|
||||
node: specifier,
|
||||
messageId: 'avoidRawHook',
|
||||
data: {
|
||||
rawHook: specifier.imported.name,
|
||||
typedHook: forbiddenHooks[specifier.imported.name],
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
"@patternfly/react-tokens": "^6.2.0",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"date-fns": "^4.1.0",
|
||||
"eslint-plugin-local-rules": "^3.0.2",
|
||||
"js-yaml": "^4.1.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"react": "^18",
|
||||
|
|
@ -9966,6 +9967,11 @@
|
|||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/eslint-plugin-local-rules": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-local-rules/-/eslint-plugin-local-rules-3.0.2.tgz",
|
||||
"integrity": "sha512-IWME7GIYHXogTkFsToLdBCQVJ0U4kbSuVyDT+nKoR4UgtnVrrVeNWuAZkdEu1nxkvi9nsPccGehEEF6dgA28IQ=="
|
||||
},
|
||||
"node_modules/eslint-plugin-no-only-tests": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-no-only-tests/-/eslint-plugin-no-only-tests-3.3.0.tgz",
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@
|
|||
"test:unit": "npm run test:jest -- --silent",
|
||||
"test:watch": "jest --watch",
|
||||
"test:coverage": "jest --coverage",
|
||||
"test:fix": "eslint --rulesdir eslint-local-rules --ext .js,.ts,.jsx,.tsx ./src --fix",
|
||||
"test:lint": "eslint --rulesdir eslint-local-rules --max-warnings 0 --ext .js,.ts,.jsx,.tsx ./src",
|
||||
"test:fix": "eslint --ext .js,.ts,.jsx,.tsx ./src --fix",
|
||||
"test:lint": "eslint --max-warnings 0 --ext .js,.ts,.jsx,.tsx ./src",
|
||||
"cypress:open": "cypress open --project src/__tests__/cypress",
|
||||
"cypress:open:mock": "CY_MOCK=1 CY_WS_PORT=9002 npm run cypress:open -- ",
|
||||
"cypress:run": "cypress run -b chrome --project src/__tests__/cypress",
|
||||
|
|
@ -108,6 +108,7 @@
|
|||
"@patternfly/react-tokens": "^6.2.0",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"date-fns": "^4.1.0",
|
||||
"eslint-plugin-local-rules": "^3.0.2",
|
||||
"js-yaml": "^4.1.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"react": "^18",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState } from 'react';
|
||||
import { NavLink, useLocation } from 'react-router-dom';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import {
|
||||
Brand,
|
||||
Nav,
|
||||
|
|
@ -9,11 +9,12 @@ import {
|
|||
PageSidebar,
|
||||
PageSidebarBody,
|
||||
} from '@patternfly/react-core';
|
||||
import { useTypedLocation } from '~/app/routerHelper';
|
||||
import { useNavData, isNavDataGroup, NavDataHref, NavDataGroup } from './AppRoutes';
|
||||
import { isMUITheme, LOGO_LIGHT } from './const';
|
||||
|
||||
const NavHref: React.FC<{ item: NavDataHref }> = ({ item }) => {
|
||||
const location = useLocation();
|
||||
const location = useTypedLocation();
|
||||
|
||||
// With the redirect in place, we can now use a simple path comparison.
|
||||
const isActive = location.pathname === item.path;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { useLocation, matchPath } from 'react-router-dom';
|
||||
import { matchPath } from 'react-router-dom';
|
||||
import { AppRouteKey, AppRoutePaths } from '~/app/routes';
|
||||
import { useTypedLocation } from '~/app/routerHelper';
|
||||
|
||||
export function useCurrentRouteKey(): AppRouteKey | undefined {
|
||||
const location = useLocation();
|
||||
const location = useTypedLocation();
|
||||
const { pathname } = location;
|
||||
|
||||
const matchEntries = Object.entries(AppRoutePaths) as [AppRouteKey, string][];
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
/* eslint-disable local-rules/no-raw-react-router-hook */
|
||||
|
||||
import {
|
||||
generatePath,
|
||||
Location,
|
||||
|
|
|
|||
Loading…
Reference in New Issue