Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: migrate to eslint 9 #142

Merged
merged 1 commit into from
Dec 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions .eslintignore

This file was deleted.

3 changes: 0 additions & 3 deletions .eslintrc.cjs

This file was deleted.

2 changes: 1 addition & 1 deletion .storybook/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {StorybookConfig} from "@storybook/react-vite";
import type { StorybookConfig } from "@storybook/react-vite";

const config: StorybookConfig = {
staticDirs: ["../packages/tailwind/build"],
Expand Down
18 changes: 10 additions & 8 deletions .storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import tailwind from '@tsed/tailwind-formio'
import {Formio, Templates} from '@tsed/react-formio'
import {INITIAL_VIEWPORTS} from '@storybook/addon-viewport'
import "./styles/index.css";

Formio.use(tailwind)
Templates.framework = 'tailwind'
import { INITIAL_VIEWPORTS } from "@storybook/addon-viewport";
import { Formio, Templates } from "@tsed/react-formio";
import tailwind from "@tsed/tailwind-formio";

// eslint-disable-next-line react-hooks/rules-of-hooks
Formio.use(tailwind);
Templates.framework = "tailwind";

Comment on lines +3 to +9
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Remove unnecessary ESLint directive for hooks rule

The ESLint directive to disable react-hooks/rules-of-hooks appears to be unnecessary because:

  • Formio.use() is a regular method call, not a React Hook
  • There's no evidence of React Hook usage in the storybook configuration
  • The same Formio.use(tailwind) pattern is used in other files without requiring the ESLint directive

You can safely remove the // eslint-disable-next-line react-hooks/rules-of-hooks comment.

🔗 Analysis chain

Verify the necessity of disabling the hooks rule.

The ESLint directive to disable react-hooks/rules-of-hooks has been added. However, since Formio.use() is not a React Hook, this directive might be unnecessary. Consider removing it if the ESLint warning is no longer present with the new ESLint configuration.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if the hooks rule warning occurs without the disable directive
# First, create a temporary file without the eslint-disable comment
cat > temp.ts << 'EOL'
import { INITIAL_VIEWPORTS } from "@storybook/addon-viewport";
import { Formio, Templates } from "@tsed/react-formio";
import tailwind from "@tsed/tailwind-formio";

Formio.use(tailwind);
Templates.framework = "tailwind";
EOL

# Run ESLint on the temporary file
eslint temp.ts

Length of output: 120


Script:

#!/bin/bash
# Let's check if there are any similar ESLint directives in the codebase
# and understand the context better
rg "eslint-disable.*react-hooks" -A 2 -B 2

# Also check for any Formio.use patterns to see how they're used elsewhere
rg "Formio\.use" -A 2 -B 2

# Let's also check the ESLint configuration to understand the rules
fd -e .eslintrc -e .eslintrc.js -e .eslintrc.json -e .eslintrc.yml

Length of output: 564


Script:

#!/bin/bash
# Let's check the storybook configuration files for any React-related setup
# that might explain the hooks rule
fd -g "*.js" -g "*.ts" .storybook/

# Also check for any React hooks usage in the storybook files
rg "use[A-Z]" .storybook/ -A 2 -B 2

# Check if there are any other instances of Formio.use in storybook files
rg "Formio" .storybook/ -A 2 -B 2

Length of output: 636

/** @type { import('@storybook/react').Preview } */
const preview = {
parameters: {
actions: {argTypesRegex: '^on[A-Z].*'},
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
Expand All @@ -20,6 +22,6 @@ const preview = {
viewport: {
viewports: INITIAL_VIEWPORTS
}
}
};

export default preview
export default preview;
146 changes: 146 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import typescriptEslint from "@typescript-eslint/eslint-plugin";
import typescriptParser from "@typescript-eslint/parser";
import pluginJsxA11y from "eslint-plugin-jsx-a11y";
import pluginPrettierRecommended from "eslint-plugin-prettier/recommended";
import pluginReact from "eslint-plugin-react";
import pluginReactHooks from "eslint-plugin-react-hooks";
import pluginSimpleImportSort from "eslint-plugin-simple-import-sort";
import pluginTestingLibrary from "eslint-plugin-testing-library";
// import vitest from "eslint-plugin-vitest";
import pluginWorkspaces from "eslint-plugin-workspaces";

export default [
{
ignores: ["**/coverage", "**/dist/**", "**/build/**", "**/storybook-static", "**/*.ejs.js"]
},
{
files: ["**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}"],
...pluginReact.configs.flat.recommended,
settings: {
react: {
version: "detect"
}
},
languageOptions: {
...pluginReact.configs.flat.recommended.languageOptions
// globals: {
// ...globals.serviceworker,
// ...globals.browser
// }
},
rules: {
...pluginReact.configs.flat.recommended.rules,
"react/no-unescaped-entities": "off",
"react/react-in-jsx-scope": "off",
"react/prop-types": "off",
"react/display-name": "warn"
}
},
{
files: ["**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}"],
languageOptions: {
ecmaVersion: "latest",
sourceType: "module",
parser: typescriptParser,
parserOptions: {
ecmaFeatures: {
jsx: true
},
ecmaVersion: "latest",
sourceType: "module"
}
// globals: {
// ...globals.browser
// }
},
plugins: {
"@typescript-eslint": typescriptEslint
},
rules: {
"@typescript-eslint/no-unused-vars": "error"
}
},
pluginJsxA11y.flatConfigs.recommended,
{
files: ["**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}"],
languageOptions: {
parserOptions: {
ecmaFeatures: {
jsx: true
}
}
},
plugins: {
"react-hooks": pluginReactHooks,
"simple-import-sort": pluginSimpleImportSort,
workspaces: pluginWorkspaces
},
rules: {
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error",
"workspaces/no-absolute-imports": "error",
"react-hooks/rules-of-hooks": "error", // Checks rules of Hooks
"react-hooks/exhaustive-deps": "warn" // Checks effect dependencies
}
},
// {
// files: ["**/*.spec.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}"],
// plugins: {
// vitest
// },
// rules: {
// ...vitest.configs.recommended.rules
// }
// },
// {
// files: ["**/*.spec.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}"], // or any other pattern
// plugins: {
// vitest
// },
// rules: {
// ...vitest.configs.recommended.rules, // you can also use vitest.configs.all.rules to enable all rules
// "vitest/consistent-test-it": [
// "error",
// { fn: "it", withinDescribe: "it" }
// ],
// "vitest/no-alias-methods": "error"
// }
// },
{
files: ["**/*.spec.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}"],
plugins: {
"testing-library": pluginTestingLibrary
},
rules: {
"testing-library/await-async-events": ["error", { eventModule: "userEvent" }],
"testing-library/await-async-queries": "error",
"testing-library/await-async-utils": "error",
"testing-library/no-await-sync-events": ["error", { eventModules: ["fire-event"] }],
"testing-library/no-await-sync-queries": "error",
"testing-library/no-container": "error",
"testing-library/no-debugging-utils": "warn",
"testing-library/no-dom-import": ["error", "react"],
"testing-library/no-global-regexp-flag-in-query": "error",
"testing-library/no-manual-cleanup": "error",
"testing-library/no-node-access": "warn",
"testing-library/no-promise-in-fire-event": "error",
"testing-library/no-render-in-lifecycle": "error",
"testing-library/no-unnecessary-act": "error",
"testing-library/no-wait-for-multiple-assertions": "error",
"testing-library/no-wait-for-side-effects": "error",
"testing-library/no-wait-for-snapshot": "error",
"testing-library/prefer-find-by": "error",
"testing-library/prefer-presence-queries": "error",
"testing-library/prefer-query-by-disappearance": "error",
"testing-library/prefer-screen-queries": "error",
"testing-library/render-result-naming-convention": "error"
}
},
pluginPrettierRecommended,
{
files: ["**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}"],
rules: {
curly: ["error", "all"]
}
}
];
39 changes: 18 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@
"configure": "monorepo ci configure",
"test": "lerna run test --stream",
"test:coverage:update": "lerna run test:coverage:update --stream",
"lint": "lerna run lint --stream",
"lint:fix": "lerna run lint:fix --stream",
"prettier": "prettier '**/*.{ts,js,json,md,yml,yaml}' --write",
"lint": "eslint",
"lint:fix": "eslint",
Comment on lines +21 to +22
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Lint scripts might be too minimal.

The lint scripts have been simplified from using Lerna to direct ESLint calls, but they're missing necessary arguments:

  • No file patterns specified
  • No configuration file referenced
  • No additional flags for fixing

Consider updating the scripts to be more explicit:

-    "lint": "eslint",
-    "lint:fix": "eslint",
+    "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
+    "lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"lint": "eslint",
"lint:fix": "eslint",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
"lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix"

"build": "monorepo build --verbose",
"publish": "monorepo publish --dry-run",
"start": "lerna run start --stream --parallel",
Expand Down Expand Up @@ -63,8 +62,8 @@
},
"devDependencies": {
"@chromatic-com/storybook": "3.2.3",
"@commitlint/cli": "^17.0.3",
"@commitlint/config-conventional": "^17.0.3",
"@commitlint/cli": "19.6.1",
"@commitlint/config-conventional": "19.6.0",
"@storybook/addon-a11y": "^8.4.7",
"@storybook/addon-essentials": "^8.4.7",
"@storybook/addon-interactions": "^8.4.7",
Expand All @@ -90,23 +89,23 @@
"@types/prop-types": "^15.7.5",
"@types/react-dnd": "3.0.2",
"@types/react-dnd-html5-backend": "3.0.2",
"@typescript-eslint/eslint-plugin": "8.18.2",
"@typescript-eslint/parser": "8.18.2",
"@vitejs/plugin-react": "^4.3.4",
"autoprefixer": "^10.4.7",
"babel-eslint": "^10.1.0",
"camelcase": "6.3.0",
"chromatic": "11.20.2",
"cross-env": "7.0.3",
"eslint": "^8.15.0",
"eslint-config-prettier": "^8.5.0",
"eslint-config-react-app": "^7.0.1",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.30.1",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-simple-import-sort": "^7.0.0",
"eslint-plugin-testing-library": "^5.5.1",
"eslint-plugin-workspaces": "^0.7.0",
"eslint": "9.17.0",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-jsx-a11y": "6.10.2",
"eslint-plugin-prettier": "5.2.1",
"eslint-plugin-react": "7.37.3",
"eslint-plugin-react-hooks": "5.1.0",
"eslint-plugin-simple-import-sort": "12.1.1",
"eslint-plugin-storybook": "0.11.1",
"eslint-plugin-testing-library": "7.1.1",
"eslint-plugin-workspaces": "0.10.1",
Comment on lines +92 to +108
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

ESLint version needs to be downgraded to 8.57.0

The dependency check reveals an incompatibility in the current setup:

  • @typescript-eslint/[email protected] requires ESLint version ^8.57.0 || ^9.0.0
  • Current ESLint version is 9.17.0
  • Latest version of @typescript-eslint/eslint-plugin is still 8.18.2

To resolve this, you should downgrade ESLint to version 8.57.0 since:

  • The TypeScript ESLint plugin is at its latest version but requires ESLint 8.57.0
  • Other plugins (react, react-hooks) are compatible with ESLint 8.x
  • This ensures maximum compatibility across all plugins
🔗 Analysis chain

Verify ESLint plugin compatibility.

The ESLint upgrade to version 9.x comes with several plugin updates. The versions look compatible, but let's verify the peer dependencies.


ESLint plugin compatibility issue detected with @typescript-eslint/eslint-plugin

The peer dependency check reveals an incompatibility:

  • @typescript-eslint/[email protected] requires eslint: ^8.57.0 || ^9.0.0, but the project uses [email protected]
  • Other plugins (eslint-plugin-react and eslint-plugin-react-hooks) are compatible with ESLint 9.x

Let's verify if there's a newer version of @typescript-eslint/eslint-plugin that might be compatible:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check peer dependency compatibility
npm info [email protected] peerDependencies
npm info @typescript-eslint/[email protected] peerDependencies
npm info [email protected] peerDependencies
npm info [email protected] peerDependencies

Length of output: 503


Script:

#!/bin/bash
# Check latest version of @typescript-eslint/eslint-plugin
npm info @typescript-eslint/eslint-plugin dist-tags.latest

Length of output: 67

"fs-extra": "10.1.0",
"husky": "^8.0.1",
"jest": "^28.1.2",
Expand All @@ -121,16 +120,14 @@
"postcss-normalize": "10.0.1",
"postcss-preset-env": "7.7.2",
"postcss-safe-parser": "6.0.0",
"prettier": "^2.6.2",
"prettier-eslint": "^14.0.3",
"prettier": "3.4.2",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-svg": "10.0.23",
"rimraf": "^3.0.2",
"semantic-release": "23.0.5",
"semantic-release-slack-bot": "4.0.2",
"serve": "^13.0.4",
"storybook": "^8.4.7",
"typescript": "4.9.5",
"vite": "5.1.8",
Expand Down Expand Up @@ -161,7 +158,7 @@
]
},
"lint-staged": {
"**/*.{ts,js}": [
"**/*.{tsx,ts,js,jsx}": [
"eslint --fix"
],
"**/*.{json,md,yml,yaml}": [
Expand Down
4 changes: 0 additions & 4 deletions packages/config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@
"license": "MIT",
"private": true,
"type": "commonjs",
"scripts": {
"lint": "eslint \"**/*.{js,jsx,ts,tsx}\"",
"lint:fix": "yarn lint --fix"
},
"bin": {
"write-coverage": "./bin/write-coverage.js"
},
Expand Down
2 changes: 0 additions & 2 deletions packages/react-formio-container/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
}
},
"scripts": {
"lint": "eslint \"**/*.{js,jsx,ts,tsx}\"",
"lint:fix": "yarn lint --fix",
"test": "cross-env NODE_ENV=test jest --coverage",
"test:coverage:update": "write-coverage",
"build": "microbundle --no-compress --format modern,cjs --jsx React.createElement --jsxFragment React.Fragment --globals react/jsx-runtime=jsx",
Expand Down
1 change: 0 additions & 1 deletion packages/react-formio-container/src/utils/HttpClient.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Formio } from "@tsed/react-formio";

export class HttpClient {
// eslint-disable-next-line no-useless-constructor
constructor(private host?: string) {}

get<T = any>(endpoint: string, data?: any, options?: any): Promise<T> {
Expand Down
3 changes: 2 additions & 1 deletion packages/react-formio-container/src/views/formEdit.view.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { FormEdit } from "@tsed/react-formio";
import classnames from "classnames";
import React from "react";

import { useForm } from "../hooks/useForm.hook";
Expand All @@ -7,7 +8,7 @@ export function FormEditView({ className, ...props }: ReturnType<typeof useForm>
const { form, saveForm, duplicateForm, i18n } = props;
const Component = props.FormEditComponent || FormEdit;
return (
<div className={"p-3 pb-1"}>
<div className={classnames("p-3 pb-1", className)}>
<Component {...props} form={form} onSubmit={saveForm} onCopy={duplicateForm} options={{ i18n }} />
</div>
);
Expand Down
2 changes: 0 additions & 2 deletions packages/react-formio-stores/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
}
},
"scripts": {
"lint": "eslint \"**/*.{js,jsx,ts,tsx}\"",
"lint:fix": "yarn lint --fix",
"test": "cross-env NODE_ENV=test jest --coverage",
"test:coverage:update": "write-coverage",
"build": "microbundle --no-compress --format modern,cjs --jsx React.createElement --jsxFragment React.Fragment --globals react/jsx-runtime=jsx",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ export async function getAccess(dispatch: any) {
dispatch(formAccessUser(AUTH, { formAccess }));
dispatch(userRoles(AUTH, { roles: result.roles }));
dispatch(userForms(AUTH, { forms: result.forms }));
} catch (err) {}
} catch {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ export async function getProjectAccess(dispatch: any) {
const projectAccess = transformProjectAccess(project.access);

dispatch(projectAccessUser(AUTH, projectAccess));
} catch (er) {}
} catch {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ describe("root Selectors", () => {
describe("selectRoot()", () => {
it("should return submission", () => {
expect(
// eslint-disable-next-line no-undef
selectRoot("submission", {
submission: {
data: {
Expand Down
1 change: 0 additions & 1 deletion packages/react-formio/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"source": "src/index.ts",
"license": "MIT",
"scripts": {
"lint": "eslint \"**/*.{js,jsx,ts,tsx}\"",
"lint:fix": "yarn lint --fix",
"test": "cross-env NODE_ENV=test jest --coverage",
"test:coverage:update": "write-coverage",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ describe("ActionsTable", () => {

const btn = screen.getByTestId("action-table-add");

await fireEvent.click(btn);
fireEvent.click(btn);
expect(onAddAction).not.toHaveBeenCalled();
});
it("should call addAction with the selected action", async () => {
Expand All @@ -73,7 +73,7 @@ describe("ActionsTable", () => {

await userEvent.selectOptions(select, String(args.availableActions[1].value));

await fireEvent.click(btn);
fireEvent.click(btn);

expect(btn).not.toHaveProperty("disabled", true);
expect(onAddAction).toHaveBeenCalledWith("sql");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
}

function useFormAccess({ form: formDefinition, roles, onSubmit, options }: FormAccessProps) {
// eslint-disable-next-line no-undef
const form = useMemo(() => getFormAccess(roles), [roles]);

const [submissions, setSubmissions] = useState(() => dataAccessToSubmissions(formDefinition, form));
Expand All @@ -42,7 +41,7 @@
setSubmissions(input);
}
}
}, [formDefinition?._id]);

Check warning on line 44 in packages/react-formio/src/components/form-access/formAccess.component.tsx

View workflow job for this annotation

GitHub Actions / lint

React Hook useEffect has missing dependencies: 'form', 'formDefinition', 'submissions.access', and 'submissions.submissionAccess'. Either include them or remove the dependency array

Check warning on line 44 in packages/react-formio/src/components/form-access/formAccess.component.tsx

View workflow job for this annotation

GitHub Actions / lint

React Hook useEffect has missing dependencies: 'form', 'formDefinition', 'submissions.access', and 'submissions.submissionAccess'. Either include them or remove the dependency array

Check warning on line 44 in packages/react-formio/src/components/form-access/formAccess.component.tsx

View workflow job for this annotation

GitHub Actions / lint

React Hook useEffect has missing dependencies: 'form', 'formDefinition', 'submissions.access', and 'submissions.submissionAccess'. Either include them or remove the dependency array

return {
options,
Expand Down
Loading
Loading