Migrate ESLint to 'flat' configuration (#28532)
Signed-off-by: Jon Koops <jonkoops@gmail.com>
This commit is contained in:
parent
3ba9a905c9
commit
debccef24b
13 changed files with 1223 additions and 1545 deletions
113
js/.eslintrc.cjs
113
js/.eslintrc.cjs
|
@ -1,113 +0,0 @@
|
|||
/** @type {import("eslint").Linter.Config } */
|
||||
module.exports = {
|
||||
root: true,
|
||||
ignorePatterns: [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"target",
|
||||
"keycloak-theme",
|
||||
"server",
|
||||
// Keycloak JS follows a completely different and outdated style, so we'll exclude it for now.
|
||||
// TODO: Eventually align the code-style for Keycloak JS.
|
||||
"libs/keycloak-js",
|
||||
],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: "./tsconfig.eslint.json",
|
||||
extraFileExtensions: [".mjs"],
|
||||
},
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
plugins: ["lodash"],
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
"plugin:import/recommended",
|
||||
"plugin:import/typescript",
|
||||
"plugin:react/recommended",
|
||||
"plugin:react/jsx-runtime",
|
||||
"plugin:react-hooks/recommended",
|
||||
"plugin:@typescript-eslint/base",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:prettier/recommended",
|
||||
],
|
||||
settings: {
|
||||
react: {
|
||||
version: "detect",
|
||||
},
|
||||
"import/resolver": {
|
||||
typescript: true,
|
||||
node: true,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
// Prefer using `includes()` to check if values exist over `indexOf() === -1`, as it's a more appropriate API for this.
|
||||
"@typescript-eslint/prefer-includes": "error",
|
||||
// Prefer using an optional chain expression, as it's more concise and easier to read.
|
||||
"@typescript-eslint/prefer-optional-chain": "error",
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-empty-function": "error",
|
||||
"@typescript-eslint/no-unnecessary-condition": "warn",
|
||||
"@typescript-eslint/no-unused-vars": "error",
|
||||
"lodash/import-scope": ["error", "member"],
|
||||
// react/prop-types cannot handle generic props, so we need to disable it.
|
||||
// https://github.com/yannickcr/eslint-plugin-react/issues/2777#issuecomment-814968432
|
||||
"react/prop-types": "off",
|
||||
// Prevent fragments from being added that have only a single child.
|
||||
"react/jsx-no-useless-fragment": "error",
|
||||
// Ban nesting components, as this will cause unintended re-mounting of components.
|
||||
// TODO: All issues should be fixed and this rule should be set to "error".
|
||||
"react/no-unstable-nested-components": ["warn", { allowAsProps: true }],
|
||||
"prefer-arrow-callback": "error",
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{
|
||||
endOfLine: "auto",
|
||||
},
|
||||
],
|
||||
// Prevent default imports from React, named imports should be used instead.
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
paths: [
|
||||
{
|
||||
name: "react",
|
||||
importNames: ["default"],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
// Prefer using the `#private` syntax for private class members, we want to keep this consistent and use the same syntax.
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
selector:
|
||||
':matches(PropertyDefinition, MethodDefinition)[accessibility="private"]',
|
||||
message: "Use #private instead",
|
||||
},
|
||||
],
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ["*.test.*"],
|
||||
rules: {
|
||||
// For tests it can make sense to pass empty functions as mocks.
|
||||
"@typescript-eslint/no-empty-function": "off",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["**/cypress/**/*"],
|
||||
extends: ["plugin:cypress/recommended", "plugin:mocha/recommended"],
|
||||
// TODO: Set these rules to "error" when issues have been resolved.
|
||||
rules: {
|
||||
"cypress/no-unnecessary-waiting": "warn",
|
||||
"cypress/unsafe-to-chain-command": "warn",
|
||||
"mocha/max-top-level-suites": "off",
|
||||
"mocha/no-exclusive-tests": "error",
|
||||
"mocha/no-identical-title": "off",
|
||||
"mocha/no-mocha-arrows": "off",
|
||||
"mocha/no-setup-in-describe": "off",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
|
@ -1,8 +1,12 @@
|
|||
# Coding Guidelines
|
||||
|
||||
## Package managers
|
||||
## Package management
|
||||
|
||||
The default package manager for the Keycloak UI projects is PNPM, we recommend installing it with [Corepack](https://nodejs.org/api/corepack.html) for the best compatibility.
|
||||
The default package manager is PNPM, we recommend enabling [Corepack](https://nodejs.org/api/corepack.html) for the best compatibility, which will automatically ensure the correct version of PNPM is used:
|
||||
|
||||
```sh
|
||||
corepack enable
|
||||
```
|
||||
|
||||
There are several reasons why PNPM is used over other package managers (such as NPM and Yarn):
|
||||
|
||||
|
@ -14,24 +18,30 @@ If you submit a pull request that changes the dependencies, make sure that you a
|
|||
|
||||
Since this project relies greatly on [PNPM workspaces](https://pnpm.io/workspaces) it is recommended you familiarize yourself with features such as [`--filter`](https://pnpm.io/filtering).
|
||||
|
||||
## Typescript
|
||||
## Code-style
|
||||
|
||||
The Keycloak UI projects uses best practices based off the official [React TypeScript Cheat sheet](https://react-typescript-cheatsheet.netlify.app/), with modifications for this project. The React TypeScript Cheat sheet is maintained and used by developers through out the world, and is a place where developers can bring together lessons learned using TypeScript and React.
|
||||
### Linting
|
||||
|
||||
To ensure code-style is consistent between various contributions [ESLint](https://eslint.org/) is used to enforce a common set of guidelines. The [recommended rules](https://eslint.org/docs/latest/rules/) of ESLint are used as a foundation.
|
||||
|
||||
For TypeScript code-style the recommendations of [`typescript-eslint`](https://typescript-eslint.io/) are adhered to as much as possible, specifically the [`strict-type-checked`](https://typescript-eslint.io/users/configs#strict-type-checked) and [`stylistic-type-checked`](https://typescript-eslint.io/users/configs#stylistic-type-checked) configurations.
|
||||
|
||||
Deviations from, or additions to these rules should be documented by comments in the [ESLint configuration](.eslintrc.cjs).
|
||||
|
||||
### Non-null assertion operator
|
||||
|
||||
In the project you will sometimes see the [non-null assertion operator](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator) (`!`) used to tell the TypeScript compiler that you guarantee that a value is not `null` or `undefined`. Because this might possibly introduce errors at run-time if you have not checked this value yourself it should be used sparingly.
|
||||
The [non-null assertion operator](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator) (`!`) is sometimes used to tell the TypeScript compiler that it is guaranteed that a value is not `null` or `undefined`. Because this might possibly introduce errors at run-time it should be used sparingly.
|
||||
|
||||
The only place where it is valid to use the non-null assertion operator is on the types that are provided by the [Admin API client](https://github.com/keycloak/keycloak-nodejs-admin-client). The reason for this is that the types are generated from Java code, which does not explicitly provide information about the nullability of fields (more on that [here](https://github.com/keycloak/keycloak-nodejs-admin-client/issues/187)).
|
||||
|
||||
## State management
|
||||
|
||||
### State management
|
||||
We have made a conscious decision to stay away from state management technologies such as Redux. These overarching state management schemes tend to be overly complex and encourage dumping everything into the global state.
|
||||
|
||||
We have made a conscious decision to stay away from state management technologies such as Redux. These overarching state management schemes tend to be overly complex and encourage dumping everything into the global state.
|
||||
Instead, we are following a simple philosophy that state should remain close to where it is used and moved to a wider scope only as truly needed. This encourages encapsulation and makes management of the state much simpler.
|
||||
|
||||
Instead, we are following a simple philosophy that state should remain close to where it is used and moved to a wider scope only as truly needed. This encourages encapsulation and makes management of the state much simpler.
|
||||
The way this plays out in our application is that we first prefer state to remain in the scope of the component that uses it. If the state is required by more than one component, we move to a more complex strategy for management of that state. In other words, in order of preference, state should be managed by:
|
||||
|
||||
The way this plays out in our application is that we first prefer state to remain in the scope of the component that uses it. If the state is required by more than one component, we move to a more complex strategy for management of that state. In other words, in order of preference, state should be managed by:
|
||||
1. Storing in the component that uses it.
|
||||
2. If #1 is not sufficient, [lift state up](https://reactjs.org/docs/lifting-state-up.html).
|
||||
3. If #2 is not sufficient, try [component composition](https://reactjs.org/docs/context.html#before-you-use-context).
|
||||
|
@ -39,7 +49,7 @@ The way this plays out in our application is that we first prefer state to remai
|
|||
|
||||
A good tutorial on this approach is found in [Kent Dodds’ blog](https://kentcdodds.com/blog/application-state-management-with-react).
|
||||
|
||||
### Hooks
|
||||
## Hooks
|
||||
|
||||
When using hooks with Typescript there are few recommendations that we follow below. Additional recommendations besides the ones mentioned in this document can be found [here](https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/hooks).
|
||||
|
||||
|
@ -63,18 +73,14 @@ setUser(newUser);
|
|||
|
||||
```
|
||||
|
||||
#### useReducers
|
||||
### useReducers
|
||||
|
||||
When using reducers make sure you specify the [return type and not use inference](https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/hooks#usereducer).
|
||||
|
||||
#### useEffect
|
||||
### useEffect
|
||||
|
||||
For useEffect only [return the function or undefined](https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/hooks#useeffect).
|
||||
|
||||
### Additional Typescript Pointers
|
||||
|
||||
Besides the details outlined above a list of recommendations for Typescript is maintained by several Typescript React developers [here](https://react-typescript-cheatsheet.netlify.app/). This is a great reference to use for any additional questions that are not outlined within the coding standards.
|
||||
|
||||
## CSS
|
||||
|
||||
We use custom CSS in rare cases where PatternFly styling does not meet our design guidelines. If styling needs to be added, we should first check that the PatternFly component is being properly built and whether a variant is already provided to meet the use case. Next, PatternFly layouts should be used for most positioning of components. For one-off tweaks (e.g. spacing an icon slightly away from the text next to it), a PatternFly utility class should be used. In all cases, PatternFly variables should be used for colors, spacing, etc. rather than hard coding color or pixel values.
|
||||
|
@ -83,9 +89,9 @@ We will use one global CSS file to surface customization variables. Styles parti
|
|||
|
||||
### Location of files, location of classes
|
||||
|
||||
* Global styling should be located…? *./public/index.css*.
|
||||
- Global styling should be located…? _./public/index.css_.
|
||||
|
||||
* The CSS relating to a single component should be located in a file within each component’s folder.
|
||||
- The CSS relating to a single component should be located in a file within each component’s folder.
|
||||
|
||||
### Naming CSS classes
|
||||
|
||||
|
@ -94,11 +100,13 @@ PatternFly reference https://pf4.patternfly.org/guidelines#variables
|
|||
For the Admin UI, we modify the PatternFly convention to namespace the classes and variables to the Keycloak packages.
|
||||
|
||||
**Class name**
|
||||
|
||||
```css
|
||||
.keycloak-admin--block[__element][--modifier][--state][--breakpoint][--pseudo-element]
|
||||
```
|
||||
|
||||
**Examples of custom CSS classes**
|
||||
|
||||
```css
|
||||
// Modification to all data tables throughout Keycloak admin
|
||||
.keycloak-admin--data-table {
|
||||
|
@ -123,6 +131,7 @@ For the Admin UI, we modify the PatternFly convention to namespace the classes a
|
|||
...
|
||||
}
|
||||
```
|
||||
|
||||
### Naming CSS custom properties and using PatternFly’s custom properties
|
||||
|
||||
Usually, PatternFly components will properly style components. Sometimes problems with the spacing or other styling indicate that a wrapper component is missing or that components haven’t been put together quite as intended. Often there is a variant of the component available that will accomplish the design.
|
||||
|
@ -134,89 +143,90 @@ These values can be seen in the [PatternFly design guidelines](https://v4-archiv
|
|||
For the Admin UI, we modify the PatternFly convention to namespace the classes and variables to the Keycloak packages.
|
||||
|
||||
**Custom property**
|
||||
|
||||
```css
|
||||
--keycloak-admin--block[__element][--modifier][--state][--breakpoint][--pseudo-element]--PropertyCamelCase
|
||||
```
|
||||
|
||||
**Example of a CSS custom property**
|
||||
|
||||
```css
|
||||
// Modify the height of the brand image
|
||||
--keycloak-admin--brand--Height: var(--pf-v5-global--spacer--xl);
|
||||
```
|
||||
|
||||
**Example**
|
||||
|
||||
```css
|
||||
// Don’t increase specificity
|
||||
// Don’t use pixel values
|
||||
.keycloak-admin--manage-columns__modal .pf-v5-c-dropdown {
|
||||
margin-bottom: 24px
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
// Do use a new class
|
||||
// Do use a PatternFly global spacer variable
|
||||
.keycloak-admin--manage-columns__dropdown {
|
||||
margin-bottom: var(--pf-v5-global--spacer--xl);
|
||||
margin-bottom: var(--pf-v5-global--spacer--xl);
|
||||
}
|
||||
```
|
||||
|
||||
### Using utility classes
|
||||
|
||||
Utility classes can be used to add specific styling to a component, such as margin-bottom or padding. However, their use should be limited to one-off styling needs.
|
||||
|
||||
For example, instead of using the utility class for margin-right multiple times, we should define a new Admin UI class that adds this *margin-right: var(--pf-v5-global--spacer--sm);* and in this example, the new class can set the color appropriately as well.
|
||||
For example, instead of using the utility class for margin-right multiple times, we should define a new Admin UI class that adds this _margin-right: var(--pf-v5-global--spacer--sm);_ and in this example, the new class can set the color appropriately as well.
|
||||
|
||||
**Using a utility class **
|
||||
```css
|
||||
|
||||
```js
|
||||
switch (titleStatus) {
|
||||
case "success":
|
||||
return (
|
||||
<>
|
||||
<InfoCircleIcon
|
||||
className="pf-v5-u-mr-sm" // utility class
|
||||
color="var(--pf-v5-global--info-color--100)"
|
||||
/>{" "}
|
||||
{titleText}{" "}
|
||||
</>
|
||||
);
|
||||
case "failure":
|
||||
return (
|
||||
<>
|
||||
<InfoCircleIcon
|
||||
className="pf-v5-u-mr-sm"
|
||||
color="var(--pf-v5-global--danger-color--100)"
|
||||
/>{" "}
|
||||
{titleText}{" "}
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
case "success":
|
||||
return (
|
||||
<>
|
||||
<InfoCircleIcon
|
||||
className="pf-v5-u-mr-sm" // utility class
|
||||
color="var(--pf-v5-global--info-color--100)"
|
||||
/>{" "}
|
||||
{titleText}
|
||||
</>
|
||||
);
|
||||
case "failure":
|
||||
return (
|
||||
<>
|
||||
<InfoCircleIcon
|
||||
className="pf-v5-u-mr-sm"
|
||||
color="var(--pf-v5-global--danger-color--100)"
|
||||
/>{" "}
|
||||
{titleText}
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**Better way with a custom class**
|
||||
```css
|
||||
|
||||
```js
|
||||
switch (titleStatus) {
|
||||
case "success":
|
||||
return (
|
||||
<>
|
||||
<InfoCircleIcon
|
||||
className="keycloak-admin--icon--info" // use a new keycloak class
|
||||
/>{" "}
|
||||
{titleText}{" "}
|
||||
</>
|
||||
);
|
||||
case "failure":
|
||||
return (
|
||||
<>
|
||||
<InfoCircleIcon
|
||||
className="keycloak-admin--icon--info"
|
||||
/>{" "}
|
||||
{titleText}{" "}
|
||||
</>
|
||||
);
|
||||
}
|
||||
case "success":
|
||||
return (
|
||||
<>
|
||||
<InfoCircleIcon
|
||||
className="keycloak-admin--icon--info" // use a new keycloak class
|
||||
/>{" "}
|
||||
{titleText}{" "}
|
||||
</>
|
||||
);
|
||||
case "failure":
|
||||
return (
|
||||
<>
|
||||
<InfoCircleIcon className="keycloak-admin--icon--info" /> {titleText}{" "}
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
* [PatternFly Docs](https://v4-archive.patternfly.org/v4/)
|
||||
* [Katacoda PatternFly tutorials](https://v4-archive.patternfly.org/v4/training/react)
|
||||
* [PatternFly global CSS variables](https://v4-archive.patternfly.org/v4/developer-resources/global-css-variables)
|
||||
* [PatternFly CSS utility classes](https://v4-archive.patternfly.org/v4/utilities/accessibility)
|
||||
* [React Typescript Cheat sheet](https://react-typescript-cheatsheet.netlify.app/)
|
||||
- [PatternFly Docs](https://www.patternfly.org/)
|
||||
- [Learn React](https://react.dev/learn)
|
||||
|
|
|
@ -8,7 +8,6 @@ This directory contains the UIs and related libraries of the Keycloak project wr
|
|||
│ ├── account-ui # Account UI for account management i.e controlling password and account access, tracking and managing permissions
|
||||
│ ├── admin-ui # Admin UI for handling login, registration, administration, and account management
|
||||
│ └── keycloak-server # Keycloak server for local development of UIs
|
||||
├── keycloak-theme # Maven build for the Keycloak theme
|
||||
├── libs
|
||||
│ ├── keycloak-admin-client # Keycloak Admin Client library for Keycloak REST API
|
||||
│ ├── keycloak-js # Keycloak JS library for securing HTML5/JavaScript applications
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
]
|
||||
},
|
||||
"lint": {
|
||||
"command": "eslint . --ext js,jsx,mjs,ts,tsx",
|
||||
"command": "eslint .",
|
||||
"dependencies": [
|
||||
"../../libs/ui-shared:build",
|
||||
"../../libs/keycloak-masthead:build",
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
]
|
||||
},
|
||||
"lint": {
|
||||
"command": "eslint . --ext js,jsx,mjs,ts,tsx",
|
||||
"command": "eslint .",
|
||||
"dependencies": [
|
||||
"../../libs/ui-shared:build",
|
||||
"../../libs/keycloak-js:build",
|
||||
|
|
153
js/eslint.config.js
Normal file
153
js/eslint.config.js
Normal file
|
@ -0,0 +1,153 @@
|
|||
// @ts-check
|
||||
import { FlatCompat } from "@eslint/eslintrc";
|
||||
import eslint from "@eslint/js";
|
||||
import mochaPlugin from "eslint-plugin-mocha";
|
||||
import prettierRecommended from "eslint-plugin-prettier/recommended";
|
||||
import reactJsxRuntime from "eslint-plugin-react/configs/jsx-runtime.js";
|
||||
import reactRecommended from "eslint-plugin-react/configs/recommended.js";
|
||||
import tseslint from "typescript-eslint";
|
||||
|
||||
const compat = new FlatCompat({
|
||||
baseDirectory: import.meta.dirname,
|
||||
});
|
||||
|
||||
export default tseslint.config(
|
||||
{
|
||||
ignores: [
|
||||
"**/dist/",
|
||||
"**/lib/",
|
||||
"**/target/",
|
||||
"./apps/keycloak-server/server/",
|
||||
// Keycloak JS follows a completely different and outdated style, so we'll exclude it for now.
|
||||
"./libs/keycloak-js/",
|
||||
],
|
||||
},
|
||||
eslint.configs.recommended,
|
||||
...tseslint.configs.strictTypeChecked,
|
||||
...tseslint.configs.stylisticTypeChecked,
|
||||
reactRecommended,
|
||||
reactJsxRuntime,
|
||||
...compat.extends("plugin:react-hooks/recommended"),
|
||||
prettierRecommended,
|
||||
...compat.plugins("lodash"),
|
||||
{
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
project: "./tsconfig.eslint.json",
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
react: {
|
||||
version: "detect",
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
// ## Rules overwriting config, disabled for now, but will have to be evaluated. ##
|
||||
"no-undef": "off",
|
||||
"no-unused-private-class-members": "off",
|
||||
"@typescript-eslint/array-type": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"@typescript-eslint/ban-tslint-comment": "off",
|
||||
"@typescript-eslint/ban-types": "off",
|
||||
"@typescript-eslint/consistent-indexed-object-style": "off",
|
||||
"@typescript-eslint/consistent-type-definitions": "off",
|
||||
"@typescript-eslint/dot-notation": "off",
|
||||
"@typescript-eslint/no-base-to-string": "off",
|
||||
"@typescript-eslint/no-confusing-non-null-assertion": "off",
|
||||
"@typescript-eslint/no-confusing-void-expression": "off",
|
||||
"@typescript-eslint/no-duplicate-type-constituents": "off",
|
||||
"@typescript-eslint/no-dynamic-delete": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-extraneous-class": "off",
|
||||
"@typescript-eslint/no-floating-promises": "off",
|
||||
"@typescript-eslint/no-inferrable-types": "off",
|
||||
"@typescript-eslint/no-invalid-void-type": "off",
|
||||
"@typescript-eslint/no-misused-promises": "off",
|
||||
"@typescript-eslint/no-non-null-asserted-optional-chain": "off",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"@typescript-eslint/no-redundant-type-constituents": "off",
|
||||
"@typescript-eslint/no-unnecessary-boolean-literal-compare": "off",
|
||||
"@typescript-eslint/no-unnecessary-condition": "off",
|
||||
"@typescript-eslint/no-unnecessary-type-arguments": "off",
|
||||
"@typescript-eslint/no-unnecessary-type-assertion": "off",
|
||||
"@typescript-eslint/no-unsafe-argument": "off",
|
||||
"@typescript-eslint/no-unsafe-assignment": "off",
|
||||
"@typescript-eslint/no-unsafe-call": "off",
|
||||
"@typescript-eslint/no-unsafe-enum-comparison": "off",
|
||||
"@typescript-eslint/no-unsafe-member-access": "off",
|
||||
"@typescript-eslint/no-unsafe-return": "off",
|
||||
"@typescript-eslint/no-useless-constructor": "off",
|
||||
"@typescript-eslint/no-useless-template-literals": "off",
|
||||
"@typescript-eslint/non-nullable-type-assertion-style": "off",
|
||||
"@typescript-eslint/only-throw-error": "off",
|
||||
"@typescript-eslint/prefer-for-of": "off",
|
||||
"@typescript-eslint/prefer-nullish-coalescing": "off",
|
||||
"@typescript-eslint/prefer-promise-reject-errors": "off",
|
||||
"@typescript-eslint/prefer-reduce-type-parameter": "off",
|
||||
"@typescript-eslint/prefer-ts-expect-error": "off",
|
||||
"@typescript-eslint/require-await": "off",
|
||||
"@typescript-eslint/restrict-plus-operands": "off",
|
||||
"@typescript-eslint/restrict-template-expressions": "off",
|
||||
"@typescript-eslint/unbound-method": "off",
|
||||
"@typescript-eslint/use-unknown-in-catch-callback-variable": "off",
|
||||
// ## Rules that are customized because of team preferences or other issues ##
|
||||
// Prevent default imports from React, named imports should be used instead.
|
||||
// This is a team preference, but also helps us enforce consistent imports.
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
paths: [
|
||||
{
|
||||
name: "react",
|
||||
importNames: ["default"],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
// Prefer using the `#private` syntax for private class members, we want to keep this consistent and use the same syntax.
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
selector:
|
||||
':matches(PropertyDefinition, MethodDefinition)[accessibility="private"]',
|
||||
message: "Use #private instead",
|
||||
},
|
||||
],
|
||||
// Require using arrow functions for callbacks, the team prefers this style over inconsistent function declarations.
|
||||
"prefer-arrow-callback": "error",
|
||||
// `react/prop-types` cannot handle generic props, so we need to disable it.
|
||||
// https://github.com/yannickcr/eslint-plugin-react/issues/2777#issuecomment-814968432
|
||||
"react/prop-types": "off",
|
||||
// Prevent fragments from being added that have only a single child.
|
||||
"react/jsx-no-useless-fragment": "error",
|
||||
// Ban nesting components, as this will cause unintended re-mounting of components.
|
||||
// See: https://react.dev/learn/your-first-component#nesting-and-organizing-components
|
||||
// TODO: Set this to "error" once all issues are fixed.
|
||||
"react/no-unstable-nested-components": ["warn", { allowAsProps: true }],
|
||||
// Prefer a specific import scope (e.g. `lodash/map` vs `lodash`).
|
||||
// Allows for more efficient tree-shaking and better code splitting.
|
||||
"lodash/import-scope": ["error", "member"],
|
||||
},
|
||||
},
|
||||
...[
|
||||
...compat.extends("plugin:cypress/recommended"),
|
||||
mochaPlugin.configs.flat.recommended,
|
||||
].map((config) => ({
|
||||
...config,
|
||||
files: ["**/cypress/**/*"],
|
||||
})),
|
||||
{
|
||||
files: ["**/cypress/**/*"],
|
||||
// TODO: Set these rules to "error" when issues have been resolved.
|
||||
rules: {
|
||||
"cypress/no-unnecessary-waiting": "warn",
|
||||
"cypress/unsafe-to-chain-command": "warn",
|
||||
"mocha/max-top-level-suites": "off",
|
||||
"mocha/no-exclusive-tests": "error",
|
||||
"mocha/no-identical-title": "off",
|
||||
"mocha/no-mocha-arrows": "off",
|
||||
"mocha/no-setup-in-describe": "off",
|
||||
},
|
||||
},
|
||||
);
|
|
@ -1 +0,0 @@
|
|||
lib
|
|
@ -30,7 +30,7 @@
|
|||
]
|
||||
},
|
||||
"lint": {
|
||||
"command": "eslint . --ext js,jsx,mjs,ts,tsx"
|
||||
"command": "eslint ."
|
||||
},
|
||||
"test": {
|
||||
"command": "TS_NODE_PROJECT=tsconfig.test.json mocha --recursive \"test/**/*.spec.ts\" --timeout 10000"
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
]
|
||||
},
|
||||
"lint": {
|
||||
"command": "eslint . --ext js,jsx,mjs,ts,tsx",
|
||||
"command": "eslint .",
|
||||
"dependencies": [
|
||||
"../../libs/keycloak-js:build"
|
||||
]
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
]
|
||||
},
|
||||
"lint": {
|
||||
"command": "eslint . --ext js,jsx,mjs,ts,tsx",
|
||||
"command": "eslint .",
|
||||
"dependencies": [
|
||||
"../keycloak-admin-client:build"
|
||||
]
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": ["**/*", ".eslintrc.js"],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"keycloak-theme",
|
||||
"server"
|
||||
]
|
||||
"include": ["**/*", "eslint.config.js"],
|
||||
"exclude": ["node_modules", "dist", "server"]
|
||||
}
|
||||
|
|
|
@ -5,14 +5,12 @@
|
|||
"prepare": "cd .. && husky js/.husky"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.0.2",
|
||||
"@eslint/js": "^9.0.0",
|
||||
"@types/node": "^20.12.5",
|
||||
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
||||
"@typescript-eslint/parser": "^6.21.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint": "^8.52.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-import-resolver-typescript": "^3.6.1",
|
||||
"eslint-plugin-cypress": "^2.15.1",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-lodash": "^7.4.0",
|
||||
"eslint-plugin-mocha": "^10.4.1",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
|
@ -23,6 +21,7 @@
|
|||
"prettier": "^3.2.5",
|
||||
"tslib": "^2.6.2",
|
||||
"typescript": "^5.4.4",
|
||||
"typescript-eslint": "^7.6.0",
|
||||
"wireit": "^0.14.4"
|
||||
},
|
||||
"packageManager": "pnpm@8.15.5",
|
||||
|
|
2306
pnpm-lock.yaml
2306
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue