diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index 920ad02..0000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,66 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -const config = { - extends: [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended-type-checked", - "plugin:@typescript-eslint/stylistic-type-checked", - "plugin:@tanstack/eslint-plugin-query/recommended", - "prettier", - "plugin:react/recommended", - "plugin:react-hooks/recommended", - "plugin:jsx-a11y/recommended", - "plugin:storybook/recommended", - ], - env: { - es2022: true, - node: true, - browser: true, - }, - parser: "@typescript-eslint/parser", - parserOptions: { - tsconfigRootDir: __dirname, - project: true, - }, - plugins: ["@typescript-eslint", "@tanstack/query", "import"], - rules: { - "react/prop-types": "off", - "@typescript-eslint/unbound-method": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - argsIgnorePattern: "^_", - varsIgnorePattern: "^_", - }, - ], - "@typescript-eslint/consistent-type-imports": [ - "warn", - { prefer: "type-imports", fixStyle: "separate-type-imports" }, - ], - "@typescript-eslint/no-misused-promises": [ - 2, - { checksVoidReturn: { attributes: false } }, - ], - "import/consistent-type-specifier-style": ["error", "prefer-top-level"], - "@tanstack/query/exhaustive-deps": "error", - "@tanstack/query/stable-query-client": "error", - }, - ignorePatterns: [ - "**/.eslintrc.cjs", - "**/*.config.js", - "**/*.config.cjs", - ".next", - "dist", - "pnpm-lock.yaml", - ], - reportUnusedDisableDirectives: true, - globals: { - React: "writable", - }, - settings: { - react: { - version: "detect", - }, - }, -}; - -module.exports = config; diff --git a/.github/workflows/set-pr-title.yml b/.github/workflows/set-pr-title.yml index ec610cb..04adef8 100644 --- a/.github/workflows/set-pr-title.yml +++ b/.github/workflows/set-pr-title.yml @@ -16,30 +16,34 @@ jobs: with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | - const { owner, repo, number: pull_number } = context.issue; - const pr = context.payload.pull_request; - const body = pr.body; - const branchName = pr.head.ref; - const [type, id, description] = branchName.split('/'); - const title = `[${type.toUpperCase()}][${id}] ${ description ? description?.split("-").join(' ') : null}`; + try { + const { owner, repo, number: pull_number } = context.issue; + const pr = context.payload.pull_request; + const body = pr.body; + const branchName = pr.head.ref; + const [type, id, description] = branchName.split('/'); + const title = `[${type.toUpperCase()}][${id}] ${ description ? description?.split("-").join(' ') : null}`; - const format = (str, ...args) => { - return str.replace(/{(\d+)}/g, (match, number) => { - return typeof args[number] !== 'undefined' ? args[number] : match; - }); - }; + const format = (str, ...args) => { + return str.replace(/{(\d+)}/g, (match, number) => { + return typeof args[number] !== 'undefined' ? args[number] : match; + }); + }; - const templateTitle = description.split("-").join(' ').replace(/\b\w/g, function(l){ return l.toUpperCase() }); - const taskCode = id.split("CU-").join(''); - const isFeature = type === 'feature' ? 'x' : ' '; - const isBugfix = ["bugfix", "hotfix"].includes(type) ? 'x' : ' '; + const templateTitle = description.split("-").join(' ').replace(/\b\w/g, function(l){ return l.toUpperCase() }); + const taskCode = id.split("CU-").join(''); + const isFeature = type === 'feature' ? 'x' : ' '; + const isBugfix = ["bugfix", "hotfix"].includes(type) ? 'x' : ' '; - const updatedBody = format(body, templateTitle, id, taskCode, isFeature, isBugfix); + const updatedBody = format(body, templateTitle, id, taskCode, isFeature, isBugfix); - await github.rest.pulls.update({ - owner, - repo, - pull_number, - title, - body: updatedBody - }); + await github.rest.pulls.update({ + owner, + repo, + pull_number, + title, + body: updatedBody + }); + } catch (error) { + console.log("Error setting PR title: ", error); + } diff --git a/.nvmrc b/.nvmrc index 7ec5619..f3f52b4 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -18.17.1 \ No newline at end of file +20.9.0 diff --git a/.vscode/settings.json b/.vscode/settings.json index 175f9e4..9b8445c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,8 @@ { "editor.codeActionsOnSave": { - "source.fixAll.eslint": "explicit" + "source.fixAll.eslint": true }, + "eslint.validate": ["javascript"], "editor.formatOnType": false, "editor.formatOnPaste": true, "editor.formatOnSave": true, diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..46f8177 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,12 @@ +import pluginJs from "@eslint/js"; +import pluginReact from "eslint-plugin-react"; +import globals from "globals"; +import tseslint from "typescript-eslint"; + +export default [ + { files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"] }, + { languageOptions: { globals: globals.browser } }, + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + pluginReact.configs.flat.recommended, +]; diff --git a/package.json b/package.json index 0057775..6a317eb 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "fe-boilerplate", "private": true, "engines": { - "node": ">=v18.17.1" + "node": ">=v20.9.0" }, "packageManager": "pnpm@8.7.4", "version": "0.0.1", @@ -50,6 +50,7 @@ "zustand": "^4.5.2" }, "devDependencies": { + "@eslint/js": "^9.8.0", "@ianvs/prettier-plugin-sort-imports": "^4.1.1", "@storybook/addon-a11y": "^7.6.17", "@storybook/addon-actions": "^7.6.17", @@ -67,8 +68,6 @@ "@storybook/theming": "^7.6.17", "@tailwindcss/forms": "^0.5.7", "@tailwindcss/typography": "^0.5.10", - "@tanstack/eslint-plugin-query": "^5.20.1", - "@types/eslint": "^8.56.5", "@types/node": "^20.11.25", "@types/react": "^18.2.64", "@types/react-dom": "^18.2.21", @@ -76,20 +75,13 @@ "@types/react-transition-group": "^4.4.10", "@types/uuid": "^9.0.8", "@types/yargs": "^17.0.32", - "@typescript-eslint/eslint-plugin": "^7.1.1", - "@typescript-eslint/parser": "^7.1.1", "@vitejs/plugin-react": "^4.2.1", "@vitejs/plugin-react-swc": "^3.6.0", "autoprefixer": "^10.4.18", "dotenv-cli": "^7.4.0", - "eslint": "^8.57.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsx-a11y": "^6.8.0", - "eslint-plugin-react": "^7.34.0", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.4.5", - "eslint-plugin-storybook": "^0.8.0", + "eslint": "^9.8", + "eslint-plugin-react": "^7.35.0", + "globals": "^15.8.0", "husky": "^9.0.11", "lint-staged": "^15.2.2", "plop": "^4.0.1", @@ -100,6 +92,7 @@ "storybook": "^7.6.17", "ts-node": "^10.9.2", "typescript": "^5.4.2", + "typescript-eslint": "^7.17.0", "vite": "^5.1.7", "yargs": "^17.7.2" }, @@ -113,8 +106,7 @@ }, "lint-staged": { "src/**/*.{js,jsx,ts,tsx}": [ - "pretty-quick --staged", - "eslint --fix" + "pretty-quick --staged" ] } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 99cdd2b..31d2468 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -219,6 +219,9 @@ devDependencies: typescript: specifier: ^5.4.2 version: 5.4.5 + typescript-eslint: + specifier: ^7.17.0 + version: 7.17.0(eslint@9.8.0)(typescript@5.4.5) vite: specifier: ^5.1.7 version: 5.2.11(@types/node@20.12.12)(less@4.2.0) @@ -2751,7 +2754,7 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.57.0 + eslint: 9.8.0 eslint-visitor-keys: 3.4.3 dev: true @@ -2772,8 +2775,8 @@ packages: dependencies: ajv: 6.12.6 debug: 4.3.4 - espree: 9.6.1 - globals: 13.24.0 + espree: 10.1.0 + globals: 14.0.0 ignore: 5.3.1 import-fresh: 3.3.0 js-yaml: 4.1.0 @@ -6796,7 +6799,7 @@ packages: "@typescript-eslint/typescript-estree": 7.17.0(typescript@5.4.5) "@typescript-eslint/visitor-keys": 7.17.0 debug: 4.3.4 - eslint: 8.57.0 + eslint: 9.8.0 typescript: 5.4.5 transitivePeerDependencies: - supports-color @@ -6851,7 +6854,7 @@ packages: "@typescript-eslint/typescript-estree": 7.17.0(typescript@5.4.5) "@typescript-eslint/utils": 7.17.0(eslint@8.57.0)(typescript@5.4.5) debug: 4.3.4 - eslint: 8.57.0 + eslint: 9.8.0 ts-api-utils: 1.3.0(typescript@5.4.5) typescript: 5.4.5 transitivePeerDependencies: @@ -8855,6 +8858,7 @@ packages: dependencies: ms: 2.1.3 dev: true + optional: true /debug@4.3.4: resolution: @@ -9693,7 +9697,7 @@ packages: array.prototype.findlastindex: 1.2.5 array.prototype.flat: 1.3.2 array.prototype.flatmap: 1.3.2 - debug: 3.2.7 + array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 @@ -9863,7 +9867,6 @@ packages: chalk: 4.1.2 cross-spawn: 7.0.3 debug: 4.3.4 - doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 eslint-visitor-keys: 3.4.3 @@ -9871,16 +9874,13 @@ packages: esquery: 1.6.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 + file-entry-cache: 8.0.0 find-up: 5.0.0 glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 ignore: 5.3.1 imurmurhash: 0.1.4 is-glob: 4.0.3 is-path-inside: 3.0.3 - js-yaml: 4.1.0 json-stable-stringify-without-jsonify: 1.0.1 levn: 0.4.1 lodash.merge: 4.6.2 @@ -10184,7 +10184,7 @@ packages: } engines: { node: ^10.12.0 || >=12.0.0 } dependencies: - flat-cache: 3.2.0 + flat-cache: 4.0.1 dev: true /file-system-cache@2.3.0: @@ -10332,7 +10332,6 @@ packages: dependencies: flatted: 3.3.1 keyv: 4.5.4 - rimraf: 3.0.2 dev: true /flatted@3.3.1: @@ -17090,7 +17089,3 @@ packages: react: 18.3.1 use-sync-external-store: 1.2.0(react@18.3.1) dev: false - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false diff --git a/prettier.config.mjs b/prettier.config.mjs index 0a4539f..64b501d 100644 --- a/prettier.config.mjs +++ b/prettier.config.mjs @@ -7,7 +7,7 @@ const config = { arrowParens: "always", printWidth: 80, singleQuote: false, - jsxSingleQuote: false, + jsxSingleQuote: true, semi: true, trailingComma: "all", tabWidth: 2, diff --git a/src/env.ts b/src/env.ts index eb1e000..f894693 100644 --- a/src/env.ts +++ b/src/env.ts @@ -15,14 +15,13 @@ type EnvValues = z.infer; // IDEA: trigger a toast message on dev instead of just a console error function logEnvError(errors: ZodError) { - const { _errors, ...formattedErrors } = errors.format(); + const { ...formattedErrors } = errors.format(); console.error("<"); console.error("ENVIRONMENT VARIABLES ERRORS:"); console.error("----"); - Object.entries(formattedErrors).forEach(([name, { _errors }]) => { - const errMsg = _errors.join(", "); - console.error(`"${name}": ${errMsg}`); + Object.entries(formattedErrors).forEach(([name]) => { + console.error(name); }); console.error("----"); console.error(">"); diff --git a/src/main.tsx b/src/main.tsx index d50f87a..8fe6b1b 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,4 +1,4 @@ -import { StrictMode } from "react"; +import React, { StrictMode } from "react"; // import * as Sentry from "@sentry/react"; import { QueryCache, diff --git a/src/router/router.tsx b/src/router/router.tsx index f1d8b17..c3cf78d 100644 --- a/src/router/router.tsx +++ b/src/router/router.tsx @@ -1,3 +1,4 @@ +import React from "react"; import { Navigate, Route, Routes, useLocation } from "react-router-dom"; import type { Location } from "react-router-dom"; @@ -35,7 +36,7 @@ export const Router = () => { }> } path={ROUTES.home} /> - } /> + } /> )} diff --git a/src/router/useNavigateModal.ts b/src/router/useNavigateModal.ts index 87611ec..16394ef 100644 --- a/src/router/useNavigateModal.ts +++ b/src/router/useNavigateModal.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ import type { NavigateOptions } from "react-router-dom"; import { useLocation, useNavigate } from "react-router-dom"; @@ -29,7 +30,7 @@ export const useNavigateModal = () => { ) => { navigate(to, { ...options, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + state: { ...options?.state, previousLocation: previousLocation ?? location, diff --git a/src/screens/ErrorBoundaryFallback.tsx b/src/screens/ErrorBoundaryFallback.tsx index 1f4a7e6..bb8c4a9 100644 --- a/src/screens/ErrorBoundaryFallback.tsx +++ b/src/screens/ErrorBoundaryFallback.tsx @@ -4,11 +4,11 @@ import { LightitLogo } from "~/assets"; export const ErrorBoundaryFallback = () => { return ( -
-
- logo +
+
+ logo
-

Something went terribly wrong!

+

Something went terribly wrong!

); }; diff --git a/src/screens/Login.tsx b/src/screens/Login.tsx index c8b97dc..be4c502 100644 --- a/src/screens/Login.tsx +++ b/src/screens/Login.tsx @@ -4,12 +4,12 @@ import { LightitLogo } from "~/assets"; export const Login = () => { return ( -
-
- Lightit logo +
+
+ Lightit logo -
-

+

+

Frontend Boilerplate Login!

diff --git a/src/shared/components/ui/Button/Button.stories.tsx b/src/shared/components/ui/Button/Button.stories.tsx index 67d3434..52493a4 100644 --- a/src/shared/components/ui/Button/Button.stories.tsx +++ b/src/shared/components/ui/Button/Button.stories.tsx @@ -1,3 +1,4 @@ +import React from "react"; import type { Meta, StoryObj } from "@storybook/react"; import { Button } from "./Button";