From 048dc1d1d944b5feace5a418e2cd67f93ce9c555 Mon Sep 17 00:00:00 2001 From: Anas WS Date: Mon, 18 Mar 2024 15:14:44 +0530 Subject: [PATCH 1/7] feat: better eslint rules --- .eslintignore | 15 ++++++- .eslintrc.js | 14 ++++++- app/utils/index.js | 3 +- app/utils/injectSaga.js | 52 +++++++++++------------- package.json | 1 + pages/_app.js | 38 ++++++++---------- pages/_document.js | 88 +++++++++++++++++++++-------------------- yarn.lock | 4 ++ 8 files changed, 117 insertions(+), 98 deletions(-) diff --git a/.eslintignore b/.eslintignore index 24c24a1..9053902 100644 --- a/.eslintignore +++ b/.eslintignore @@ -9,4 +9,17 @@ npm-debug.log .idea **/coverage/** **/storybook-static/** -**/server/** \ No newline at end of file +**/server/** +lighthouserc.js +lingui.config.js +__tests__ +internals/**/*.* +coverage/**/*.* +reports/**/*.* +badges/**/*.* +assets/**/*.* +**/tests/**/*.test.js +playwright.config.js +babel.config.js +app/translations/*.js +app/**/stories/**/*.* \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index 0c340bf..e3e0106 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -9,15 +9,25 @@ module.exports = { es2021: true, 'jest/globals': true }, + plugins: ['jest', 'immutable', 'prettier'], extends: ['eslint:recommended', 'prettier', 'plugin:import/recommended', 'next'], - plugins: ['prettier', 'jest'], rules: { 'prettier/prettier': ['error', prettierOptions], 'import/no-webpack-loader-syntax': 0, 'react/display-name': 0, 'react/react-in-jsx-scope': 'off', curly: ['error', 'all'], - 'no-console': ['error', { allow: ['error'] }] + 'no-console': ['error', { allow: ['error'] }], + 'max-lines': ['error', { max: 300, skipBlankLines: true, skipComments: true }], + 'max-lines-per-function': ['error', 250], + 'no-else-return': 'error', + 'max-params': ['error', 3], + 'no-shadow': 'error', + complexity: ['error', 5], + 'no-empty': 'error', + 'import/order': ['error', { groups: [['builtin', 'external', 'internal', 'parent', 'sibling', 'index']] }], + 'immutable/no-this': 2, + 'eslint-comments/no-use': 0 }, globals: { GLOBAL: false, diff --git a/app/utils/index.js b/app/utils/index.js index ca6520b..852c625 100644 --- a/app/utils/index.js +++ b/app/utils/index.js @@ -36,9 +36,8 @@ export const setDeviceType = (width = document.body.clientWidth) => { return 'mobile'; } else if (width >= screenSizes.tablet && width < screenSizes.desktop) { return 'tablet'; - } else { - return 'desktop'; } + return 'desktop'; }; export const getDeviceType = (device) => (device || setDeviceType()).toUpperCase(); diff --git a/app/utils/injectSaga.js b/app/utils/injectSaga.js index ba34014..cb5eecd 100644 --- a/app/utils/injectSaga.js +++ b/app/utils/injectSaga.js @@ -1,7 +1,6 @@ -import React from 'react'; +import React, { useContext, useEffect } from 'react'; import hoistNonReactStatics from 'hoist-non-react-statics'; import { ReactReduxContext } from 'react-redux'; - import getInjectors from './sagaInjectors'; /** @@ -16,39 +15,34 @@ import getInjectors from './sagaInjectors'; * - constants.ONCE_TILL_UNMOUNT — behaves like 'RESTART_ON_REMOUNT' but never runs it again. * */ -export default ({ key, saga, mode }) => +const withSaga = + ({ key, saga, mode }) => (WrappedComponent) => { - class InjectSaga extends React.Component { - static WrappedComponent = WrappedComponent; - - static contextType = ReactReduxContext; - - static displayName = `withSaga(${WrappedComponent.displayName || WrappedComponent.name || 'Component'})`; - - constructor(props, context) { - super(props, context); - - this.injectors = getInjectors(context.store); - - this.injectors.injectSaga(key, { saga, mode }, this.props); - } - - componentWillUnmount() { - this.injectors.ejectSaga(key); - } + const InjectSaga = (props) => { + const { store } = useContext(ReactReduxContext); + const injectors = getInjectors(store); + + useEffect(() => { + injectors.injectSaga(key, { saga, mode }, props); + return () => { + injectors.ejectSaga(key); + }; + }, []); + + return ; + }; - render() { - return ; - } - } + InjectSaga.WrappedComponent = WrappedComponent; + InjectSaga.displayName = `withSaga(${WrappedComponent.displayName || WrappedComponent.name || 'Component'})`; return hoistNonReactStatics(InjectSaga, WrappedComponent); }; const useInjectSaga = ({ key, saga, mode }) => { - const context = React.useContext(ReactReduxContext); - React.useEffect(() => { - const injectors = getInjectors(context.store); + const { store } = useContext(ReactReduxContext); + const injectors = getInjectors(store); + + useEffect(() => { injectors.injectSaga(key, { saga, mode }); return () => { injectors.ejectSaga(key); @@ -56,4 +50,4 @@ const useInjectSaga = ({ key, saga, mode }) => { }, []); }; -export { useInjectSaga }; +export { withSaga, useInjectSaga }; diff --git a/package.json b/package.json index cc1e74c..cd904b6 100644 --- a/package.json +++ b/package.json @@ -102,6 +102,7 @@ "eslint-config-standard": "17.0.0", "eslint-import-resolver-alias": "^1.1.2", "eslint-import-resolver-webpack": "0.13.2", + "eslint-plugin-immutable": "github:alichherawalla/eslint-plugin-immutable.git#6af48f5498ca1912b618c16bceab8c5464a92f1c", "eslint-plugin-import": "^2.26.0", "eslint-plugin-jest": "^26.4.5", "eslint-plugin-jsx-a11y": "^6.5.1", diff --git a/pages/_app.js b/pages/_app.js index a952d30..78698c3 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -1,5 +1,5 @@ +import React from 'react'; import { IntlProvider } from 'react-intl'; -import App from 'next/app'; import { ThemeProvider } from 'styled-components'; import colors from '@themes/colors'; import globalStyle from '@app/global-styles'; @@ -12,27 +12,23 @@ const theme = { colors }; -class MyApp extends App { - static getInitialProps = async ({ Component, ctx }) => { - return { - pageProps: { - ...(Component.getInitialProps ? await Component.getInitialProps(ctx) : {}), - pathname: ctx.pathname - } - }; - }; +const MyApp = ({ Component, pageProps }) => { + return ( + + + + + + + ); +}; - render() { - const { Component, pageProps } = this.props; - return ( - - - - - - - ); +MyApp.getInitialProps = async ({ Component, ctx }) => { + let pageProps = {}; + if (Component.getInitialProps) { + pageProps = await Component.getInitialProps(ctx); } -} + return { pageProps }; +}; export default wrapper.withRedux(MyApp); diff --git a/pages/_document.js b/pages/_document.js index c30311e..87b06b2 100644 --- a/pages/_document.js +++ b/pages/_document.js @@ -2,50 +2,52 @@ import Document, { Head, Html, Main, NextScript } from 'next/document'; import Script from 'next/script'; import { ServerStyleSheet } from 'styled-components'; -export default class MyDocument extends Document { - static async getInitialProps(ctx) { - const sheet = new ServerStyleSheet(); - const originalRenderPage = ctx.renderPage; - try { - ctx.renderPage = () => - originalRenderPage({ - enhanceApp: (App) => (props) => sheet.collectStyles() - }); +const MyDocument = ({ localeDataScript, locale, styles }) => { + // Polyfill Intl API for older browsers + const polyfill = `https://cdn.polyfill.io/v3/polyfill.min.js?features=Intl.~locale.${locale}`; - const initialProps = await Document.getInitialProps(ctx); - return { - ...initialProps, - styles: ( - <> - {initialProps.styles} - {sheet.getStyleElement()} - - ) - }; - } finally { - sheet.seal(); - } - } + return ( + + + +
+