From cbf8d1ccd3d5674c743b085936289fa2814bd42a Mon Sep 17 00:00:00 2001 From: konsumlamm Date: Wed, 22 May 2024 17:20:53 +0200 Subject: [PATCH 1/4] [CI] Build liberica --- .github/workflows/ci.yaml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 38bf28e..e004886 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -3,7 +3,7 @@ name: CI on: - pull_request - push - + env: CARGO_TERM_COLOR: always @@ -14,12 +14,12 @@ jobs: steps: - name: Checkout sources uses: actions/checkout@v4 - + - uses: actions/cache@v3 with: path: target key: ${{ runner.os }}-robusta-mister-x - + - name: 🔬 Rust fmt run: cargo fmt --check --all @@ -30,25 +30,28 @@ jobs: liberica: name: ⚡ liberica Check runs-on: ubuntu-latest - + defaults: run: working-directory: liberica - + steps: - name: Checkout sources uses: actions/checkout@v4 - + - uses: actions/cache@v3 with: path: liberica/node_modules key: ${{ runner.os }}-liberica-mister-x - + - name: 🚧 Setup bun uses: oven-sh/setup-bun@v1 - name: 🚧 Install dependencies run: bun install + - name: 🔨 Build liberica + run: bun run build + - name: 🔎 Lint liberica run: bun lint From 403cfee55beaaf836a3d1e77c1184d9f044c58d0 Mon Sep 17 00:00:00 2001 From: Aaron Geiger Date: Thu, 23 May 2024 14:10:53 +0200 Subject: [PATCH 2/4] Type check in lint stage --- .github/workflows/ci.yaml | 3 --- liberica/eslint.config.js | 12 ++++++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e004886..161827a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -50,8 +50,5 @@ jobs: - name: 🚧 Install dependencies run: bun install - - name: 🔨 Build liberica - run: bun run build - - name: 🔎 Lint liberica run: bun lint diff --git a/liberica/eslint.config.js b/liberica/eslint.config.js index 06c9e24..940113d 100644 --- a/liberica/eslint.config.js +++ b/liberica/eslint.config.js @@ -21,13 +21,21 @@ import eslintConfigPrettier from "eslint-config-prettier" /** @type {import("eslint").Config} */ export default [ { ignores: ["src/lib/bindings.ts", "node_modules", "dist"] }, - { languageOptions: { globals: globals.browser } }, + { + languageOptions: { + globals: globals.browser, + parserOptions: { + project: true, + tsconfigRootDir: import.meta.dirname + } + } + }, eslintJs.configs.recommended, eslintPluginPrettier, eslintConfigPrettier, // disables some rules that cause conflicts - ...tseslint.configs.strict, // strict is a superset of recommended + ...tseslint.configs.strictTypeChecked, // strict is a superset of recommended ...tseslint.configs.stylistic, ]; From 03363968fc137720af5a51f93d12fb87cbd9dc92 Mon Sep 17 00:00:00 2001 From: Aaron Geiger Date: Thu, 23 May 2024 14:25:25 +0200 Subject: [PATCH 3/4] Disable no-confusing-void-expression --- liberica/eslint.config.js | 7 +++++++ liberica/src/lib/websockets.ts | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/liberica/eslint.config.js b/liberica/eslint.config.js index 940113d..02edbbe 100644 --- a/liberica/eslint.config.js +++ b/liberica/eslint.config.js @@ -38,4 +38,11 @@ export default [ ...tseslint.configs.strictTypeChecked, // strict is a superset of recommended ...tseslint.configs.stylistic, + + + { + rules: { + "@typescript-eslint/no-confusing-void-expression": "off" + } + } ]; diff --git a/liberica/src/lib/websockets.ts b/liberica/src/lib/websockets.ts index 04958d7..8857422 100644 --- a/liberica/src/lib/websockets.ts +++ b/liberica/src/lib/websockets.ts @@ -45,7 +45,7 @@ export class WebSocketApi { public reconnect(force = false) { // Don't try to reconnect if there is a connection already - if (this.connection?.readyState === this.connection.OPEN && force) + if (this.connection.readyState === this.connection.OPEN && force) return; this.disconnect(); @@ -90,7 +90,7 @@ export class WebSocketApi { public register>( type: T, handler: WSHandlerMap[T], - ): WebSocketApi { + ): this { this.handlers[type] = handler; return this; } From 8dc9b42f0d16808bf6a97c634e9adfd3d4d8378c Mon Sep 17 00:00:00 2001 From: Aaron Geiger Date: Thu, 23 May 2024 15:37:56 +0200 Subject: [PATCH 4/4] Fix lints --- liberica/src/components/InputElements.tsx | 9 +++++---- liberica/src/components/Spinner.tsx | 4 ++-- liberica/src/lib/api.ts | 18 +++++++++++++++--- liberica/src/lib/websockets.ts | 1 + liberica/src/main.tsx | 6 +++++- liberica/src/page/CreateTeam.tsx | 13 ++++--------- liberica/src/page/Game.tsx | 23 +++++++++++------------ liberica/src/page/Home.tsx | 5 +++-- liberica/src/page/Replay.tsx | 15 +++++++-------- 9 files changed, 53 insertions(+), 41 deletions(-) diff --git a/liberica/src/components/InputElements.tsx b/liberica/src/components/InputElements.tsx index 7d848d3..eb028ac 100644 --- a/liberica/src/components/InputElements.tsx +++ b/liberica/src/components/InputElements.tsx @@ -14,11 +14,12 @@ export const TextInput = ({ placeholder="Lila Pause" onChange={(e) => { const fn = { - end: String.prototype.trimEnd, - start: String.prototype.trimStart, - all: String.prototype.trim, + end: (s: string) => s.trimEnd(), + start: (s: string) => s.trimStart(), + all: (s: string) => s.trim(), }; - const value = trim && fn[trim].call(e.target.value); + + const value = trim && fn[trim](e.target.value); onTextChange(value || e.target.value); }} {...props} diff --git a/liberica/src/components/Spinner.tsx b/liberica/src/components/Spinner.tsx index e5e5226..51a67db 100644 --- a/liberica/src/components/Spinner.tsx +++ b/liberica/src/components/Spinner.tsx @@ -1,8 +1,8 @@ -export function Spinner(props: { className?: string; color?: string }) { +export function Spinner(props: { color?: string }) { const color = props.color ?? "white"; return ( => AXIOS.post(ENDPOINTS.POST_CREATE_TEAM, team); export const getTeams = (): Promise => - AXIOS.get(ENDPOINTS.GET_TEAMS).then((data) => data.data); + AXIOS.get(ENDPOINTS.GET_TEAMS).then((data) => data.data as Team[]); export const getStops = (): Promise => - AXIOS.get(ENDPOINTS.GET_STOPS).then((data) => data.data); + AXIOS.get(ENDPOINTS.GET_STOPS).then((data) => data.data as Stop[]); export const serverAlive = (): Promise => AXIOS.get(ENDPOINTS.GET_PING) @@ -74,3 +74,15 @@ export const serverAlive = (): Promise => export const createWebSocketConnection = () => new WebSocketApi(BASE_URLS.WEBSOCKET + ENDPOINTS.GET_WS); + +export const defaultErrorHandler = (err: unknown) => { + if (err instanceof AxiosError) { + if (err.response) console.error("Request Error", err.response); + return; + } + + if (err instanceof Error) { + console.error(err.message); + return; + } +}; diff --git a/liberica/src/lib/websockets.ts b/liberica/src/lib/websockets.ts index 8857422..a12713a 100644 --- a/liberica/src/lib/websockets.ts +++ b/liberica/src/lib/websockets.ts @@ -60,6 +60,7 @@ export class WebSocketApi { this.connection.onclose = (e) => this.metaHandlers["Disconnect"]?.(e); this.connection.onopen = () => this.metaHandlers["Connect"]?.(); this.connection.onmessage = (e) => { + if (typeof e.data !== "string") return; const res = this.parseMsg(e.data); if (res) this.handleMessage(res); }; diff --git a/liberica/src/main.tsx b/liberica/src/main.tsx index 95a173a..56b4d43 100644 --- a/liberica/src/main.tsx +++ b/liberica/src/main.tsx @@ -25,7 +25,11 @@ i18n.use(LanguageDetector) en: { translation: en_translation }, de: { translation: de_translation }, }, - }); + }) + .catch( + (e: unknown) => + e instanceof Error && console.error("i18n init error", e.message), + ); const rootElement = document.getElementById("root") as HTMLElement; ReactDOM.createRoot(rootElement).render( diff --git a/liberica/src/page/CreateTeam.tsx b/liberica/src/page/CreateTeam.tsx index 92785f0..0f10ba7 100644 --- a/liberica/src/page/CreateTeam.tsx +++ b/liberica/src/page/CreateTeam.tsx @@ -1,5 +1,5 @@ import { Button, DropDown, TextInput } from "components/InputElements"; -import { postCreateTeam } from "lib/api"; +import { defaultErrorHandler, postCreateTeam } from "lib/api"; import { TeamKind } from "lib/bindings"; import { FormEvent, useState } from "react"; import { useTranslation } from "react-i18next"; @@ -28,14 +28,9 @@ export function CreateTeam() { setLoading(true); postCreateTeam({ color, name, kind }) - .then(() => { - setLoading(false); - navigate("/"); - }) - .catch((err) => { - setLoading(false); - alert(t(err.response.data)); - }); + .then(() => navigate("/")) + .catch(defaultErrorHandler) + .finally(() => setLoading(false)); }; return ( diff --git a/liberica/src/page/Game.tsx b/liberica/src/page/Game.tsx index c8443ee..31e157a 100644 --- a/liberica/src/page/Game.tsx +++ b/liberica/src/page/Game.tsx @@ -12,21 +12,21 @@ export function Game() { const [ws, setWS] = useState(); const [gs, setGameState] = useState({ teams: [], trains: [] }); const [embarkedTrain, setEmbarkedTrain] = useState(); - const team: Team = useLocation().state; // this is how Home passes the team + const team = useLocation().state as Team | undefined; // this is how Home passes the team const { t } = useTranslation(); function disembark() { - if (team) { - setEmbarkedTrain(undefined); - ws?.send("DisembarkTrain"); - } + if (!team) return; + + setEmbarkedTrain(undefined); + ws?.send("DisembarkTrain"); } function embark(train: Train) { - if (team) { - setEmbarkedTrain(train); - ws?.send({ EmbarkTrain: { train_id: train.line_id } }); - } + if (!team) return; + + setEmbarkedTrain(train); + ws?.send({ EmbarkTrain: { train_id: train.line_id } }); } useEffect(() => { @@ -49,9 +49,8 @@ export function Game() { }, []); useEffect(() => { - if (team) { - ws?.send({ JoinTeam: { team_id: team.id } }); - } + if (!team) return; + ws?.send({ JoinTeam: { team_id: team.id } }); }, [ws, team]); useEffect(() => { diff --git a/liberica/src/page/Home.tsx b/liberica/src/page/Home.tsx index 4b15dc5..e4de2e3 100644 --- a/liberica/src/page/Home.tsx +++ b/liberica/src/page/Home.tsx @@ -13,14 +13,15 @@ export function Home() { const { t } = useTranslation(); useEffect(() => { - const updateTeams = () => getTeams().then(setTeams); + const updateTeams = () => void getTeams().then(setTeams); updateTeams(); + const interval = setInterval(updateTeams, 500); return () => clearInterval(interval); }, []); - const process = async () => { + const process = () => { if (selected === undefined) { return; } diff --git a/liberica/src/page/Replay.tsx b/liberica/src/page/Replay.tsx index 4dbbf70..d00255c 100644 --- a/liberica/src/page/Replay.tsx +++ b/liberica/src/page/Replay.tsx @@ -183,19 +183,18 @@ export function Replay() { if (file.size >= max_replay_size) { alert(t("ReplayTooBig")); } - file.text().then((data) => { - try { + file.text() + .then((data) => { const state = parseCSV(data); if (state.length > 0) { startReplay(state); } - } catch (e) { - alert(t("FailedParseReplay")); + }) + .catch(() => console.error( - `failed to parse replay file: ${e}`, - ); - } - }); + `failed to parse replay file`, + ), + ); } // invalid replay file reset();