From cbcc0a11d203b9774f79293919730f9f0fe0bc91 Mon Sep 17 00:00:00 2001 From: Webber Date: Sun, 8 Feb 2026 02:25:16 +0100 Subject: [PATCH 1/2] ci: add checks workflow for frontend and Rust Add a lightweight checks workflow that runs on PRs and pushes to main: Frontend: - TypeScript typecheck (tsc --noEmit) - oxlint linting - vitest tests Rust: - cargo fmt --check - cargo clippy with deny warnings - cargo check Also adds oxlint and vitest as dev dependencies with corresponding npm scripts, and applies cargo fmt to existing Rust source files. --- .github/workflows/checks.yml | 69 +++++++ package.json | 12 +- src-tauri/src/auth.rs | 16 +- src-tauri/src/settings.rs | 20 +- yarn.lock | 370 ++++++++++++++++++++++++++++++++++- 5 files changed, 467 insertions(+), 20 deletions(-) create mode 100644 .github/workflows/checks.yml diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml new file mode 100644 index 0000000..3929048 --- /dev/null +++ b/.github/workflows/checks.yml @@ -0,0 +1,69 @@ +name: Checks + +on: + pull_request: + push: + branches: + - main + +jobs: + frontend: + name: Frontend checks + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - run: corepack enable && corepack install + + - uses: actions/setup-node@v4 + with: + node-version-file: package.json + cache: yarn + + - run: yarn install --frozen-lockfile --immutable + + - name: Typecheck + run: yarn typecheck + + - name: Lint + run: yarn lint + + - name: Test + run: yarn test + + rust: + name: Rust checks + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf xdg-utils + + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy, rustfmt + + - uses: swatinem/rust-cache@v2 + with: + workspaces: './src-tauri -> target' + + - run: corepack enable && corepack install + + - uses: actions/setup-node@v4 + with: + node-version-file: package.json + cache: yarn + + - run: yarn install --frozen-lockfile --immutable + + - name: Format + run: yarn rust:fmt + + - name: Clippy + run: yarn rust:clippy + + - name: Check + run: yarn rust:check diff --git a/package.json b/package.json index 23b6841..d5b3883 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,13 @@ "dev": "vite", "build": "tsc && vite build", "preview": "vite preview", - "tauri": "tauri" + "tauri": "tauri", + "typecheck": "tsc --noEmit", + "lint": "oxlint src --deny-warnings", + "test": "vitest run --passWithNoTests", + "rust:check": "cargo check --manifest-path src-tauri/Cargo.toml", + "rust:clippy": "cargo clippy --manifest-path src-tauri/Cargo.toml -- -D warnings", + "rust:fmt": "cargo fmt --manifest-path src-tauri/Cargo.toml --check" }, "dependencies": { "@tauri-apps/api": "^2", @@ -23,9 +29,11 @@ "@types/react": "^19.1.8", "@types/react-dom": "^19.1.6", "@vitejs/plugin-react": "^4.6.0", + "oxlint": "^1.43.0", "tailwindcss": "^4", "typescript": "~5.8.3", - "vite": "^7.0.4" + "vite": "^7.0.4", + "vitest": "^4.0.18" }, "volta": { "node": "22.17.1", diff --git a/src-tauri/src/auth.rs b/src-tauri/src/auth.rs index 22f16fc..af02b46 100644 --- a/src-tauri/src/auth.rs +++ b/src-tauri/src/auth.rs @@ -240,8 +240,7 @@ pub async fn auth_device_poll( expires_in: u64, state: tauri::State<'_, Arc>, ) -> Result { - let deadline = - tokio::time::Instant::now() + tokio::time::Duration::from_secs(expires_in); + let deadline = tokio::time::Instant::now() + tokio::time::Duration::from_secs(expires_in); let poll_interval = tokio::time::Duration::from_secs(interval.max(5)); loop { @@ -259,18 +258,14 @@ pub async fn auth_device_poll( ("client_id", CLIENT_ID), ("scopes", SCOPES), ("device_code", device_code.as_str()), - ( - "grant_type", - "urn:ietf:params:oauth:grant-type:device_code", - ), + ("grant_type", "urn:ietf:params:oauth:grant-type:device_code"), ]) .send() .await .map_err(|e| e.to_string())?; if resp.status().is_success() { - let tokens: TwitchTokenResponse = - resp.json().await.map_err(|e| e.to_string())?; + let tokens: TwitchTokenResponse = resp.json().await.map_err(|e| e.to_string())?; info!("[auth] device flow got tokens, validating…"); let username = validate_token(&state.http, &tokens.access_token).await?; let now = chrono::Utc::now().timestamp(); @@ -340,10 +335,7 @@ pub async fn auth_logout(state: tauri::State<'_, Arc>) -> Result<(), let _ = state .http .post("https://id.twitch.tv/oauth2/revoke") - .form(&[ - ("client_id", CLIENT_ID), - ("token", &data.access_token), - ]) + .form(&[("client_id", CLIENT_ID), ("token", &data.access_token)]) .send() .await; } diff --git a/src-tauri/src/settings.rs b/src-tauri/src/settings.rs index 6a737f1..c7f9c60 100644 --- a/src-tauri/src/settings.rs +++ b/src-tauri/src/settings.rs @@ -54,12 +54,18 @@ pub fn write_settings(data: Value, state: tauri::State<'_, SettingsState>) -> Re pub fn read_chat_history(state: tauri::State<'_, SettingsState>) -> Result, String> { match std::fs::read_to_string(&state.chat_history_path) { Ok(json) => { - info!("[chat-history] loaded from {}", state.chat_history_path.display()); + info!( + "[chat-history] loaded from {}", + state.chat_history_path.display() + ); let data: Value = serde_json::from_str(&json).map_err(|e| e.to_string())?; Ok(Some(data)) } Err(e) if e.kind() == std::io::ErrorKind::NotFound => { - info!("[chat-history] no file at {}", state.chat_history_path.display()); + info!( + "[chat-history] no file at {}", + state.chat_history_path.display() + ); Ok(None) } Err(e) => { @@ -70,7 +76,10 @@ pub fn read_chat_history(state: tauri::State<'_, SettingsState>) -> Result) -> Result<(), String> { +pub fn write_chat_history( + data: Value, + state: tauri::State<'_, SettingsState>, +) -> Result<(), String> { if let Some(parent) = state.chat_history_path.parent() { std::fs::create_dir_all(parent).map_err(|e| e.to_string())?; } @@ -79,6 +88,9 @@ pub fn write_chat_history(data: Value, state: tauri::State<'_, SettingsState>) - error!("[chat-history] write error: {e}"); e.to_string() })?; - info!("[chat-history] saved to {}", state.chat_history_path.display()); + info!( + "[chat-history] saved to {}", + state.chat_history_path.display() + ); Ok(()) } diff --git a/yarn.lock b/yarn.lock index 1784201..7b146dc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -521,6 +521,62 @@ __metadata: languageName: node linkType: hard +"@oxlint/darwin-arm64@npm:1.43.0": + version: 1.43.0 + resolution: "@oxlint/darwin-arm64@npm:1.43.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@oxlint/darwin-x64@npm:1.43.0": + version: 1.43.0 + resolution: "@oxlint/darwin-x64@npm:1.43.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@oxlint/linux-arm64-gnu@npm:1.43.0": + version: 1.43.0 + resolution: "@oxlint/linux-arm64-gnu@npm:1.43.0" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@oxlint/linux-arm64-musl@npm:1.43.0": + version: 1.43.0 + resolution: "@oxlint/linux-arm64-musl@npm:1.43.0" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@oxlint/linux-x64-gnu@npm:1.43.0": + version: 1.43.0 + resolution: "@oxlint/linux-x64-gnu@npm:1.43.0" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@oxlint/linux-x64-musl@npm:1.43.0": + version: 1.43.0 + resolution: "@oxlint/linux-x64-musl@npm:1.43.0" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@oxlint/win32-arm64@npm:1.43.0": + version: 1.43.0 + resolution: "@oxlint/win32-arm64@npm:1.43.0" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@oxlint/win32-x64@npm:1.43.0": + version: 1.43.0 + resolution: "@oxlint/win32-x64@npm:1.43.0" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@rolldown/pluginutils@npm:1.0.0-beta.27": version: 1.0.0-beta.27 resolution: "@rolldown/pluginutils@npm:1.0.0-beta.27" @@ -703,6 +759,13 @@ __metadata: languageName: node linkType: hard +"@standard-schema/spec@npm:^1.0.0": + version: 1.1.0 + resolution: "@standard-schema/spec@npm:1.1.0" + checksum: 10/a209615c9e8b2ea535d7db0a5f6aa0f962fd4ab73ee86a46c100fb78116964af1f55a27c1794d4801e534a196794223daa25ff5135021e03c7828aa3d95e1763 + languageName: node + linkType: hard + "@tailwindcss/node@npm:4.1.18": version: 4.1.18 resolution: "@tailwindcss/node@npm:4.1.18" @@ -1063,7 +1126,24 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:1.0.8": +"@types/chai@npm:^5.2.2": + version: 5.2.3 + resolution: "@types/chai@npm:5.2.3" + dependencies: + "@types/deep-eql": "npm:*" + assertion-error: "npm:^2.0.1" + checksum: 10/e79947307dc235953622e65f83d2683835212357ca261389116ab90bed369ac862ba28b146b4fed08b503ae1e1a12cb93ce783f24bb8d562950469f4320e1c7c + languageName: node + linkType: hard + +"@types/deep-eql@npm:*": + version: 4.0.2 + resolution: "@types/deep-eql@npm:4.0.2" + checksum: 10/249a27b0bb22f6aa28461db56afa21ec044fa0e303221a62dff81831b20c8530502175f1a49060f7099e7be06181078548ac47c668de79ff9880241968d43d0c + languageName: node + linkType: hard + +"@types/estree@npm:1.0.8, @types/estree@npm:^1.0.0": version: 1.0.8 resolution: "@types/estree@npm:1.0.8" checksum: 10/25a4c16a6752538ffde2826c2cc0c6491d90e69cd6187bef4a006dd2c3c45469f049e643d7e516c515f21484dc3d48fd5c870be158a5beb72f5baf3dc43e4099 @@ -1104,6 +1184,86 @@ __metadata: languageName: node linkType: hard +"@vitest/expect@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/expect@npm:4.0.18" + dependencies: + "@standard-schema/spec": "npm:^1.0.0" + "@types/chai": "npm:^5.2.2" + "@vitest/spy": "npm:4.0.18" + "@vitest/utils": "npm:4.0.18" + chai: "npm:^6.2.1" + tinyrainbow: "npm:^3.0.3" + checksum: 10/2115bff1bbcad460ce72032022e4dbcf8572c4b0fe07ca60f5644a8d96dd0dfa112986b5a1a5c5705f4548119b3b829c45d1de0838879211e0d6bb276b4ece73 + languageName: node + linkType: hard + +"@vitest/mocker@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/mocker@npm:4.0.18" + dependencies: + "@vitest/spy": "npm:4.0.18" + estree-walker: "npm:^3.0.3" + magic-string: "npm:^0.30.21" + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + checksum: 10/46f584a4c1180dfb513137bc8db6e2e3b53e141adfe964307297e98321652d86a3f2a52d80cda1f810205bd5fdcab789bb8b52a532e68f175ef1e20be398218d + languageName: node + linkType: hard + +"@vitest/pretty-format@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/pretty-format@npm:4.0.18" + dependencies: + tinyrainbow: "npm:^3.0.3" + checksum: 10/4cafc7c9853097345bd94e8761bf47c2c04e00d366ac56d79928182787ff83c512c96f1dc2ce9b6aeed4d3a8c23ce12254da203783108d3c096bc398eed2a62d + languageName: node + linkType: hard + +"@vitest/runner@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/runner@npm:4.0.18" + dependencies: + "@vitest/utils": "npm:4.0.18" + pathe: "npm:^2.0.3" + checksum: 10/d7deebf086d7e084f449733ecea6c9c81737a18aafece318cbe7500e45debea00fa9dbf9315fd38aa88550dd5240a791b885ac71665f89b154d71a6c63da5836 + languageName: node + linkType: hard + +"@vitest/snapshot@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/snapshot@npm:4.0.18" + dependencies: + "@vitest/pretty-format": "npm:4.0.18" + magic-string: "npm:^0.30.21" + pathe: "npm:^2.0.3" + checksum: 10/50aa5fb7fca45c499c145cc2f20e53b8afb0990b53ff4a4e6447dd6f147437edc5316f22e2d82119e154c3cf7c59d44898e7b2faf7ba614ac1051cbe4d662a77 + languageName: node + linkType: hard + +"@vitest/spy@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/spy@npm:4.0.18" + checksum: 10/f7b1618ae13790105771dd2a8c973c63c018366fcc69b50f15ce5d12f9ac552efd3c1e6e5ae4ebdb6023d0b8d8f31fef2a0b1b77334284928db45c80c63de456 + languageName: node + linkType: hard + +"@vitest/utils@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/utils@npm:4.0.18" + dependencies: + "@vitest/pretty-format": "npm:4.0.18" + tinyrainbow: "npm:^3.0.3" + checksum: 10/e8b2ad7bc35b2bc5590f9dc1d1a67644755da416b47ab7099a6f26792903fa0aacb81e6ba99f0f03858d9d3a1d76eeba65150a1a0849690a40817424e749c367 + languageName: node + linkType: hard + "abbrev@npm:^4.0.0": version: 4.0.0 resolution: "abbrev@npm:4.0.0" @@ -1118,6 +1278,13 @@ __metadata: languageName: node linkType: hard +"assertion-error@npm:^2.0.1": + version: 2.0.1 + resolution: "assertion-error@npm:2.0.1" + checksum: 10/a0789dd882211b87116e81e2648ccb7f60340b34f19877dd020b39ebb4714e475eb943e14ba3e22201c221ef6645b7bfe10297e76b6ac95b48a9898c1211ce66 + languageName: node + linkType: hard + "baseline-browser-mapping@npm:^2.9.0": version: 2.9.19 resolution: "baseline-browser-mapping@npm:2.9.19" @@ -1168,6 +1335,13 @@ __metadata: languageName: node linkType: hard +"chai@npm:^6.2.1": + version: 6.2.2 + resolution: "chai@npm:6.2.2" + checksum: 10/13cda42cc40aa46da04a41cf7e5c61df6b6ae0b4e8a8c8b40e04d6947e4d7951377ea8c14f9fa7fe5aaa9e8bd9ba414f11288dc958d4cee6f5221b9436f2778f + languageName: node + linkType: hard + "chownr@npm:^3.0.0": version: 3.0.0 resolution: "chownr@npm:3.0.0" @@ -1248,6 +1422,13 @@ __metadata: languageName: node linkType: hard +"es-module-lexer@npm:^1.7.0": + version: 1.7.0 + resolution: "es-module-lexer@npm:1.7.0" + checksum: 10/b6f3e576a3fed4d82b0d0ad4bbf6b3a5ad694d2e7ce8c4a069560da3db6399381eaba703616a182b16dde50ce998af64e07dcf49f2ae48153b9e07be3f107087 + languageName: node + linkType: hard + "esbuild@npm:^0.27.0": version: 0.27.3 resolution: "esbuild@npm:0.27.3" @@ -1344,6 +1525,22 @@ __metadata: languageName: node linkType: hard +"estree-walker@npm:^3.0.3": + version: 3.0.3 + resolution: "estree-walker@npm:3.0.3" + dependencies: + "@types/estree": "npm:^1.0.0" + checksum: 10/a65728d5727b71de172c5df323385755a16c0fdab8234dc756c3854cfee343261ddfbb72a809a5660fac8c75d960bb3e21aa898c2d7e9b19bb298482ca58a3af + languageName: node + linkType: hard + +"expect-type@npm:^1.2.2": + version: 1.3.0 + resolution: "expect-type@npm:1.3.0" + checksum: 10/a5fada3d0c621649261f886e7d93e6bf80ce26d8a86e5d517e38301b8baec8450ab2cb94ba6e7a0a6bf2fc9ee55f54e1b06938ef1efa52ddcfeffbfa01acbbcc + languageName: node + linkType: hard + "exponential-backoff@npm:^3.1.1": version: 3.1.3 resolution: "exponential-backoff@npm:3.1.3" @@ -1817,6 +2014,53 @@ __metadata: languageName: node linkType: hard +"obug@npm:^2.1.1": + version: 2.1.1 + resolution: "obug@npm:2.1.1" + checksum: 10/bdcf9213361786688019345f3452b95a1dc73710e4b403c82a1994b98bad6abc31b26cb72a482128c5fd53ea9daf6fbb7d0e0e7b2b7e9c8be6d779deeccee07f + languageName: node + linkType: hard + +"oxlint@npm:^1.43.0": + version: 1.43.0 + resolution: "oxlint@npm:1.43.0" + dependencies: + "@oxlint/darwin-arm64": "npm:1.43.0" + "@oxlint/darwin-x64": "npm:1.43.0" + "@oxlint/linux-arm64-gnu": "npm:1.43.0" + "@oxlint/linux-arm64-musl": "npm:1.43.0" + "@oxlint/linux-x64-gnu": "npm:1.43.0" + "@oxlint/linux-x64-musl": "npm:1.43.0" + "@oxlint/win32-arm64": "npm:1.43.0" + "@oxlint/win32-x64": "npm:1.43.0" + peerDependencies: + oxlint-tsgolint: ">=0.11.2" + dependenciesMeta: + "@oxlint/darwin-arm64": + optional: true + "@oxlint/darwin-x64": + optional: true + "@oxlint/linux-arm64-gnu": + optional: true + "@oxlint/linux-arm64-musl": + optional: true + "@oxlint/linux-x64-gnu": + optional: true + "@oxlint/linux-x64-musl": + optional: true + "@oxlint/win32-arm64": + optional: true + "@oxlint/win32-x64": + optional: true + peerDependenciesMeta: + oxlint-tsgolint: + optional: true + bin: + oxlint: bin/oxlint + checksum: 10/179a01354cdfd79964155a0d5812fc26eca3bbd22e2860bb30b109a5ad8697289fff7eca2b5959d4171d440c9119a15ec6526340190f8a906ad692b699a242e8 + languageName: node + linkType: hard + "p-map@npm:^7.0.2": version: 7.0.4 resolution: "p-map@npm:7.0.4" @@ -1834,6 +2078,13 @@ __metadata: languageName: node linkType: hard +"pathe@npm:^2.0.3": + version: 2.0.3 + resolution: "pathe@npm:2.0.3" + checksum: 10/01e9a69928f39087d96e1751ce7d6d50da8c39abf9a12e0ac2389c42c83bc76f78c45a475bd9026a02e6a6f79be63acc75667df855862fe567d99a00a540d23d + languageName: node + linkType: hard + "picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" @@ -2030,6 +2281,13 @@ __metadata: languageName: node linkType: hard +"siginfo@npm:^2.0.0": + version: 2.0.0 + resolution: "siginfo@npm:2.0.0" + checksum: 10/e93ff66c6531a079af8fb217240df01f980155b5dc408d2d7bebc398dd284e383eb318153bf8acd4db3c4fe799aa5b9a641e38b0ba3b1975700b1c89547ea4e7 + languageName: node + linkType: hard + "smart-buffer@npm:^4.2.0": version: 4.2.0 resolution: "smart-buffer@npm:4.2.0" @@ -2074,6 +2332,20 @@ __metadata: languageName: node linkType: hard +"stackback@npm:0.0.2": + version: 0.0.2 + resolution: "stackback@npm:0.0.2" + checksum: 10/2d4dc4e64e2db796de4a3c856d5943daccdfa3dd092e452a1ce059c81e9a9c29e0b9badba91b43ef0d5ff5c04ee62feb3bcc559a804e16faf447bac2d883aa99 + languageName: node + linkType: hard + +"std-env@npm:^3.10.0": + version: 3.10.0 + resolution: "std-env@npm:3.10.0" + checksum: 10/19c9cda4f370b1ffae2b8b08c72167d8c3e5cfa972aaf5c6873f85d0ed2faa729407f5abb194dc33380708c00315002febb6f1e1b484736bfcf9361ad366013a + languageName: node + linkType: hard + "streamer@workspace:.": version: 0.0.0-use.local resolution: "streamer@workspace:." @@ -2086,11 +2358,13 @@ __metadata: "@types/react": "npm:^19.1.8" "@types/react-dom": "npm:^19.1.6" "@vitejs/plugin-react": "npm:^4.6.0" + oxlint: "npm:^1.43.0" react: "npm:^19.1.0" react-dom: "npm:^19.1.0" tailwindcss: "npm:^4" typescript: "npm:~5.8.3" vite: "npm:^7.0.4" + vitest: "npm:^4.0.18" zustand: "npm:^5" languageName: unknown linkType: soft @@ -2122,6 +2396,20 @@ __metadata: languageName: node linkType: hard +"tinybench@npm:^2.9.0": + version: 2.9.0 + resolution: "tinybench@npm:2.9.0" + checksum: 10/cfa1e1418e91289219501703c4693c70708c91ffb7f040fd318d24aef419fb5a43e0c0160df9471499191968b2451d8da7f8087b08c3133c251c40d24aced06c + languageName: node + linkType: hard + +"tinyexec@npm:^1.0.2": + version: 1.0.2 + resolution: "tinyexec@npm:1.0.2" + checksum: 10/cb709ed4240e873d3816e67f851d445f5676e0ae3a52931a60ff571d93d388da09108c8057b62351766133ee05ff3159dd56c3a0fbd39a5933c6639ce8771405 + languageName: node + linkType: hard + "tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.15": version: 0.2.15 resolution: "tinyglobby@npm:0.2.15" @@ -2132,6 +2420,13 @@ __metadata: languageName: node linkType: hard +"tinyrainbow@npm:^3.0.3": + version: 3.0.3 + resolution: "tinyrainbow@npm:3.0.3" + checksum: 10/169cc63c15e1378674180f3207c82c05bfa58fc79992e48792e8d97b4b759012f48e95297900ede24a81f0087cf329a0d85bb81109739eacf03c650127b3f6c1 + languageName: node + linkType: hard + "tslib@npm:^2.4.0": version: 2.8.1 resolution: "tslib@npm:2.8.1" @@ -2191,7 +2486,7 @@ __metadata: languageName: node linkType: hard -"vite@npm:^7.0.4": +"vite@npm:^6.0.0 || ^7.0.0, vite@npm:^7.0.4": version: 7.3.1 resolution: "vite@npm:7.3.1" dependencies: @@ -2246,6 +2541,65 @@ __metadata: languageName: node linkType: hard +"vitest@npm:^4.0.18": + version: 4.0.18 + resolution: "vitest@npm:4.0.18" + dependencies: + "@vitest/expect": "npm:4.0.18" + "@vitest/mocker": "npm:4.0.18" + "@vitest/pretty-format": "npm:4.0.18" + "@vitest/runner": "npm:4.0.18" + "@vitest/snapshot": "npm:4.0.18" + "@vitest/spy": "npm:4.0.18" + "@vitest/utils": "npm:4.0.18" + es-module-lexer: "npm:^1.7.0" + expect-type: "npm:^1.2.2" + magic-string: "npm:^0.30.21" + obug: "npm:^2.1.1" + pathe: "npm:^2.0.3" + picomatch: "npm:^4.0.3" + std-env: "npm:^3.10.0" + tinybench: "npm:^2.9.0" + tinyexec: "npm:^1.0.2" + tinyglobby: "npm:^0.2.15" + tinyrainbow: "npm:^3.0.3" + vite: "npm:^6.0.0 || ^7.0.0" + why-is-node-running: "npm:^2.3.0" + peerDependencies: + "@edge-runtime/vm": "*" + "@opentelemetry/api": ^1.9.0 + "@types/node": ^20.0.0 || ^22.0.0 || >=24.0.0 + "@vitest/browser-playwright": 4.0.18 + "@vitest/browser-preview": 4.0.18 + "@vitest/browser-webdriverio": 4.0.18 + "@vitest/ui": 4.0.18 + happy-dom: "*" + jsdom: "*" + peerDependenciesMeta: + "@edge-runtime/vm": + optional: true + "@opentelemetry/api": + optional: true + "@types/node": + optional: true + "@vitest/browser-playwright": + optional: true + "@vitest/browser-preview": + optional: true + "@vitest/browser-webdriverio": + optional: true + "@vitest/ui": + optional: true + happy-dom: + optional: true + jsdom: + optional: true + bin: + vitest: vitest.mjs + checksum: 10/6c6464ebcf3af83546862896fd1b5f10cb6607261bffce39df60033a288b8c1687ae1dd20002b6e4997a7a05303376d1eb58ce20afe63be052529a4378a8c165 + languageName: node + linkType: hard + "which@npm:^6.0.0": version: 6.0.0 resolution: "which@npm:6.0.0" @@ -2257,6 +2611,18 @@ __metadata: languageName: node linkType: hard +"why-is-node-running@npm:^2.3.0": + version: 2.3.0 + resolution: "why-is-node-running@npm:2.3.0" + dependencies: + siginfo: "npm:^2.0.0" + stackback: "npm:0.0.2" + bin: + why-is-node-running: cli.js + checksum: 10/0de6e6cd8f2f94a8b5ca44e84cf1751eadcac3ebedcdc6e5fbbe6c8011904afcbc1a2777c53496ec02ced7b81f2e7eda61e76bf8262a8bc3ceaa1f6040508051 + languageName: node + linkType: hard + "yallist@npm:^3.0.2": version: 3.1.1 resolution: "yallist@npm:3.1.1" From a7604630e4bc719e59404b97cf94055660ebd317 Mon Sep 17 00:00:00 2001 From: Webber Date: Sun, 8 Feb 2026 02:36:53 +0100 Subject: [PATCH 2/2] fix: clippy warnings and add project agent rules - Add #[allow(unused_variables)] for cross-platform cfg-gated function - Rename POINT to Point to satisfy clippy upper_case_acronyms - Add AGENTS.md with Rust-specific rules for cfg-gated code - Add CLAUDE.md linking to AGENTS.md --- AGENTS.md | 6 ++++++ CLAUDE.md | 1 + src-tauri/src/lib.rs | 7 ++++--- 3 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 AGENTS.md create mode 100644 CLAUDE.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..2483eec --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,6 @@ +# Agents + +## Rust + +- When writing `#[cfg]`-gated code, proactively add `#[allow(unused_variables)]` if parameters are only used in some platform branches +- Always run `yarn rust:clippy` (not just `cargo check`) as part of local verification diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..73ac7d8 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +See: @AGENTS.md diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 3fa8a76..4ba7859 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -15,18 +15,19 @@ fn set_ignore_cursor(window: tauri::WebviewWindow, ignore: bool) -> Result<(), S } #[tauri::command] +#[allow(unused_variables)] fn get_cursor_position(window: tauri::WebviewWindow) -> Result<(f64, f64), String> { #[cfg(target_os = "windows")] { #[repr(C)] - struct POINT { + struct Point { x: i32, y: i32, } extern "system" { - fn GetCursorPos(lp_point: *mut POINT) -> i32; + fn GetCursorPos(lp_point: *mut Point) -> i32; } - let mut point = POINT { x: 0, y: 0 }; + let mut point = Point { x: 0, y: 0 }; if unsafe { GetCursorPos(&mut point) } == 0 { return Err("GetCursorPos failed".into()); }