Repository navigation
fix(web): handle the two unawaited Promises SonarQube flagged, and lint wwwroot locally - #144
Conversation
SonarQube's only open issues on develop were two javascript:S9383 findings
("Promises should not be left unhandled") in
apps/RustPlusApi.CredentialsWeb/wwwroot/app.js: the delegated paste handler's
submitPaste() call and the delegated copy button's copyText() call. Both
functions report their own failures next to the control that triggered them,
so the calls are now marked `void` with a comment saying where the failure
handling lives.
Nothing checked that file locally: the C# side fails the build through
SonarAnalyzer.CSharp, but the browser script had no analyzer behind it and
Sonar.yml only analyzes develop after the merge. The app directory now carries
a dev-only Node toolchain (package.json, eslint.config.mjs, tsconfig.json for
type-aware linting of plain JavaScript) whose `npm run lint` mirrors the rules
SonarQube applies: typescript-eslint's no-floating-promises (S9383) and
no-misused-promises configured as Sonar's S6544 is, plus eslint-plugin-sonarjs
recommended and ESLint recommended. Run before the fix it reported exactly
Sonar's two findings and nothing else.
The lint runs in a new CI.yml `lint-web` job on every push and PR, and in the
pre-push hook whenever a push touches the script or its lint setup. Dependabot
keeps the toolchain current. The csproj removes the three JSON files from
Content (the Web SDK was publishing them) and blocks Visual Studio's
TypeScript build from acting on tsconfig.json; .dockerignore drops
node_modules from the image build context.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ReSharper's cleanupcode exits 3 with "No items were found to cleanup" when every included file is a .csproj/.props/.targets, and the pre-push hook treated any non-zero exit as a formatting failure, so a push touching only project files (such as this branch's csproj change) was rejected with nothing to fix. Exit 3 now passes the check; every other non-zero code still blocks the push. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
An unresolved moderate issue remains in the Web project, where node_modules is not excluded from the SDK's recursive Content globs, causing local builds and publishes to pick up thousands of unintended files.
1 open issue
1 file not reviewed
apps/RustPlusApi.CredentialsWeb/package-lock.json: Generated file
What changed in this PR
This PR resolves the two outstanding SonarQube javascript:S9383 ("Promises should not be left unhandled") findings in the credentials web app's browser script, and, more substantially, closes the gap that let those smells reach develop undetected: the browser JavaScript previously had no analyzer behind it locally or in pre-merge CI. It fits into the repo's existing "fail fast locally and in CI" philosophy (ReSharper formatting hook, strict C# analyzers) by giving wwwroot/app.js an ESLint toolchain that mirrors SonarQube's JS rules.
Changes:
- Mark the two intentionally unawaited calls (
submitPaste(),copyText()) withvoidplus a justifying comment. - Add a dev-only Node lint toolchain (
package.json,package-lock.json,eslint.config.mjs,tsconfig.json) mirroring Sonar'sno-floating-promises/no-misused-promises, wired into a new CIlint-webjob, the pre-push hook, and a weekly Dependabot npm group. - Secondary fixes: pre-push hook now treats ReSharper exit code 3 ("No items to cleanup") as a pass; csproj stops the Web SDK from publishing the toolchain JSON files;
node_modulesadded to.dockerignore; docs updated.
| File | Description |
|---|---|
apps/RustPlusApi.CredentialsWeb/wwwroot/app.js |
Marks the two floating-promise calls with void and comments. |
apps/RustPlusApi.CredentialsWeb/eslint.config.mjs |
New flat ESLint config mirroring SonarQube JS rules via typescript-eslint. |
apps/RustPlusApi.CredentialsWeb/tsconfig.json |
Minimal TS program so ESLint can run type-aware rules over the JS. |
apps/RustPlusApi.CredentialsWeb/package.json / package-lock.json |
Pinned dev-only lint toolchain. |
apps/RustPlusApi.CredentialsWeb/RustPlusApi.CredentialsWeb.csproj |
Blocks TS build step; removes three toolchain JSON files from Content — but does not exclude node_modules from the SDK globs (see comment). |
.github/workflows/CI.yml |
Adds a lint-web job running the lint on push/PR. |
.githooks/pre-push |
Runs the web lint when the script/lint-setup changes; treats ReSharper exit 3 as a pass. |
.github/dependabot.yml |
Adds a weekly grouped npm update for the toolchain. |
.dockerignore |
Excludes node_modules from the Docker build context. |
CLAUDE.md, AGENTS.md, docs/development/formatting.md, docs/development/testing.md |
Document the new lint workflow. |
Review effort: Balanced
| <!-- The lint toolchain's files, not app content: the Web SDK globs every *.json beside the project | ||
| as Content and would otherwise publish them (and ship them in the Docker image). --> | ||
| <Content Remove="package.json;package-lock.json;tsconfig.json" /> |

Summary
SonarQube's only open issues on
developwere twojavascript:S9383findings ("Promises should not be left unhandled") inapps/RustPlusApi.CredentialsWeb/wwwroot/app.js: the delegated paste handler'ssubmitPaste()call and the delegated copy button'scopyText()call. Both functions report their own failures beside the control that triggered them, so the calls are now markedvoidwith a comment saying where the failure handling lives.Nothing checked that file locally: the C# side fails the build through SonarAnalyzer.CSharp, but the browser script had no analyzer behind it and
Sonar.ymlonly analyzesdevelopafter the merge. This PR adds the local guard so the same class of smell fails before the push.Changes
app.js: the two intentionally unawaited calls are markedvoid, each with a one-line justification.package.json,eslint.config.mjs,tsconfig.json):npm run lintmirrors SonarQube's JavaScript rules — typescript-eslint's type-awareno-floating-promises(S9383) andno-misused-promisesconfigured as Sonar's S6544 is (checksVoidReturnoff), pluseslint-plugin-sonarjsrecommended and ESLint recommended. Run before the fix it reported exactly Sonar's two findings and nothing else.lint-webjob runs the lint on every push and PR..csproj/.props/.targets, and the hook rejected that. Pre-existing ondevelop; exit 3 now passes.Content.TypeScriptCompileBlockedstops Visual Studio's TypeScript build acting ontsconfig.json.node_modulesadded to.dockerignore.docs/development/testing.md,docs/development/formatting.md,CLAUDE.md,AGENTS.md.Test plan
npm run lintin the app directory: clean after the fix, two S9383 findings before itdotnet build RustPlusApi.slnand the web app's 211 unit tests passdotnet publishof the web app no longer containspackage.json,package-lock.json,tsconfig.jsonlint-webCI job green on this PRdevelop🤖 Generated with Claude Code