From 3fb7b37d75525fdef53bfd1fe58ad1bce1b74152 Mon Sep 17 00:00:00 2001 From: Marco Pasqualetti <24919330+marcalexiei@users.noreply.github.com> Date: Mon, 9 Feb 2026 09:15:46 +0100 Subject: [PATCH] refactor: add `eslint-plugin-import-x` (#65) - related to #29 --- .github/workflows/ci.yml | 12 +- .vscode/settings.json | 3 +- .../output/functions/api.func/router.js | 15 +-- apps/backend/api-renamed/delete-user.js | 2 +- apps/backend/api-renamed/downgrade.js | 3 +- apps/backend/api-renamed/gist.js | 10 +- apps/backend/api-renamed/index.js | 2 +- apps/backend/api-renamed/pin.js | 5 +- apps/backend/api-renamed/status/up.js | 2 +- apps/backend/api-renamed/top-langs.js | 2 +- apps/backend/api-renamed/user-access.js | 2 +- apps/backend/api-renamed/wakatime-proxy.js | 2 +- apps/backend/api-renamed/wakatime.js | 10 +- apps/backend/express.js | 5 +- apps/backend/scripts/close-stale-theme-prs.js | 10 +- apps/backend/scripts/generate-langs-json.js | 5 +- apps/backend/scripts/generate-theme-doc.js | 1 + apps/backend/scripts/preview-theme.js | 15 ++- apps/backend/src/cards/gist.js | 14 +-- apps/backend/src/cards/repo.js | 12 +- apps/backend/src/cards/stats.js | 5 +- apps/backend/src/cards/top-languages.js | 2 +- apps/backend/src/cards/wakatime.js | 4 +- apps/backend/src/common/access.js | 4 +- apps/backend/src/common/database.js | 1 + apps/backend/src/common/fmt.js | 1 + apps/backend/src/common/ops.js | 1 + apps/backend/src/common/render.js | 2 +- apps/backend/src/common/retryer.js | 2 +- apps/backend/src/fetchers/gist.js | 2 +- apps/backend/src/fetchers/repo.js | 1 + apps/backend/src/fetchers/stats.js | 7 +- apps/backend/src/fetchers/top-languages.js | 6 +- apps/backend/src/fetchers/wakatime.js | 1 + apps/backend/src/repeatRequests.js | 3 +- apps/backend/src/users.js | 1 + apps/backend/tests/api.test.js | 3 +- apps/backend/tests/bench/api.bench.js | 6 +- .../tests/bench/calculateRank.bench.js | 4 +- apps/backend/tests/bench/gist.bench.js | 6 +- apps/backend/tests/bench/pin.bench.js | 6 +- apps/backend/tests/calculateRank.test.js | 2 + apps/backend/tests/card.test.js | 3 +- apps/backend/tests/color.test.js | 3 +- apps/backend/tests/e2e/e2e.test.js | 6 +- apps/backend/tests/fetchGist.test.js | 1 + apps/backend/tests/fetchRepo.test.js | 1 + apps/backend/tests/fetchStats.test.js | 1 + apps/backend/tests/fetchTopLanguages.test.js | 2 + apps/backend/tests/fetchWakatime.test.js | 1 + apps/backend/tests/flexLayout.test.js | 1 + apps/backend/tests/fmt.test.js | 1 + apps/backend/tests/gist.test.js | 3 +- apps/backend/tests/html.test.js | 1 + apps/backend/tests/i18n.test.js | 1 + apps/backend/tests/ops.test.js | 11 +- apps/backend/tests/pat-info.test.js | 7 +- apps/backend/tests/pin.test.js | 3 +- apps/backend/tests/render.test.js | 1 + apps/backend/tests/renderGistCard.test.js | 1 + apps/backend/tests/renderRepoCard.test.js | 1 + apps/backend/tests/renderStatsCard.test.js | 1 + .../tests/renderTopLanguagesCard.test.js | 3 +- apps/backend/tests/renderWakatimeCard.test.js | 5 +- apps/backend/tests/retryer.test.js | 3 +- apps/backend/tests/setup.jest.js | 2 +- apps/backend/tests/status.up.test.js | 1 + apps/backend/tests/top-langs.test.js | 3 +- apps/backend/tests/wakatime.test.js | 1 + apps/frontend/e2e/app.spec.ts | 2 +- apps/frontend/index.html | 2 +- apps/frontend/src/axios-override.ts | 2 +- apps/frontend/src/components/Card/Card.tsx | 2 +- .../src/components/Card/CardImage.tsx | 2 +- .../src/components/Card/SvgInline.tsx | 6 +- .../src/components/Generic/Button.tsx | 2 +- .../src/components/Generic/Select.tsx | 2 +- .../src/components/Home/CheckboxSection.tsx | 6 +- .../Home/LanguagesLayoutSection.tsx | 3 +- .../frontend/src/components/Home/Progress.tsx | 3 +- apps/frontend/src/components/Home/Section.tsx | 1 - .../src/components/Home/TextSection.tsx | 2 +- .../components/Home/WakatimeLayoutSection.tsx | 3 +- apps/frontend/src/{index.jsx => index.tsx} | 7 +- apps/frontend/src/pages/App/AppTrends.tsx | 19 ++-- apps/frontend/src/pages/App/Header.tsx | 2 +- apps/frontend/src/pages/Home/Home.tsx | 30 ++--- .../src/pages/Home/stages/Customize.tsx | 13 +-- .../src/pages/Home/stages/Display.tsx | 15 +-- .../src/pages/Home/stages/Login/Login.tsx | 2 +- .../stages/Login/LoginAccountDeleteModal.tsx | 3 +- .../stages/Login/LoginAccountManagement.tsx | 21 ++-- .../src/pages/Home/stages/Login/LoginBox.tsx | 2 +- .../Home/stages/Login/LoginBoxDemoCards.tsx | 2 +- .../pages/Home/stages/Login/LoginOptions.tsx | 2 +- .../src/pages/Home/stages/SelectCard.tsx | 6 +- apps/frontend/src/pages/Home/stages/Theme.tsx | 2 +- apps/frontend/src/wakatime-override.ts | 1 + apps/frontend/vite.config.ts | 3 +- eslint.config.js | 37 +++++- knip.jsonc | 2 +- package.json | 2 + pnpm-lock.yaml | 105 ++++++++++++++++++ 103 files changed, 394 insertions(+), 190 deletions(-) rename apps/frontend/src/{index.jsx => index.tsx} (68%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab8c8272..bfa3ec69 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -97,15 +97,19 @@ jobs: - name: Checkout code uses: actions/checkout@v6 - - name: Install Dependencies - uses: ./.github/actions/install-dependencies - - # needed to resolve .vercel folder from apps/frontend/src/components/Card/SVG.js + # Heads up! + # + # 1. Execution of this script is needed to resolve `.vercel` folder from `apps/frontend/src/components/Card/SVG.js` + # 2. This scripts removes `apps/backend/node_modules` breaking ESLint’s module resolution. + # Dependency installation must occur after running ./vercel-preparation.sh. - name: Run vercel-preparation.sh run: | chmod +x ./vercel-preparation.sh ./vercel-preparation.sh + - name: Install Dependencies + uses: ./.github/actions/install-dependencies + - name: Format run: pnpm run format:check diff --git a/.vscode/settings.json b/.vscode/settings.json index 52099c7f..fe8961d3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,7 +3,8 @@ "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode", "[javascript]": { - "editor.tabSize": 2 + "editor.tabSize": 2, + "editor.defaultFormatter": "esbenp.prettier-vscode" }, "cSpell.words": ["Wakatime"] } diff --git a/apps/backend/_dot_vercel_copy/output/functions/api.func/router.js b/apps/backend/_dot_vercel_copy/output/functions/api.func/router.js index 352bb707..b9a98e1e 100644 --- a/apps/backend/_dot_vercel_copy/output/functions/api.func/router.js +++ b/apps/backend/_dot_vercel_copy/output/functions/api.func/router.js @@ -1,16 +1,17 @@ -import { default as api } from "./api-renamed/index.js"; +/* eslint-disable import-x/no-unresolved */ +import { default as authenticate } from "./api-renamed/authenticate.js"; +import { default as deleteUser } from "./api-renamed/delete-user.js"; +import { default as downgrade } from "./api-renamed/downgrade.js"; import { default as gist } from "./api-renamed/gist.js"; +import { default as api } from "./api-renamed/index.js"; import { default as pin } from "./api-renamed/pin.js"; -import { default as topLangs } from "./api-renamed/top-langs.js"; -import { default as wakatime } from "./api-renamed/wakatime.js"; -import { default as wakatimeProxy } from "./api-renamed/wakatime-proxy.js"; import { default as repeatRecent } from "./api-renamed/repeat-recent.js"; import { default as patInfo } from "./api-renamed/status/pat-info.js"; import { default as statusUp } from "./api-renamed/status/up.js"; -import { default as authenticate } from "./api-renamed/authenticate.js"; -import { default as deleteUser } from "./api-renamed/delete-user.js"; +import { default as topLangs } from "./api-renamed/top-langs.js"; import { default as userAccess } from "./api-renamed/user-access.js"; -import { default as downgrade } from "./api-renamed/downgrade.js"; +import { default as wakatimeProxy } from "./api-renamed/wakatime-proxy.js"; +import { default as wakatime } from "./api-renamed/wakatime.js"; export default async (req, res) => { // remaining code expects express.js-like request and response objects diff --git a/apps/backend/api-renamed/delete-user.js b/apps/backend/api-renamed/delete-user.js index 25e991ad..83c073e9 100644 --- a/apps/backend/api-renamed/delete-user.js +++ b/apps/backend/api-renamed/delete-user.js @@ -1,5 +1,5 @@ -import { logger } from "../src/common/log.js"; import { deleteUser } from "../src/common/database.js"; +import { logger } from "../src/common/log.js"; /** * @param {any} req The request. diff --git a/apps/backend/api-renamed/downgrade.js b/apps/backend/api-renamed/downgrade.js index c4714a37..519d3f9f 100644 --- a/apps/backend/api-renamed/downgrade.js +++ b/apps/backend/api-renamed/downgrade.js @@ -1,5 +1,6 @@ -import { getUserAccessByKey, deleteUser } from "../src/common/database.js"; import axios from "axios"; + +import { deleteUser, getUserAccessByKey } from "../src/common/database.js"; import { logger } from "../src/common/log.js"; export default async (req, res) => { diff --git a/apps/backend/api-renamed/gist.js b/apps/backend/api-renamed/gist.js index e050a5ce..26e973ee 100644 --- a/apps/backend/api-renamed/gist.js +++ b/apps/backend/api-renamed/gist.js @@ -1,22 +1,22 @@ // @ts-check -import { renderError } from "../src/common/render.js"; -import { isLocaleAvailable } from "../src/translations.js"; import { renderGistCard } from "../src/cards/gist.js"; -import { fetchGist } from "../src/fetchers/gist.js"; -import { storeRequest } from "../src/common/database.js"; +import { guardAccess } from "../src/common/access.js"; import { CACHE_TTL, resolveCacheSeconds, setCacheHeaders, setErrorCacheHeaders, } from "../src/common/cache.js"; -import { guardAccess } from "../src/common/access.js"; +import { storeRequest } from "../src/common/database.js"; import { MissingParamError, retrieveSecondaryMessage, } from "../src/common/error.js"; import { parseBoolean } from "../src/common/ops.js"; +import { renderError } from "../src/common/render.js"; +import { fetchGist } from "../src/fetchers/gist.js"; +import { isLocaleAvailable } from "../src/translations.js"; // @ts-ignore export default async (req, res) => { diff --git a/apps/backend/api-renamed/index.js b/apps/backend/api-renamed/index.js index 3f68ef85..55ac2e72 100644 --- a/apps/backend/api-renamed/index.js +++ b/apps/backend/api-renamed/index.js @@ -8,6 +8,7 @@ import { setCacheHeaders, setErrorCacheHeaders, } from "../src/common/cache.js"; +import { storeRequest } from "../src/common/database.js"; import { MissingParamError, retrieveSecondaryMessage, @@ -16,7 +17,6 @@ import { parseArray, parseBoolean } from "../src/common/ops.js"; import { renderError } from "../src/common/render.js"; import { fetchStats } from "../src/fetchers/stats.js"; import { isLocaleAvailable } from "../src/translations.js"; -import { storeRequest } from "../src/common/database.js"; // @ts-ignore export default async (req, res) => { diff --git a/apps/backend/api-renamed/pin.js b/apps/backend/api-renamed/pin.js index e34a4b9a..b79a74f6 100644 --- a/apps/backend/api-renamed/pin.js +++ b/apps/backend/api-renamed/pin.js @@ -8,16 +8,15 @@ import { setCacheHeaders, setErrorCacheHeaders, } from "../src/common/cache.js"; +import { storeRequest } from "../src/common/database.js"; import { MissingParamError, retrieveSecondaryMessage, } from "../src/common/error.js"; -import { parseBoolean } from "../src/common/ops.js"; -import { parseArray } from "../src/common/ops.js"; +import { parseArray, parseBoolean } from "../src/common/ops.js"; import { renderError } from "../src/common/render.js"; import { fetchRepo } from "../src/fetchers/repo.js"; import { isLocaleAvailable } from "../src/translations.js"; -import { storeRequest } from "../src/common/database.js"; // @ts-ignore export default async (req, res) => { diff --git a/apps/backend/api-renamed/status/up.js b/apps/backend/api-renamed/status/up.js index 05b5e263..3afe5853 100644 --- a/apps/backend/api-renamed/status/up.js +++ b/apps/backend/api-renamed/status/up.js @@ -8,8 +8,8 @@ */ import { request } from "../../src/common/http.js"; -import retryer from "../../src/common/retryer.js"; import { logger } from "../../src/common/log.js"; +import { default as retryer } from "../../src/common/retryer.js"; export const RATE_LIMIT_SECONDS = 60 * 3; // 1 request per 3 minutes diff --git a/apps/backend/api-renamed/top-langs.js b/apps/backend/api-renamed/top-langs.js index 8f0f588d..056193c8 100644 --- a/apps/backend/api-renamed/top-langs.js +++ b/apps/backend/api-renamed/top-langs.js @@ -8,6 +8,7 @@ import { setCacheHeaders, setErrorCacheHeaders, } from "../src/common/cache.js"; +import { storeRequest } from "../src/common/database.js"; import { MissingParamError, retrieveSecondaryMessage, @@ -16,7 +17,6 @@ import { parseArray, parseBoolean } from "../src/common/ops.js"; import { renderError } from "../src/common/render.js"; import { fetchTopLanguages } from "../src/fetchers/top-languages.js"; import { isLocaleAvailable } from "../src/translations.js"; -import { storeRequest } from "../src/common/database.js"; // @ts-ignore export default async (req, res) => { diff --git a/apps/backend/api-renamed/user-access.js b/apps/backend/api-renamed/user-access.js index 4fde6aa0..218ceac0 100644 --- a/apps/backend/api-renamed/user-access.js +++ b/apps/backend/api-renamed/user-access.js @@ -1,5 +1,5 @@ -import { logger } from "../src/common/log.js"; import { getUserAccessByKey } from "../src/common/database.js"; +import { logger } from "../src/common/log.js"; /** * @param {any} req The request. diff --git a/apps/backend/api-renamed/wakatime-proxy.js b/apps/backend/api-renamed/wakatime-proxy.js index 77dca8ba..34dc4611 100644 --- a/apps/backend/api-renamed/wakatime-proxy.js +++ b/apps/backend/api-renamed/wakatime-proxy.js @@ -1,5 +1,5 @@ -import { fetchWakatimeStats } from "../src/fetchers/wakatime.js"; import { logger } from "../src/common/log.js"; +import { fetchWakatimeStats } from "../src/fetchers/wakatime.js"; /** * @param {any} req The request. diff --git a/apps/backend/api-renamed/wakatime.js b/apps/backend/api-renamed/wakatime.js index 42938f86..dd1c3ead 100644 --- a/apps/backend/api-renamed/wakatime.js +++ b/apps/backend/api-renamed/wakatime.js @@ -1,22 +1,22 @@ // @ts-check import { renderWakatimeCard } from "../src/cards/wakatime.js"; -import { renderError } from "../src/common/render.js"; -import { fetchWakatimeStats } from "../src/fetchers/wakatime.js"; -import { isLocaleAvailable } from "../src/translations.js"; -import { storeRequest } from "../src/common/database.js"; +import { guardAccess } from "../src/common/access.js"; import { CACHE_TTL, resolveCacheSeconds, setCacheHeaders, setErrorCacheHeaders, } from "../src/common/cache.js"; -import { guardAccess } from "../src/common/access.js"; +import { storeRequest } from "../src/common/database.js"; import { MissingParamError, retrieveSecondaryMessage, } from "../src/common/error.js"; import { parseArray, parseBoolean } from "../src/common/ops.js"; +import { renderError } from "../src/common/render.js"; +import { fetchWakatimeStats } from "../src/fetchers/wakatime.js"; +import { isLocaleAvailable } from "../src/translations.js"; // @ts-ignore export default async (req, res) => { diff --git a/apps/backend/express.js b/apps/backend/express.js index 9948221a..0e020275 100644 --- a/apps/backend/express.js +++ b/apps/backend/express.js @@ -1,10 +1,11 @@ import "dotenv/config"; +import express from "express"; + +import gistCard from "./api-renamed/gist.js"; import statsCard from "./api-renamed/index.js"; import repoCard from "./api-renamed/pin.js"; import langCard from "./api-renamed/top-langs.js"; import wakatimeCard from "./api-renamed/wakatime.js"; -import gistCard from "./api-renamed/gist.js"; -import express from "express"; const app = express(); const router = express.Router(); diff --git a/apps/backend/scripts/close-stale-theme-prs.js b/apps/backend/scripts/close-stale-theme-prs.js index 4f2c936d..26b374f4 100644 --- a/apps/backend/scripts/close-stale-theme-prs.js +++ b/apps/backend/scripts/close-stale-theme-prs.js @@ -1,14 +1,16 @@ /** * @file Script that can be used to close stale theme PRs that have a `invalid` label. */ -import * as dotenv from "dotenv"; -dotenv.config(); - import { debug, setFailed } from "@actions/core"; -import github from "@actions/github"; +import * as github from "@actions/github"; +// eslint-disable-next-line import-x/no-unresolved import { RequestError } from "@octokit/request-error"; +import * as dotenv from "dotenv"; + import { getGithubToken, getRepoInfo } from "./helpers.js"; +dotenv.config(); + const CLOSING_COMMENT = ` \rThis theme PR has been automatically closed due to inactivity. Please reopen it if you want to continue working on it.\ \rThank you for your contributions. diff --git a/apps/backend/scripts/generate-langs-json.js b/apps/backend/scripts/generate-langs-json.js index 803d60b1..dbf12642 100644 --- a/apps/backend/scripts/generate-langs-json.js +++ b/apps/backend/scripts/generate-langs-json.js @@ -1,6 +1,7 @@ -import axios from "axios"; import fs from "fs"; -import jsYaml from "js-yaml"; + +import axios from "axios"; +import { default as jsYaml } from "js-yaml"; const LANGS_FILEPATH = "./src/common/languageColors.json"; diff --git a/apps/backend/scripts/generate-theme-doc.js b/apps/backend/scripts/generate-theme-doc.js index d3d1993e..93c8e6a7 100644 --- a/apps/backend/scripts/generate-theme-doc.js +++ b/apps/backend/scripts/generate-theme-doc.js @@ -1,4 +1,5 @@ import fs from "fs"; + import { themes } from "../themes/index.js"; const TARGET_FILE = "./themes/README.md"; diff --git a/apps/backend/scripts/preview-theme.js b/apps/backend/scripts/preview-theme.js index 012efd84..f4d71567 100644 --- a/apps/backend/scripts/preview-theme.js +++ b/apps/backend/scripts/preview-theme.js @@ -1,21 +1,24 @@ /** * @file This script is used to preview the theme on theme PRs. */ -import * as dotenv from "dotenv"; -dotenv.config(); +import { info } from "console"; +import { inspect } from "util"; import { debug, setFailed } from "@actions/core"; -import github from "@actions/github"; +import { default as github } from "@actions/github"; import ColorContrastChecker from "color-contrast-checker"; -import { info } from "console"; +import * as dotenv from "dotenv"; import Hjson from "hjson"; import snakeCase from "lodash.snakecase"; import parse from "parse-diff"; -import { inspect } from "util"; -import { isValidHexColor, isValidGradient } from "../src/common/color.js"; + +import { isValidGradient, isValidHexColor } from "../src/common/color.js"; import { themes } from "../themes/index.js"; + import { getGithubToken, getRepoInfo } from "./helpers.js"; +dotenv.config(); + const COMMENTER = "github-actions[bot]"; const COMMENT_TITLE = "Automated Theme Preview"; diff --git a/apps/backend/src/cards/gist.js b/apps/backend/src/cards/gist.js index b71c44f9..b630dad8 100644 --- a/apps/backend/src/cards/gist.js +++ b/apps/backend/src/cards/gist.js @@ -1,18 +1,18 @@ // @ts-check -import { - measureText, - flexLayout, - iconWithLabel, - createLanguageNode, -} from "../common/render.js"; -import Card from "../common/Card.js"; +import { default as Card } from "../common/Card.js"; import { getCardColors } from "../common/color.js"; import { kFormatter, wrapTextMultiline } from "../common/fmt.js"; import { encodeHTML } from "../common/html.js"; import { icons } from "../common/icons.js"; import languageColors from "../common/languageColors.json" with { type: "json" }; import { parseEmojis } from "../common/ops.js"; +import { + createLanguageNode, + flexLayout, + iconWithLabel, + measureText, +} from "../common/render.js"; const ICON_SIZE = 16; const CARD_DEFAULT_WIDTH = 400; diff --git a/apps/backend/src/cards/repo.js b/apps/backend/src/cards/repo.js index fbbbdf36..6b1afb50 100644 --- a/apps/backend/src/cards/repo.js +++ b/apps/backend/src/cards/repo.js @@ -1,20 +1,20 @@ // @ts-check import { Card } from "../common/Card.js"; +import { I18n } from "../common/I18n.js"; import { getCardColors } from "../common/color.js"; import { kFormatter, wrapTextMultiline } from "../common/fmt.js"; import { encodeHTML } from "../common/html.js"; -import { I18n } from "../common/I18n.js"; import { icons } from "../common/icons.js"; -import { clampValue, parseEmojis } from "../common/ops.js"; -import { buildSearchFilter } from "../common/ops.js"; +import { buildSearchFilter, clampValue, parseEmojis } from "../common/ops.js"; import { - flexLayout, - measureText, - iconWithLabel, createLanguageNode, + flexLayout, + iconWithLabel, + measureText, } from "../common/render.js"; import { repoCardLocales } from "../translations.js"; + import { createTextNode } from "./stats.js"; const ICON_SIZE = 16; diff --git a/apps/backend/src/cards/stats.js b/apps/backend/src/cards/stats.js index f3063ac1..09aef286 100644 --- a/apps/backend/src/cards/stats.js +++ b/apps/backend/src/cards/stats.js @@ -1,13 +1,12 @@ // @ts-check import { Card } from "../common/Card.js"; +import { I18n } from "../common/I18n.js"; import { getCardColors } from "../common/color.js"; import { CustomError } from "../common/error.js"; import { kFormatter } from "../common/fmt.js"; -import { I18n } from "../common/I18n.js"; import { icons, rankIcon } from "../common/icons.js"; -import { clampValue } from "../common/ops.js"; -import { buildSearchFilter } from "../common/ops.js"; +import { buildSearchFilter, clampValue } from "../common/ops.js"; import { flexLayout, measureText } from "../common/render.js"; import { statCardLocales, wakatimeCardLocales } from "../translations.js"; diff --git a/apps/backend/src/cards/top-languages.js b/apps/backend/src/cards/top-languages.js index 64c11448..8955d653 100644 --- a/apps/backend/src/cards/top-languages.js +++ b/apps/backend/src/cards/top-languages.js @@ -1,9 +1,9 @@ // @ts-check import { Card } from "../common/Card.js"; +import { I18n } from "../common/I18n.js"; import { getCardColors } from "../common/color.js"; import { formatBytes } from "../common/fmt.js"; -import { I18n } from "../common/I18n.js"; import { chunkArray, clampValue, lowercaseTrim } from "../common/ops.js"; import { createProgressNode, diff --git a/apps/backend/src/cards/wakatime.js b/apps/backend/src/cards/wakatime.js index 2012f9c2..02eac539 100644 --- a/apps/backend/src/cards/wakatime.js +++ b/apps/backend/src/cards/wakatime.js @@ -1,12 +1,12 @@ // @ts-check import { Card } from "../common/Card.js"; -import { getCardColors } from "../common/color.js"; import { I18n } from "../common/I18n.js"; +import { getCardColors } from "../common/color.js"; +import languageColors from "../common/languageColors.json" with { type: "json" }; import { clampValue, lowercaseTrim } from "../common/ops.js"; import { createProgressNode, flexLayout } from "../common/render.js"; import { wakatimeCardLocales } from "../translations.js"; -import languageColors from "../common/languageColors.json" with { type: "json" }; const DEFAULT_CARD_WIDTH = 495; const MIN_CARD_WIDTH = 250; diff --git a/apps/backend/src/common/access.js b/apps/backend/src/common/access.js index 25777356..05a5dbe5 100644 --- a/apps/backend/src/common/access.js +++ b/apps/backend/src/common/access.js @@ -1,8 +1,8 @@ // @ts-check -import { renderError } from "./render.js"; import { blacklist } from "./blacklist.js"; -import { whitelist, gistWhitelist } from "./envs.js"; +import { gistWhitelist, whitelist } from "./envs.js"; +import { renderError } from "./render.js"; const NOT_WHITELISTED_USERNAME_MESSAGE = "This username is not whitelisted"; const NOT_WHITELISTED_GIST_MESSAGE = "This gist ID is not whitelisted"; diff --git a/apps/backend/src/common/database.js b/apps/backend/src/common/database.js index e62988cc..cf6c508a 100644 --- a/apps/backend/src/common/database.js +++ b/apps/backend/src/common/database.js @@ -1,4 +1,5 @@ import pkg from "pg"; +// eslint-disable-next-line import-x/no-named-as-default-member const { Pool } = pkg; export const pool = process.env.POSTGRES_URL diff --git a/apps/backend/src/common/fmt.js b/apps/backend/src/common/fmt.js index 5820b53e..16c80b8b 100644 --- a/apps/backend/src/common/fmt.js +++ b/apps/backend/src/common/fmt.js @@ -1,6 +1,7 @@ // @ts-check import wrap from "word-wrap"; + import { encodeHTML } from "./html.js"; /** diff --git a/apps/backend/src/common/ops.js b/apps/backend/src/common/ops.js index e9c9ab40..692673df 100644 --- a/apps/backend/src/common/ops.js +++ b/apps/backend/src/common/ops.js @@ -1,6 +1,7 @@ // @ts-check import toEmoji from "emoji-name-map"; + import { CustomError } from "./error.js"; const OWNER_AFFILIATIONS = ["OWNER", "COLLABORATOR", "ORGANIZATION_MEMBER"]; diff --git a/apps/backend/src/common/render.js b/apps/backend/src/common/render.js index abf49070..36533464 100644 --- a/apps/backend/src/common/render.js +++ b/apps/backend/src/common/render.js @@ -1,7 +1,7 @@ // @ts-check -import { SECONDARY_ERROR_MESSAGES, TRY_AGAIN_LATER } from "./error.js"; import { getCardColors } from "./color.js"; +import { SECONDARY_ERROR_MESSAGES, TRY_AGAIN_LATER } from "./error.js"; import { encodeHTML } from "./html.js"; import { clampValue } from "./ops.js"; diff --git a/apps/backend/src/common/retryer.js b/apps/backend/src/common/retryer.js index f85cde27..4661deff 100644 --- a/apps/backend/src/common/retryer.js +++ b/apps/backend/src/common/retryer.js @@ -1,8 +1,8 @@ // @ts-check +import { getUserAccessByName } from "./database.js"; import { CustomError } from "./error.js"; import { logger } from "./log.js"; -import { getUserAccessByName } from "./database.js"; /** * Returns a random integer from 0 (inclusive) to `max` (exclusive). diff --git a/apps/backend/src/fetchers/gist.js b/apps/backend/src/fetchers/gist.js index da27f994..e80264ff 100644 --- a/apps/backend/src/fetchers/gist.js +++ b/apps/backend/src/fetchers/gist.js @@ -1,8 +1,8 @@ // @ts-check -import { retryer } from "../common/retryer.js"; import { MissingParamError } from "../common/error.js"; import { request } from "../common/http.js"; +import { retryer } from "../common/retryer.js"; const QUERY = ` query gistInfo($gistName: String!) { diff --git a/apps/backend/src/fetchers/repo.js b/apps/backend/src/fetchers/repo.js index 04371c5b..90b269c4 100644 --- a/apps/backend/src/fetchers/repo.js +++ b/apps/backend/src/fetchers/repo.js @@ -3,6 +3,7 @@ import { MissingParamError } from "../common/error.js"; import { request } from "../common/http.js"; import { retryer } from "../common/retryer.js"; + import { fetchRepoUserStats } from "./stats.js"; /** diff --git a/apps/backend/src/fetchers/stats.js b/apps/backend/src/fetchers/stats.js index 557f0afd..be7c1224 100644 --- a/apps/backend/src/fetchers/stats.js +++ b/apps/backend/src/fetchers/stats.js @@ -3,14 +3,15 @@ import axios from "axios"; import * as dotenv from "dotenv"; import githubUsernameRegex from "github-username-regex"; + import { calculateRank } from "../calculateRank.js"; -import { retryer } from "../common/retryer.js"; -import { buildSearchFilter, parseOwnerAffiliations } from "../common/ops.js"; -import { logger } from "../common/log.js"; import { excludeRepositories } from "../common/envs.js"; import { CustomError, MissingParamError } from "../common/error.js"; import { wrapTextMultiline } from "../common/fmt.js"; import { request } from "../common/http.js"; +import { logger } from "../common/log.js"; +import { buildSearchFilter, parseOwnerAffiliations } from "../common/ops.js"; +import { retryer } from "../common/retryer.js"; dotenv.config(); diff --git a/apps/backend/src/fetchers/top-languages.js b/apps/backend/src/fetchers/top-languages.js index 60e6d6f8..dad43ebe 100644 --- a/apps/backend/src/fetchers/top-languages.js +++ b/apps/backend/src/fetchers/top-languages.js @@ -1,12 +1,12 @@ // @ts-check -import { retryer } from "../common/retryer.js"; -import { parseOwnerAffiliations } from "../common/ops.js"; -import { logger } from "../common/log.js"; import { excludeRepositories } from "../common/envs.js"; import { CustomError, MissingParamError } from "../common/error.js"; import { wrapTextMultiline } from "../common/fmt.js"; import { request } from "../common/http.js"; +import { logger } from "../common/log.js"; +import { parseOwnerAffiliations } from "../common/ops.js"; +import { retryer } from "../common/retryer.js"; /** * Top languages fetcher object. diff --git a/apps/backend/src/fetchers/wakatime.js b/apps/backend/src/fetchers/wakatime.js index 2cf11e87..916d84a8 100644 --- a/apps/backend/src/fetchers/wakatime.js +++ b/apps/backend/src/fetchers/wakatime.js @@ -1,6 +1,7 @@ // @ts-check import axios from "axios"; + import { CustomError, MissingParamError } from "../common/error.js"; /** diff --git a/apps/backend/src/repeatRequests.js b/apps/backend/src/repeatRequests.js index 033f7fe5..14c6a533 100644 --- a/apps/backend/src/repeatRequests.js +++ b/apps/backend/src/repeatRequests.js @@ -1,8 +1,9 @@ import axios from "axios"; + import { - pool, deleteOldRequests, getRecentRequests, + pool, } from "./common/database.js"; /** diff --git a/apps/backend/src/users.js b/apps/backend/src/users.js index 55e43e9e..25e5d403 100644 --- a/apps/backend/src/users.js +++ b/apps/backend/src/users.js @@ -1,4 +1,5 @@ import axios from "axios"; + import { storeUser } from "./common/database.js"; /** diff --git a/apps/backend/tests/api.test.js b/apps/backend/tests/api.test.js index e3f44c37..8ec1f28b 100644 --- a/apps/backend/tests/api.test.js +++ b/apps/backend/tests/api.test.js @@ -10,11 +10,12 @@ import { } from "@jest/globals"; import axios from "axios"; import MockAdapter from "axios-mock-adapter"; + import api from "../api-renamed/index.js"; import { calculateRank } from "../src/calculateRank.js"; import { renderStatsCard } from "../src/cards/stats.js"; -import { renderError } from "../src/common/render.js"; import { CACHE_TTL, DURATIONS } from "../src/common/cache.js"; +import { renderError } from "../src/common/render.js"; /** * @type {import("../src/fetchers/stats").StatsData} diff --git a/apps/backend/tests/bench/api.bench.js b/apps/backend/tests/bench/api.bench.js index 2106df54..c14872a0 100644 --- a/apps/backend/tests/bench/api.bench.js +++ b/apps/backend/tests/bench/api.bench.js @@ -1,7 +1,9 @@ -import api from "../../api-renamed/index.js"; +import { it, jest } from "@jest/globals"; import axios from "axios"; import MockAdapter from "axios-mock-adapter"; -import { it, jest } from "@jest/globals"; + +import api from "../../api-renamed/index.js"; + import { runAndLogStats } from "./utils.js"; const stats = { diff --git a/apps/backend/tests/bench/calculateRank.bench.js b/apps/backend/tests/bench/calculateRank.bench.js index 6907dd21..bd39ff46 100644 --- a/apps/backend/tests/bench/calculateRank.bench.js +++ b/apps/backend/tests/bench/calculateRank.bench.js @@ -1,5 +1,7 @@ -import { calculateRank } from "../../src/calculateRank.js"; import { it } from "@jest/globals"; + +import { calculateRank } from "../../src/calculateRank.js"; + import { runAndLogStats } from "./utils.js"; it("calculateRank", async () => { diff --git a/apps/backend/tests/bench/gist.bench.js b/apps/backend/tests/bench/gist.bench.js index f310ea37..1fc845b1 100644 --- a/apps/backend/tests/bench/gist.bench.js +++ b/apps/backend/tests/bench/gist.bench.js @@ -1,7 +1,9 @@ -import gist from "../../api-renamed/gist.js"; +import { it, jest } from "@jest/globals"; import axios from "axios"; import MockAdapter from "axios-mock-adapter"; -import { it, jest } from "@jest/globals"; + +import gist from "../../api-renamed/gist.js"; + import { runAndLogStats } from "./utils.js"; const gist_data = { diff --git a/apps/backend/tests/bench/pin.bench.js b/apps/backend/tests/bench/pin.bench.js index e862617b..6c945fed 100644 --- a/apps/backend/tests/bench/pin.bench.js +++ b/apps/backend/tests/bench/pin.bench.js @@ -1,7 +1,9 @@ -import pin from "../../api-renamed/pin.js"; +import { it, jest } from "@jest/globals"; import axios from "axios"; import MockAdapter from "axios-mock-adapter"; -import { it, jest } from "@jest/globals"; + +import pin from "../../api-renamed/pin.js"; + import { runAndLogStats } from "./utils.js"; const data_repo = { diff --git a/apps/backend/tests/calculateRank.test.js b/apps/backend/tests/calculateRank.test.js index 34c2617e..ba341d5c 100644 --- a/apps/backend/tests/calculateRank.test.js +++ b/apps/backend/tests/calculateRank.test.js @@ -1,6 +1,8 @@ import { describe, expect, it } from "@jest/globals"; + import "@testing-library/jest-dom"; import { calculateRank } from "../src/calculateRank.js"; + import { approxNumber } from "./bench/utils.js"; describe("Test calculateRank", () => { diff --git a/apps/backend/tests/card.test.js b/apps/backend/tests/card.test.js index 21303603..574df25e 100644 --- a/apps/backend/tests/card.test.js +++ b/apps/backend/tests/card.test.js @@ -2,9 +2,10 @@ import { describe, expect, it } from "@jest/globals"; import { queryByTestId } from "@testing-library/dom"; import "@testing-library/jest-dom"; import { cssToObject } from "@uppercod/css-to-object"; + import { Card } from "../src/common/Card.js"; -import { icons } from "../src/common/icons.js"; import { getCardColors } from "../src/common/color.js"; +import { icons } from "../src/common/icons.js"; describe("Card", () => { it("should hide border", () => { diff --git a/apps/backend/tests/color.test.js b/apps/backend/tests/color.test.js index 464714b8..31ad423f 100644 --- a/apps/backend/tests/color.test.js +++ b/apps/backend/tests/color.test.js @@ -1,6 +1,7 @@ -import { getCardColors } from "../src/common/color"; import { describe, expect, it } from "@jest/globals"; +import { getCardColors } from "../src/common/color"; + describe("Test color.js", () => { it("getCardColors: should return expected values", () => { let colors = getCardColors({ diff --git a/apps/backend/tests/e2e/e2e.test.js b/apps/backend/tests/e2e/e2e.test.js index 68c0e09a..cfc8b7d3 100644 --- a/apps/backend/tests/e2e/e2e.test.js +++ b/apps/backend/tests/e2e/e2e.test.js @@ -1,17 +1,19 @@ /** * @file Contains end-to-end tests for the Vercel preview instance. */ -import dotenv from "dotenv"; -dotenv.config(); import { beforeAll, describe, expect, test } from "@jest/globals"; import axios from "axios"; +import * as dotenv from "dotenv"; + import { renderGistCard } from "../../src/cards/gist.js"; import { renderRepoCard } from "../../src/cards/repo.js"; import { renderStatsCard } from "../../src/cards/stats.js"; import { renderTopLanguages } from "../../src/cards/top-languages.js"; import { renderWakatimeCard } from "../../src/cards/wakatime.js"; +dotenv.config(); + const REPO = "curly-fiesta"; const USER = "catelinemnemosyne"; const STATS_CARD_USER = "e2eninja"; diff --git a/apps/backend/tests/fetchGist.test.js b/apps/backend/tests/fetchGist.test.js index ba5f3e52..6953921b 100644 --- a/apps/backend/tests/fetchGist.test.js +++ b/apps/backend/tests/fetchGist.test.js @@ -2,6 +2,7 @@ import { afterEach, describe, expect, it } from "@jest/globals"; import "@testing-library/jest-dom"; import axios from "axios"; import MockAdapter from "axios-mock-adapter"; + import { fetchGist } from "../src/fetchers/gist.js"; const gist_data = { diff --git a/apps/backend/tests/fetchRepo.test.js b/apps/backend/tests/fetchRepo.test.js index e976dd72..da615ab6 100644 --- a/apps/backend/tests/fetchRepo.test.js +++ b/apps/backend/tests/fetchRepo.test.js @@ -2,6 +2,7 @@ import { afterEach, describe, expect, it } from "@jest/globals"; import "@testing-library/jest-dom"; import axios from "axios"; import MockAdapter from "axios-mock-adapter"; + import { fetchRepo } from "../src/fetchers/repo.js"; const data_repo = { diff --git a/apps/backend/tests/fetchStats.test.js b/apps/backend/tests/fetchStats.test.js index c1ad5e4d..de3cc5d0 100644 --- a/apps/backend/tests/fetchStats.test.js +++ b/apps/backend/tests/fetchStats.test.js @@ -9,6 +9,7 @@ import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; import "@testing-library/jest-dom"; import axios from "axios"; import MockAdapter from "axios-mock-adapter"; + import { calculateRank } from "../src/calculateRank.js"; import { fetchStats } from "../src/fetchers/stats.js"; diff --git a/apps/backend/tests/fetchTopLanguages.test.js b/apps/backend/tests/fetchTopLanguages.test.js index b45fc03e..9f725452 100644 --- a/apps/backend/tests/fetchTopLanguages.test.js +++ b/apps/backend/tests/fetchTopLanguages.test.js @@ -2,7 +2,9 @@ import { afterEach, describe, expect, it } from "@jest/globals"; import "@testing-library/jest-dom"; import axios from "axios"; import MockAdapter from "axios-mock-adapter"; + import { fetchTopLanguages } from "../src/fetchers/top-languages.js"; + import { approxNumber } from "./bench/utils.js"; const mock = new MockAdapter(axios); diff --git a/apps/backend/tests/fetchWakatime.test.js b/apps/backend/tests/fetchWakatime.test.js index a0f8b12a..e3afba8b 100644 --- a/apps/backend/tests/fetchWakatime.test.js +++ b/apps/backend/tests/fetchWakatime.test.js @@ -2,6 +2,7 @@ import { afterEach, describe, expect, it } from "@jest/globals"; import "@testing-library/jest-dom"; import axios from "axios"; import MockAdapter from "axios-mock-adapter"; + import { fetchWakatimeStats } from "../src/fetchers/wakatime.js"; const mock = new MockAdapter(axios); diff --git a/apps/backend/tests/flexLayout.test.js b/apps/backend/tests/flexLayout.test.js index 740d9daa..b2bace7d 100644 --- a/apps/backend/tests/flexLayout.test.js +++ b/apps/backend/tests/flexLayout.test.js @@ -1,4 +1,5 @@ import { describe, expect, it } from "@jest/globals"; + import { flexLayout } from "../src/common/render.js"; describe("flexLayout", () => { diff --git a/apps/backend/tests/fmt.test.js b/apps/backend/tests/fmt.test.js index 857221f2..c6774c6a 100644 --- a/apps/backend/tests/fmt.test.js +++ b/apps/backend/tests/fmt.test.js @@ -1,4 +1,5 @@ import { describe, expect, it } from "@jest/globals"; + import { formatBytes, kFormatter, diff --git a/apps/backend/tests/gist.test.js b/apps/backend/tests/gist.test.js index 43846cee..c401a6bf 100644 --- a/apps/backend/tests/gist.test.js +++ b/apps/backend/tests/gist.test.js @@ -4,10 +4,11 @@ import { afterEach, describe, expect, it, jest } from "@jest/globals"; import "@testing-library/jest-dom"; import axios from "axios"; import MockAdapter from "axios-mock-adapter"; + import gist from "../api-renamed/gist.js"; import { renderGistCard } from "../src/cards/gist.js"; -import { renderError } from "../src/common/render.js"; import { CACHE_TTL, DURATIONS } from "../src/common/cache.js"; +import { renderError } from "../src/common/render.js"; const gist_data = { data: { diff --git a/apps/backend/tests/html.test.js b/apps/backend/tests/html.test.js index d83143ad..a9083232 100644 --- a/apps/backend/tests/html.test.js +++ b/apps/backend/tests/html.test.js @@ -1,4 +1,5 @@ import { describe, expect, it } from "@jest/globals"; + import { encodeHTML } from "../src/common/html.js"; describe("Test html.js", () => { diff --git a/apps/backend/tests/i18n.test.js b/apps/backend/tests/i18n.test.js index 22580029..f9a9bbdb 100644 --- a/apps/backend/tests/i18n.test.js +++ b/apps/backend/tests/i18n.test.js @@ -1,4 +1,5 @@ import { describe, expect, it } from "@jest/globals"; + import { I18n } from "../src/common/I18n.js"; import { statCardLocales } from "../src/translations.js"; diff --git a/apps/backend/tests/ops.test.js b/apps/backend/tests/ops.test.js index dd4e08b8..5cf2e37e 100644 --- a/apps/backend/tests/ops.test.js +++ b/apps/backend/tests/ops.test.js @@ -1,12 +1,13 @@ import { describe, expect, it } from "@jest/globals"; + import { - parseBoolean, - parseArray, - clampValue, - lowercaseTrim, chunkArray, - parseEmojis, + clampValue, dateDiff, + lowercaseTrim, + parseArray, + parseBoolean, + parseEmojis, } from "../src/common/ops.js"; describe("Test ops.js", () => { diff --git a/apps/backend/tests/pat-info.test.js b/apps/backend/tests/pat-info.test.js index 84d0ccad..866b0abb 100644 --- a/apps/backend/tests/pat-info.test.js +++ b/apps/backend/tests/pat-info.test.js @@ -2,9 +2,6 @@ * @file Tests for the status/pat-info cloud function. */ -import dotenv from "dotenv"; -dotenv.config(); - import { afterEach, beforeAll, @@ -15,8 +12,12 @@ import { } from "@jest/globals"; import axios from "axios"; import MockAdapter from "axios-mock-adapter"; +import { dotenv } from "dotenv"; + import patInfo, { RATE_LIMIT_SECONDS } from "../api-renamed/status/pat-info.js"; +dotenv.config(); + const mock = new MockAdapter(axios); const successData = { diff --git a/apps/backend/tests/pin.test.js b/apps/backend/tests/pin.test.js index 40530db0..70b00182 100644 --- a/apps/backend/tests/pin.test.js +++ b/apps/backend/tests/pin.test.js @@ -4,10 +4,11 @@ import { afterEach, describe, expect, it, jest } from "@jest/globals"; import "@testing-library/jest-dom"; import axios from "axios"; import MockAdapter from "axios-mock-adapter"; + import pin from "../api-renamed/pin.js"; import { renderRepoCard } from "../src/cards/repo.js"; -import { renderError } from "../src/common/render.js"; import { CACHE_TTL, DURATIONS } from "../src/common/cache.js"; +import { renderError } from "../src/common/render.js"; const data_repo = { repository: { diff --git a/apps/backend/tests/render.test.js b/apps/backend/tests/render.test.js index 6bb409b1..212bef3e 100644 --- a/apps/backend/tests/render.test.js +++ b/apps/backend/tests/render.test.js @@ -2,6 +2,7 @@ import { describe, expect, it } from "@jest/globals"; import { queryByTestId } from "@testing-library/dom"; + import "@testing-library/jest-dom/jest-globals"; import { renderError } from "../src/common/render.js"; diff --git a/apps/backend/tests/renderGistCard.test.js b/apps/backend/tests/renderGistCard.test.js index c397281a..9fbb227a 100644 --- a/apps/backend/tests/renderGistCard.test.js +++ b/apps/backend/tests/renderGistCard.test.js @@ -2,6 +2,7 @@ import { describe, expect, it } from "@jest/globals"; import { queryByTestId } from "@testing-library/dom"; import "@testing-library/jest-dom"; import { cssToObject } from "@uppercod/css-to-object"; + import { renderGistCard } from "../src/cards/gist.js"; import { themes } from "../themes/index.js"; diff --git a/apps/backend/tests/renderRepoCard.test.js b/apps/backend/tests/renderRepoCard.test.js index 9fb5ab36..7e5c3d91 100644 --- a/apps/backend/tests/renderRepoCard.test.js +++ b/apps/backend/tests/renderRepoCard.test.js @@ -2,6 +2,7 @@ import { describe, expect, it } from "@jest/globals"; import { queryByTestId } from "@testing-library/dom"; import "@testing-library/jest-dom"; import { cssToObject } from "@uppercod/css-to-object"; + import { renderRepoCard } from "../src/cards/repo.js"; import { themes } from "../themes/index.js"; diff --git a/apps/backend/tests/renderStatsCard.test.js b/apps/backend/tests/renderStatsCard.test.js index 1327fada..a6b045d6 100644 --- a/apps/backend/tests/renderStatsCard.test.js +++ b/apps/backend/tests/renderStatsCard.test.js @@ -6,6 +6,7 @@ import { } from "@testing-library/dom"; import "@testing-library/jest-dom"; import { cssToObject } from "@uppercod/css-to-object"; + import { renderStatsCard } from "../src/cards/stats.js"; import { CustomError } from "../src/common/error.js"; import { themes } from "../themes/index.js"; diff --git a/apps/backend/tests/renderTopLanguagesCard.test.js b/apps/backend/tests/renderTopLanguagesCard.test.js index 045fc89b..ccdeca5a 100644 --- a/apps/backend/tests/renderTopLanguagesCard.test.js +++ b/apps/backend/tests/renderTopLanguagesCard.test.js @@ -2,6 +2,7 @@ import { describe, expect, it } from "@jest/globals"; import { queryAllByTestId, queryByTestId } from "@testing-library/dom"; import "@testing-library/jest-dom"; import { cssToObject } from "@uppercod/css-to-object"; + import { MIN_CARD_WIDTH, calculateCompactLayoutHeight, @@ -20,8 +21,8 @@ import { renderTopLanguages, trimTopLanguages, } from "../src/cards/top-languages.js"; - import { themes } from "../themes/index.js"; + import { approxNumber } from "./bench/utils.js"; const langs = { diff --git a/apps/backend/tests/renderWakatimeCard.test.js b/apps/backend/tests/renderWakatimeCard.test.js index 24743f8d..a796e7a9 100644 --- a/apps/backend/tests/renderWakatimeCard.test.js +++ b/apps/backend/tests/renderWakatimeCard.test.js @@ -1,9 +1,12 @@ import { describe, expect, it } from "@jest/globals"; import { queryByTestId } from "@testing-library/dom"; -import "@testing-library/jest-dom"; + import { renderWakatimeCard } from "../src/cards/wakatime.js"; + import { wakaTimeData } from "./fetchWakatime.test.js"; +import "@testing-library/jest-dom"; + describe("Test Render WakaTime Card", () => { it("should render correctly", () => { const card = renderWakatimeCard(wakaTimeData.data); diff --git a/apps/backend/tests/retryer.test.js b/apps/backend/tests/retryer.test.js index b71e41f4..83751f25 100644 --- a/apps/backend/tests/retryer.test.js +++ b/apps/backend/tests/retryer.test.js @@ -1,9 +1,10 @@ // @ts-check import { describe, expect, it, jest } from "@jest/globals"; + import "@testing-library/jest-dom"; -import { retryer } from "../src/common/retryer.js"; import { logger } from "../src/common/log.js"; +import { retryer } from "../src/common/retryer.js"; const fetcher = jest.fn((variables, token) => { logger.log(variables, token); diff --git a/apps/backend/tests/setup.jest.js b/apps/backend/tests/setup.jest.js index 7c10c446..0a77a124 100644 --- a/apps/backend/tests/setup.jest.js +++ b/apps/backend/tests/setup.jest.js @@ -1,6 +1,6 @@ //https://stackoverflow.com/a/68468204/1643179 -import { TextEncoder, TextDecoder } from "util"; +import { TextDecoder, TextEncoder } from "util"; Object.assign(global, { TextDecoder, TextEncoder }); process.env.PAT_1 = "dummyPAT1"; diff --git a/apps/backend/tests/status.up.test.js b/apps/backend/tests/status.up.test.js index cc9e9e7a..d874d692 100644 --- a/apps/backend/tests/status.up.test.js +++ b/apps/backend/tests/status.up.test.js @@ -5,6 +5,7 @@ import { afterEach, describe, expect, it, jest } from "@jest/globals"; import axios from "axios"; import MockAdapter from "axios-mock-adapter"; + import up, { RATE_LIMIT_SECONDS } from "../api-renamed/status/up.js"; const mock = new MockAdapter(axios); diff --git a/apps/backend/tests/top-langs.test.js b/apps/backend/tests/top-langs.test.js index 453ac7cf..53983cc6 100644 --- a/apps/backend/tests/top-langs.test.js +++ b/apps/backend/tests/top-langs.test.js @@ -4,10 +4,11 @@ import { afterEach, describe, expect, it, jest } from "@jest/globals"; import "@testing-library/jest-dom"; import axios from "axios"; import MockAdapter from "axios-mock-adapter"; + import topLangs from "../api-renamed/top-langs.js"; import { renderTopLanguages } from "../src/cards/top-languages.js"; -import { renderError } from "../src/common/render.js"; import { CACHE_TTL, DURATIONS } from "../src/common/cache.js"; +import { renderError } from "../src/common/render.js"; const data_langs = { data: { diff --git a/apps/backend/tests/wakatime.test.js b/apps/backend/tests/wakatime.test.js index 98b530ab..58983a66 100644 --- a/apps/backend/tests/wakatime.test.js +++ b/apps/backend/tests/wakatime.test.js @@ -2,6 +2,7 @@ import { afterEach, describe, expect, it, jest } from "@jest/globals"; import "@testing-library/jest-dom"; import axios from "axios"; import MockAdapter from "axios-mock-adapter"; + import wakatime from "../api-renamed/wakatime.js"; import { renderWakatimeCard } from "../src/cards/wakatime.js"; import { CACHE_TTL, DURATIONS } from "../src/common/cache.js"; diff --git a/apps/frontend/e2e/app.spec.ts b/apps/frontend/e2e/app.spec.ts index 6a2ed8e1..882c2130 100644 --- a/apps/frontend/e2e/app.spec.ts +++ b/apps/frontend/e2e/app.spec.ts @@ -1,4 +1,4 @@ -import { test, expect } from "@playwright/test"; +import { expect, test } from "@playwright/test"; test("load initial page correctly", async ({ page }) => { await page.goto(""); diff --git a/apps/frontend/index.html b/apps/frontend/index.html index 1707e0a0..b09638c3 100644 --- a/apps/frontend/index.html +++ b/apps/frontend/index.html @@ -39,6 +39,6 @@
- + diff --git a/apps/frontend/src/axios-override.ts b/apps/frontend/src/axios-override.ts index 5b716ccf..d3c904d3 100644 --- a/apps/frontend/src/axios-override.ts +++ b/apps/frontend/src/axios-override.ts @@ -1,7 +1,7 @@ import axios, { getAdapter } from "axios"; import { setupCache } from "axios-cache-interceptor"; -import { HOST } from "./constants"; +import { HOST } from "./constants"; import additionalUserStars from "./mockData/additional_user_stars.json" with { type: "json" }; import commentedIssues from "./mockData/commented_issues.json" with { type: "json" }; import commentedPrs from "./mockData/commented_prs.json" with { type: "json" }; diff --git a/apps/frontend/src/components/Card/Card.tsx b/apps/frontend/src/components/Card/Card.tsx index 833720be..ec70d0d2 100644 --- a/apps/frontend/src/components/Card/Card.tsx +++ b/apps/frontend/src/components/Card/Card.tsx @@ -1,5 +1,5 @@ +import { clsx } from "clsx"; import type { JSX } from "react"; -import clsx from "clsx"; import { CardImage } from "./CardImage"; diff --git a/apps/frontend/src/components/Card/CardImage.tsx b/apps/frontend/src/components/Card/CardImage.tsx index e09c97ea..ce6fca69 100644 --- a/apps/frontend/src/components/Card/CardImage.tsx +++ b/apps/frontend/src/components/Card/CardImage.tsx @@ -1,4 +1,4 @@ -import clsx from "clsx"; +import { clsx } from "clsx"; import { HOST } from "../../constants"; diff --git a/apps/frontend/src/components/Card/SvgInline.tsx b/apps/frontend/src/components/Card/SvgInline.tsx index c9b37377..c3571167 100644 --- a/apps/frontend/src/components/Card/SvgInline.tsx +++ b/apps/frontend/src/components/Card/SvgInline.tsx @@ -1,13 +1,13 @@ +import axios from "axios"; import { useEffect, useRef, useState } from "react"; import type { JSX } from "react"; -import axios from "axios"; import Skeleton from "react-loading-skeleton"; import "react-loading-skeleton/dist/skeleton.css"; -import { createMockRequest, createMockResponse } from "../../mock-http.js"; +import { setShouldMock } from "../../axios-override.js"; // @ts-expect-error will be solved by npm package import { default as router } from "../../backend/.vercel/output/functions/api.func/router.js"; -import { setShouldMock } from "../../axios-override.js"; +import { createMockRequest, createMockResponse } from "../../mock-http.js"; import { useIsAuthenticated, useUserToken, diff --git a/apps/frontend/src/components/Generic/Button.tsx b/apps/frontend/src/components/Generic/Button.tsx index f88426eb..4417da01 100644 --- a/apps/frontend/src/components/Generic/Button.tsx +++ b/apps/frontend/src/components/Generic/Button.tsx @@ -1,4 +1,4 @@ -import clsx from "clsx"; +import { clsx } from "clsx"; import type { HTMLProps, JSX, ReactNode } from "react"; interface ButtonProps extends HTMLProps { diff --git a/apps/frontend/src/components/Generic/Select.tsx b/apps/frontend/src/components/Generic/Select.tsx index 9f80370e..b5a7c9a6 100644 --- a/apps/frontend/src/components/Generic/Select.tsx +++ b/apps/frontend/src/components/Generic/Select.tsx @@ -1,4 +1,4 @@ -import clsx from "clsx"; +import { clsx } from "clsx"; import type { JSX } from "react"; export interface SelectOption { diff --git a/apps/frontend/src/components/Home/CheckboxSection.tsx b/apps/frontend/src/components/Home/CheckboxSection.tsx index 89a95cea..1f505a79 100644 --- a/apps/frontend/src/components/Home/CheckboxSection.tsx +++ b/apps/frontend/src/components/Home/CheckboxSection.tsx @@ -1,7 +1,9 @@ -import { Section } from "./Section"; -import { Checkbox } from "../Generic/Checkbox"; import type { JSX } from "react"; +import { Checkbox } from "../Generic/Checkbox"; + +import { Section } from "./Section"; + interface CheckboxSectionProps { title: string; question: string; diff --git a/apps/frontend/src/components/Home/LanguagesLayoutSection.tsx b/apps/frontend/src/components/Home/LanguagesLayoutSection.tsx index 97c81400..0152ba80 100644 --- a/apps/frontend/src/components/Home/LanguagesLayoutSection.tsx +++ b/apps/frontend/src/components/Home/LanguagesLayoutSection.tsx @@ -1,9 +1,10 @@ import type { JSX } from "react"; -import { Section } from "./Section"; import { Select } from "../Generic/Select"; import type { SelectOption } from "../Generic/Select"; +import { Section } from "./Section"; + export const DEFAULT_OPTION: SelectOption = { id: 1, label: "Normal", diff --git a/apps/frontend/src/components/Home/Progress.tsx b/apps/frontend/src/components/Home/Progress.tsx index f296c333..27e6acfa 100644 --- a/apps/frontend/src/components/Home/Progress.tsx +++ b/apps/frontend/src/components/Home/Progress.tsx @@ -1,6 +1,5 @@ -import clsx from "clsx"; +import { clsx } from "clsx"; import type { JSX, MouseEventHandler } from "react"; - import { FaArrowLeft as LeftArrowIcon, FaArrowRight as RightArrowIcon, diff --git a/apps/frontend/src/components/Home/Section.tsx b/apps/frontend/src/components/Home/Section.tsx index cf4e8d91..c2d9c4ef 100644 --- a/apps/frontend/src/components/Home/Section.tsx +++ b/apps/frontend/src/components/Home/Section.tsx @@ -1,5 +1,4 @@ import type { JSX, ReactNode } from "react"; - import { HiOutlineLightningBolt as LightningIcon } from "react-icons/hi"; interface SectionProps { diff --git a/apps/frontend/src/components/Home/TextSection.tsx b/apps/frontend/src/components/Home/TextSection.tsx index 8a04caa8..3fa760d2 100644 --- a/apps/frontend/src/components/Home/TextSection.tsx +++ b/apps/frontend/src/components/Home/TextSection.tsx @@ -1,6 +1,6 @@ +import { clsx } from "clsx"; import { useEffect, useRef, useState } from "react"; import type { ClipboardEventHandler, JSX, ReactNode } from "react"; -import clsx from "clsx"; import { Section } from "./Section"; diff --git a/apps/frontend/src/components/Home/WakatimeLayoutSection.tsx b/apps/frontend/src/components/Home/WakatimeLayoutSection.tsx index 13ce0b3d..3e49ee77 100644 --- a/apps/frontend/src/components/Home/WakatimeLayoutSection.tsx +++ b/apps/frontend/src/components/Home/WakatimeLayoutSection.tsx @@ -1,9 +1,10 @@ import type { JSX } from "react"; -import { Section } from "./Section"; import { Select } from "../Generic/Select"; import type { SelectOption } from "../Generic/Select"; +import { Section } from "./Section"; + export const DEFAULT_OPTION: SelectOption = { id: 1, label: "Normal", diff --git a/apps/frontend/src/index.jsx b/apps/frontend/src/index.tsx similarity index 68% rename from apps/frontend/src/index.jsx rename to apps/frontend/src/index.tsx index 93289cd6..18d2d6a3 100644 --- a/apps/frontend/src/index.jsx +++ b/apps/frontend/src/index.tsx @@ -1,13 +1,14 @@ import "./axios-override"; -import ReactDOM from "react-dom/client"; + +import { createRoot } from "react-dom/client"; import { Provider } from "react-redux"; -import { store } from "./redux/store"; import { AppTrends } from "./pages/App/AppTrends"; +import { store } from "./redux/store"; import "./index.css"; -const root = ReactDOM.createRoot(document.getElementById("root")); +const root = createRoot(document.getElementById("root") as HTMLElement); root.render( diff --git a/apps/frontend/src/pages/App/AppTrends.tsx b/apps/frontend/src/pages/App/AppTrends.tsx index 7c602d32..8b6a1e46 100644 --- a/apps/frontend/src/pages/App/AppTrends.tsx +++ b/apps/frontend/src/pages/App/AppTrends.tsx @@ -1,24 +1,25 @@ import { useEffect, useRef, useState } from "react"; import { useDispatch } from "react-redux"; -import { toast, ToastContainer } from "react-toastify"; -import "react-toastify/dist/ReactToastify.css"; +import { ToastContainer, toast } from "react-toastify"; -import { - logout as _logout, - setUserAccess as _setUserAccess, -} from "../../redux/slices/user"; -import { clearAxiosCache } from "../../axios-override"; -import { HomeScreen } from "../Home/Home"; import { getUserMetadata } from "../../api/user"; +import { clearAxiosCache } from "../../axios-override"; +import type { StageIndex } from "../../models/Stage"; import { useIsAuthenticated, useUserKey, useUserToken, } from "../../redux/selectors/userSelectors"; -import type { StageIndex } from "../../models/Stage"; +import { + logout as _logout, + setUserAccess as _setUserAccess, +} from "../../redux/slices/user"; +import { HomeScreen } from "../Home/Home"; import { Header } from "./Header"; +import "react-toastify/dist/ReactToastify.css"; + const toMessage = ( input: string | ErrorEvent | PromiseRejectionEvent, ): string => { diff --git a/apps/frontend/src/pages/App/Header.tsx b/apps/frontend/src/pages/App/Header.tsx index ae6e81b0..ba4c3b66 100644 --- a/apps/frontend/src/pages/App/Header.tsx +++ b/apps/frontend/src/pages/App/Header.tsx @@ -1,7 +1,7 @@ import type { JSX } from "react"; +import { FaGithub as GithubIcon } from "react-icons/fa"; import appIcon from "../../assets/appLogo64.png"; -import { FaGithub as GithubIcon } from "react-icons/fa"; import { ProgressBar } from "../../components/Home/Progress"; import { STAGE_LABELS } from "../../models/Stage"; import type { StageIndex } from "../../models/Stage"; diff --git a/apps/frontend/src/pages/Home/Home.tsx b/apps/frontend/src/pages/Home/Home.tsx index 22997762..a1f7b5e3 100644 --- a/apps/frontend/src/pages/Home/Home.tsx +++ b/apps/frontend/src/pages/Home/Home.tsx @@ -1,30 +1,30 @@ +import axios from "axios"; import { useEffect, useMemo, useRef, useState } from "react"; import type { JSX } from "react"; import { useDispatch } from "react-redux"; import BounceLoader from "react-spinners/BounceLoader"; -import axios from "axios"; import { v4 as uuidv4 } from "uuid"; import { authenticate } from "../../api/user"; -import { login } from "../../redux/slices/user"; -import { - HOST, - DEMO_USER, - DEMO_WAKATIME_USER, - DEMO_REPO, - DEMO_GIST, -} from "../../constants"; -import { CardType } from "../../models/CardType"; -import { DEFAULT_OPTION as STATS_DEFAULT_RANK } from "../../components/Home/StatsRankSection"; import { DEFAULT_OPTION as LANGUAGES_DEFAULT_LAYOUT } from "../../components/Home/LanguagesLayoutSection"; +import { DEFAULT_OPTION as STATS_DEFAULT_RANK } from "../../components/Home/StatsRankSection"; import { DEFAULT_OPTION as WAKATIME_DEFAULT_LAYOUT } from "../../components/Home/WakatimeLayoutSection"; import { - useUserId, - useIsAuthenticated, - usePrivateAccess, -} from "../../redux/selectors/userSelectors"; + DEMO_GIST, + DEMO_REPO, + DEMO_USER, + DEMO_WAKATIME_USER, + HOST, +} from "../../constants"; +import { CardType } from "../../models/CardType"; import { STAGE_LABELS } from "../../models/Stage"; import type { StageIndex } from "../../models/Stage"; +import { + useIsAuthenticated, + usePrivateAccess, + useUserId, +} from "../../redux/selectors/userSelectors"; +import { login } from "../../redux/slices/user"; import { CustomizeStage } from "./stages/Customize"; import { DisplayStage } from "./stages/Display"; diff --git a/apps/frontend/src/pages/Home/stages/Customize.tsx b/apps/frontend/src/pages/Home/stages/Customize.tsx index 64f25f89..43b65f18 100644 --- a/apps/frontend/src/pages/Home/stages/Customize.tsx +++ b/apps/frontend/src/pages/Home/stages/Customize.tsx @@ -1,13 +1,12 @@ -import type React from "react"; -import type { JSX } from "react"; +import type { JSX, default as React } from "react"; -import { CardType } from "../../../models/CardType"; import { CardImage } from "../../../components/Card/CardImage"; +import type { SelectOption } from "../../../components/Generic/Select"; import { CheckboxSection } from "../../../components/Home/CheckboxSection"; -import { TextSection } from "../../../components/Home/TextSection"; +import { LanguagesLayoutSection } from "../../../components/Home/LanguagesLayoutSection"; import { NumericSection } from "../../../components/Home/NumericSection"; import { StatsRankSection } from "../../../components/Home/StatsRankSection"; -import { LanguagesLayoutSection } from "../../../components/Home/LanguagesLayoutSection"; +import { TextSection } from "../../../components/Home/TextSection"; import { WakatimeLayoutSection } from "../../../components/Home/WakatimeLayoutSection"; import { DEMO_GIST, @@ -15,9 +14,9 @@ import { DEMO_USER, DEMO_WAKATIME_USER, } from "../../../constants"; -import { useIsAuthenticated } from "../../../redux/selectors/userSelectors"; -import type { SelectOption } from "../../../components/Generic/Select"; +import { CardType } from "../../../models/CardType"; import type { StageIndex } from "../../../models/Stage"; +import { useIsAuthenticated } from "../../../redux/selectors/userSelectors"; type Updater = React.Dispatch>; diff --git a/apps/frontend/src/pages/Home/stages/Display.tsx b/apps/frontend/src/pages/Home/stages/Display.tsx index 4ce8a13b..e59c7bcb 100644 --- a/apps/frontend/src/pages/Home/stages/Display.tsx +++ b/apps/frontend/src/pages/Home/stages/Display.tsx @@ -1,12 +1,13 @@ import { clsx } from "clsx"; -import { saveSvgAsPng } from "save-svg-as-png"; -import { toast } from "react-toastify"; -import "react-toastify/dist/ReactToastify.css"; - -import { Button } from "../../../components/Generic/Button"; -import { CardImage } from "../../../components/Card/CardImage"; -import { HOST } from "../../../constants"; import type { JSX } from "react"; +import { toast } from "react-toastify"; +import { saveSvgAsPng } from "save-svg-as-png"; + +import { CardImage } from "../../../components/Card/CardImage"; +import { Button } from "../../../components/Generic/Button"; +import { HOST } from "../../../constants"; + +import "react-toastify/dist/ReactToastify.css"; interface DisplayStageProps { filename: string; diff --git a/apps/frontend/src/pages/Home/stages/Login/Login.tsx b/apps/frontend/src/pages/Home/stages/Login/Login.tsx index 2209fa0d..684d2f4d 100644 --- a/apps/frontend/src/pages/Home/stages/Login/Login.tsx +++ b/apps/frontend/src/pages/Home/stages/Login/Login.tsx @@ -2,8 +2,8 @@ import type { JSX } from "react"; import { useIsAuthenticated } from "../../../../redux/selectors/userSelectors"; -import { LoginOptions } from "./LoginOptions"; import { LoginAccountManagement } from "./LoginAccountManagement"; +import { LoginOptions } from "./LoginOptions"; interface LoginStageProps { onContinueAsGuest: () => void; diff --git a/apps/frontend/src/pages/Home/stages/Login/LoginAccountDeleteModal.tsx b/apps/frontend/src/pages/Home/stages/Login/LoginAccountDeleteModal.tsx index 7dc653bd..ba2c0f96 100644 --- a/apps/frontend/src/pages/Home/stages/Login/LoginAccountDeleteModal.tsx +++ b/apps/frontend/src/pages/Home/stages/Login/LoginAccountDeleteModal.tsx @@ -1,4 +1,5 @@ -import { useEffect, useRef, type JSX, type RefObject } from "react"; +import { useEffect, useRef } from "react"; +import type { JSX, RefObject } from "react"; import { createPortal } from "react-dom"; import { Button } from "../../../../components/Generic/Button"; diff --git a/apps/frontend/src/pages/Home/stages/Login/LoginAccountManagement.tsx b/apps/frontend/src/pages/Home/stages/Login/LoginAccountManagement.tsx index a2f30992..f0c36921 100644 --- a/apps/frontend/src/pages/Home/stages/Login/LoginAccountManagement.tsx +++ b/apps/frontend/src/pages/Home/stages/Login/LoginAccountManagement.tsx @@ -1,22 +1,23 @@ -import { useCallback, useState, type JSX } from "react"; -import { useDispatch } from "react-redux"; +import { useCallback, useState } from "react"; +import type { JSX } from "react"; import { FaGithub as GithubIcon } from "react-icons/fa"; +import { useDispatch } from "react-redux"; +import { deleteAccount } from "../../../../api/user"; +import { Button } from "../../../../components/Generic/Button"; +import { + CLIENT_ID, + GITHUB_PRIVATE_AUTH_URL, + HOST, +} from "../../../../constants"; import { usePrivateAccess, useUserId, useUserKey, } from "../../../../redux/selectors/userSelectors"; -import { deleteAccount } from "../../../../api/user"; -import { Button } from "../../../../components/Generic/Button"; -import { - CLIENT_ID, - HOST, - GITHUB_PRIVATE_AUTH_URL, -} from "../../../../constants"; -import { LoginAccountDeleteModal } from "./LoginAccountDeleteModal"; import { logout } from "../../../../redux/slices/user"; +import { LoginAccountDeleteModal } from "./LoginAccountDeleteModal"; import { LoginBox } from "./LoginBox"; export function LoginAccountManagement(): JSX.Element { diff --git a/apps/frontend/src/pages/Home/stages/Login/LoginBox.tsx b/apps/frontend/src/pages/Home/stages/Login/LoginBox.tsx index c5ca4236..d603563a 100644 --- a/apps/frontend/src/pages/Home/stages/Login/LoginBox.tsx +++ b/apps/frontend/src/pages/Home/stages/Login/LoginBox.tsx @@ -1,5 +1,5 @@ +import { clsx } from "clsx"; import type { JSX, ReactNode } from "react"; -import clsx from "clsx"; import { LoginBoxDemoCards } from "./LoginBoxDemoCards"; diff --git a/apps/frontend/src/pages/Home/stages/Login/LoginBoxDemoCards.tsx b/apps/frontend/src/pages/Home/stages/Login/LoginBoxDemoCards.tsx index 4d11c249..99834c38 100644 --- a/apps/frontend/src/pages/Home/stages/Login/LoginBoxDemoCards.tsx +++ b/apps/frontend/src/pages/Home/stages/Login/LoginBoxDemoCards.tsx @@ -2,10 +2,10 @@ import type { JSX } from "react"; import { CardImage } from "../../../../components/Card/CardImage"; import { + DEMO_GIST, DEMO_REPO, DEMO_USER, DEMO_WAKATIME_USER, - DEMO_GIST, } from "../../../../constants"; const cards: Array<{ demoImageSrc: string }> = [ diff --git a/apps/frontend/src/pages/Home/stages/Login/LoginOptions.tsx b/apps/frontend/src/pages/Home/stages/Login/LoginOptions.tsx index ede4545f..4e763bad 100644 --- a/apps/frontend/src/pages/Home/stages/Login/LoginOptions.tsx +++ b/apps/frontend/src/pages/Home/stages/Login/LoginOptions.tsx @@ -3,8 +3,8 @@ import { FaGithub as GithubIcon } from "react-icons/fa"; import { Button } from "../../../../components/Generic/Button"; import { - GITHUB_PUBLIC_AUTH_URL, GITHUB_PRIVATE_AUTH_URL, + GITHUB_PUBLIC_AUTH_URL, } from "../../../../constants"; import { LoginBox } from "./LoginBox"; diff --git a/apps/frontend/src/pages/Home/stages/SelectCard.tsx b/apps/frontend/src/pages/Home/stages/SelectCard.tsx index aa66b3f8..ed59b09e 100644 --- a/apps/frontend/src/pages/Home/stages/SelectCard.tsx +++ b/apps/frontend/src/pages/Home/stages/SelectCard.tsx @@ -1,5 +1,7 @@ +import { useMemo } from "react"; +import type { JSX } from "react"; + import { Card } from "../../../components/Card/Card"; -import { useUserId } from "../../../redux/selectors/userSelectors"; import { DEMO_GIST, DEMO_REPO, @@ -7,7 +9,7 @@ import { DEMO_WAKATIME_USER, } from "../../../constants"; import { CardType } from "../../../models/CardType"; -import { useMemo, type JSX } from "react"; +import { useUserId } from "../../../redux/selectors/userSelectors"; interface SelectCardStageProps { selectedCardType: CardType; diff --git a/apps/frontend/src/pages/Home/stages/Theme.tsx b/apps/frontend/src/pages/Home/stages/Theme.tsx index 91278361..247d8caf 100644 --- a/apps/frontend/src/pages/Home/stages/Theme.tsx +++ b/apps/frontend/src/pages/Home/stages/Theme.tsx @@ -1,8 +1,8 @@ import type { JSX } from "react"; -import { Card } from "../../../components/Card/Card"; // @ts-expect-error this will be provided by the npm package import { themes } from "../../../backend/themes/index"; +import { Card } from "../../../components/Card/Card"; // to be removed once npm package has been created type ThemeData = Record< diff --git a/apps/frontend/src/wakatime-override.ts b/apps/frontend/src/wakatime-override.ts index d7dbb894..61b678be 100644 --- a/apps/frontend/src/wakatime-override.ts +++ b/apps/frontend/src/wakatime-override.ts @@ -1,4 +1,5 @@ import axios from "axios"; + import { HOST } from "./constants"; // See https://github.com/stats-organization/github-stats-extended/pull/27#discussion_r2712184285 diff --git a/apps/frontend/vite.config.ts b/apps/frontend/vite.config.ts index 35976299..71fbcb9d 100644 --- a/apps/frontend/vite.config.ts +++ b/apps/frontend/vite.config.ts @@ -1,9 +1,8 @@ import path from "node:path"; +import react from "@vitejs/plugin-react-swc"; import { defineConfig } from "vite"; import { nodePolyfills } from "vite-plugin-node-polyfills"; -import react from "@vitejs/plugin-react-swc"; - import StringReplace from "vite-plugin-string-replace"; // https://vitejs.dev/config/ diff --git a/eslint.config.js b/eslint.config.js index ec647033..b1b9de20 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,19 +1,46 @@ import { fileURLToPath } from "node:url"; -import { defineConfig } from "eslint/config"; -import globals from "globals"; +import { includeIgnoreFile } from "@eslint/compat"; import js from "@eslint/js"; -import jsdoc from "eslint-plugin-jsdoc"; +import { defineConfig } from "eslint/config"; +import { importX } from "eslint-plugin-import-x"; +import { default as jsdoc } from "eslint-plugin-jsdoc"; import react from "eslint-plugin-react"; import reactHooks from "eslint-plugin-react-hooks"; -import { includeIgnoreFile } from "@eslint/compat"; -import tseslint from "typescript-eslint"; +import globals from "globals"; +import { default as tseslint } from "typescript-eslint"; const gitignorePath = fileURLToPath(new URL(".gitignore", import.meta.url)); export default defineConfig( includeIgnoreFile(gitignorePath, "Imported .gitignore patterns"), js.configs.recommended, + + { + extends: [importX.flatConfigs.recommended, importX.flatConfigs.typescript], + rules: { + "import-x/consistent-type-specifier-style": ["error", "prefer-top-level"], + "import-x/order": [ + "error", + { + groups: [ + "builtin", + "external", + "internal", + "parent", + "sibling", + "index", + ], + alphabetize: { + order: "asc", + caseInsensitive: false, + }, + named: { enabled: true, export: false }, + "newlines-between": "always", + }, + ], + }, + }, { linterOptions: { reportUnusedDisableDirectives: "error", diff --git a/knip.jsonc b/knip.jsonc index 0a4cf9da..b1b0c6a1 100644 --- a/knip.jsonc +++ b/knip.jsonc @@ -19,7 +19,7 @@ }, "apps/frontend": { "entry": [ - "src/index.jsx", + "src/index.tsx", "src/dotenv-browser-stub.ts", // referenced by vite.config.ts "src/wakatime-override.ts" ], diff --git a/package.json b/package.json index b9a5131a..087d6e34 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,8 @@ "@playwright/test": "1.58.1", "@types/node": "24.10.9", "eslint": "9.39.2", + "eslint-import-resolver-typescript": "4.4.4", + "eslint-plugin-import-x": "4.16.1", "eslint-plugin-jsdoc": "61.7.1", "eslint-plugin-react": "7.37.5", "eslint-plugin-react-hooks": "7.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 42dbcdc8..2c3f2a87 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,12 @@ importers: eslint: specifier: 9.39.2 version: 9.39.2(jiti@2.6.1) + eslint-import-resolver-typescript: + specifier: 4.4.4 + version: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)) + eslint-plugin-import-x: + specifier: 4.16.1 + version: 4.16.1(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)) eslint-plugin-jsdoc: specifier: 61.7.1 version: 61.7.1(eslint@9.39.2(jiti@2.6.1)) @@ -2211,6 +2217,41 @@ packages: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} + eslint-import-context@0.1.9: + resolution: {integrity: sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + peerDependencies: + unrs-resolver: ^1.0.0 + peerDependenciesMeta: + unrs-resolver: + optional: true + + eslint-import-resolver-typescript@4.4.4: + resolution: {integrity: sha512-1iM2zeBvrYmUNTj2vSC/90JTHDth+dfOfiNKkxApWRsTJYNrc8rOdxxIf5vazX+BiAXTeOT0UvWpGI/7qIWQOw==} + engines: {node: ^16.17.0 || >=18.6.0} + peerDependencies: + eslint: '*' + eslint-plugin-import: '*' + eslint-plugin-import-x: '*' + peerDependenciesMeta: + eslint-plugin-import: + optional: true + eslint-plugin-import-x: + optional: true + + eslint-plugin-import-x@4.16.1: + resolution: {integrity: sha512-vPZZsiOKaBAIATpFE2uMI4w5IRwdv/FpQ+qZZMR4E+PeOcM4OeoEbqxRMnywdxP19TyB/3h6QBB0EWon7letSQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/utils': ^8.0.0 + eslint: ^8.57.0 || ^9.0.0 + eslint-import-resolver-node: '*' + peerDependenciesMeta: + '@typescript-eslint/utils': + optional: true + eslint-import-resolver-node: + optional: true + eslint-plugin-jsdoc@61.7.1: resolution: {integrity: sha512-36DpldF95MlTX//n3/naULFVt8d1cV4jmSkx7ZKrE9ikkKHAgMLesuWp1SmwpVwAs5ndIM6abKd6PeOYZUgdWg==} engines: {node: '>=20.11.0'} @@ -2477,6 +2518,9 @@ packages: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} + get-tsconfig@4.13.1: + resolution: {integrity: sha512-EoY1N2xCn44xU6750Sx7OjOIT59FkmstNc3X6y5xpz7D5cBtZRe/3pSlTkDJgqsOk3WwZPkWfonhhUJfttQo3w==} + github-username-regex@1.0.0: resolution: {integrity: sha512-EqDVkN0/5MQyDPOSDLInVRRXdeISRfcN1UW/1FUqD2knV1HHw8DndMB3UPNn5lO51DvRnjzbLXwWqNNV86PLOw==} @@ -2696,6 +2740,9 @@ packages: resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} engines: {node: '>=4'} + is-bun-module@2.0.0: + resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==} + is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -3733,6 +3780,9 @@ packages: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolve@1.22.11: resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} engines: {node: '>= 0.4'} @@ -3923,6 +3973,10 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + stable-hash-x@0.2.0: + resolution: {integrity: sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==} + engines: {node: '>=12.0.0'} + stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} @@ -6561,6 +6615,45 @@ snapshots: escape-string-regexp@5.0.0: {} + eslint-import-context@0.1.9(unrs-resolver@1.11.1): + dependencies: + get-tsconfig: 4.13.1 + stable-hash-x: 0.2.0 + optionalDependencies: + unrs-resolver: 1.11.1 + + eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)): + dependencies: + debug: 4.4.3 + eslint: 9.39.2(jiti@2.6.1) + eslint-import-context: 0.1.9(unrs-resolver@1.11.1) + get-tsconfig: 4.13.1 + is-bun-module: 2.0.0 + stable-hash-x: 0.2.0 + tinyglobby: 0.2.15 + unrs-resolver: 1.11.1 + optionalDependencies: + eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)) + transitivePeerDependencies: + - supports-color + + eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)): + dependencies: + '@typescript-eslint/types': 8.54.0 + comment-parser: 1.4.1 + debug: 4.4.3 + eslint: 9.39.2(jiti@2.6.1) + eslint-import-context: 0.1.9(unrs-resolver@1.11.1) + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.3 + stable-hash-x: 0.2.0 + unrs-resolver: 1.11.1 + optionalDependencies: + '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + transitivePeerDependencies: + - supports-color + eslint-plugin-jsdoc@61.7.1(eslint@9.39.2(jiti@2.6.1)): dependencies: '@es-joy/jsdoccomment': 0.78.0 @@ -6917,6 +7010,10 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.3.0 + get-tsconfig@4.13.1: + dependencies: + resolve-pkg-maps: 1.0.0 + github-username-regex@1.0.0: {} glob-parent@5.1.2: @@ -7141,6 +7238,10 @@ snapshots: is-buffer@2.0.5: {} + is-bun-module@2.0.0: + dependencies: + semver: 7.7.3 + is-callable@1.2.7: {} is-core-module@2.16.1: @@ -8393,6 +8494,8 @@ snapshots: resolve-from@5.0.0: {} + resolve-pkg-maps@1.0.0: {} + resolve@1.22.11: dependencies: is-core-module: 2.16.1 @@ -8643,6 +8746,8 @@ snapshots: sprintf-js@1.0.3: {} + stable-hash-x@0.2.0: {} + stack-utils@2.0.6: dependencies: escape-string-regexp: 2.0.0