Skip to content

chore: migrate to eslint 9 flat config and format the codebase - #219

Closed
edospadoni wants to merge 1 commit into
mainfrom
chore/eslint9-flat-config-v2
Closed

edospadoni wants to merge 1 commit into
mainfrom
chore/eslint9-flat-config-v2

Conversation

@edospadoni

Copy link
Copy Markdown
Member

Rifà #215 partendo da main aggiornato, e nel farlo sblocca anche #205 e #206.

Closes #205
Closes #206

Il problema

ESLint era completamente rotto su main: .eslintrc.cjs estendeva react-app e react-app/jest, ma eslint-config-react-app non è mai stato installato. npm run lint falliva prima ancora di analizzare un file:

ESLint couldn't find the config "react-app" to extend from.

Per questo nessuno vedeva più né errori né problemi di formattazione.

La scelta

Invece di rattoppare la configurazione eslintrc su eslint 8, ho migrato a eslint 9 + flat config. Questo risolve la #215 e contemporaneamente sblocca le due major di Renovate ferme sul peer eslint >= 9, che era esattamente la domanda aperta:

Pacchetto Da A
eslint ^8.56.0 ^9.39.5
@electron-toolkit/eslint-config-ts ^1.0.1 ^3.1.0 (#206)
@electron-toolkit/eslint-config-prettier ^2.0.0 ^3.0.0 (#205)
eslint-plugin-react ^7.33.2 ^7.37.5 (supporto flat config)
eslint-plugin-react-hooks — ^5.2.0 (era referenziato ma mai installato)

.eslintrc.cjs e .eslintignore sono sostituiti da eslint.config.mjs.

Scelte di configurazione

Partivo da 190 errori e 3485 warning. Tre decisioni non ovvie:

  • Regole React limitate a src/renderer/**. rules-of-hooks segnalava 4 violazioni in AccountController, una classe del main process: useNethVoiceAPI e useLogin sono funzioni normali che si chiamano use*, non hook. Restringere lo scope è più corretto che spegnere la regola.
  • camelcase disattivata. Tutti e 41 i report erano identificatori snake_case vincolati dal contratto con il backend (speeddial_num, shared_groups, dst_cnam) o token del tema (extra_large, full_w). Non sono rinominabili.
  • react/prop-types disattivata, TypeScript già controlla le props.

Due trappole incontrate

Le segnalo perché non erano evidenti e sarebbero passate inosservate:

1. spaced-comment --fix distrugge le direttive triple-slash. Trasformava /// <reference types="vite/client" /> in // / <reference ... />, annullando la direttiva. Conseguenza: tutti gli import .svg smettevano di risolvere, perché le dichiarazioni le fornisce vite/client. Risolto con markers: ['/'] nella configurazione della regola.

2. Prettier può spostare un @ts-ignore lontano dall'errore che sopprime. In store.ts la direttiva copriva una riga che conteneva l'intera espressione; riformattando, la riga è stata spezzata in due e la soppressione è finita sulla riga sbagliata, facendo riemergere un errore di tipo zustand. Spostata accanto all'argomento corretto.

Correzioni oltre la formattazione

  • useNethVoiceAPI.ts: rimosso l'executor async ridondante attorno a logout. Il corpo risolveva già incondizionatamente in finally, quindi il comportamento è identico e non si perde nessun percorso di rejection.
  • logger.ts: il tipo Function sostituito da una firma esplicita.
  • main.ts, Modal/index.tsx: import duplicati uniti.
  • AboutModule.tsx: rimosso il pattern di destructuring vuoto.
  • usePresenceService.ts: rimosso un blocco finally vuoto.
  • ipcEvents.ts: documentato il catch volutamente silenzioso nel percorso di drag.

Verifica

  • npm run lint: 0 errori, 336 warning (nessuno bloccante: no-explicit-any, no-unused-vars, exhaustive-deps).
  • npm run typecheck e npm run build: verdi.
  • Il fix della fix: better error management #197 su ipcEvents.ts è sopravvissuto alla riformattazione (verificato).
  • Le 11 soppressioni @ts-ignore/@ts-expect-error sono le stesse di main, nessuna persa per spostamento.

Fuori scope

Prettier segnala altri 14 file non coperti da eslint (workflow YAML, README.md, template di issue, renovate.json, index.html, index.css). Li ho lasciati fuori per non aggiungere rumore a un diff già di 140 file: npm run format li toccherebbe, ed è una condizione preesistente.

ESLint was entirely broken on main: .eslintrc.cjs extended 'react-app'
and 'react-app/jest' while eslint-config-react-app was never installed,
so 'npm run lint' failed before linting a single file.

Rather than repair the eslintrc setup on eslint 8, this migrates to
eslint 9 flat config, which also unblocks the two Renovate majors that
were stuck on the 'eslint >= 9' peer requirement:

- eslint ^8.56.0 -> ^9.39.5
- @electron-toolkit/eslint-config-ts ^1.0.1 -> ^3.1.0 (#206)
- @electron-toolkit/eslint-config-prettier ^2.0.0 -> ^3.0.0 (#205)
- eslint-plugin-react ^7.33.2 -> ^7.37.5 (flat config support)
- eslint-plugin-react-hooks ^5.2.0 (was referenced, never installed)

.eslintrc.cjs and .eslintignore are replaced by eslint.config.mjs.

Config decisions:

- React and react-hooks rules are scoped to src/renderer/**. The main
  process has plain functions named use* (useNethVoiceAPI, useLogin)
  that rules-of-hooks reported as hook violations in AccountController.
- camelcase is off. Every one of its 41 reports was a snake_case field
  fixed by the backend API contract (speeddial_num, shared_groups,
  dst_cnam) or a theme token (extra_large, full_w).
- react/prop-types is off, since TypeScript already checks props.
- spaced-comment carries markers: ['/'] so --fix cannot mangle
  TypeScript triple-slash directives into '// / <reference ... />',
  which silently broke the vite/client types for .svg imports.

Beyond formatting, these lint errors needed real fixes:

- useNethVoiceAPI.ts: drop the redundant async Promise executor around
  logout; the body already resolved unconditionally, so behaviour is
  unchanged and no rejection path is lost.
- logger.ts: replace the unsafe Function type with an explicit signature.
- main.ts, Modal/index.tsx: merge duplicate imports.
- AboutModule.tsx: drop the empty destructuring pattern.
- usePresenceService.ts: drop an empty finally block.
- ipcEvents.ts: document the intentionally silent catch in the drag path.
- store.ts: move a // @ts-ignore next to the expression it suppresses.
  Reformatting split the statement it used to cover onto two lines,
  which silently un-suppressed the error.

'npm run lint' now reports 0 errors and 336 warnings. typecheck and
build are green.

Supersedes #215.
@github-actions

Copy link
Copy Markdown

Automatic builds from https://github.com/NethServer/nethlink/actions/runs/35341740808.
Commit: 27d8446

Name Platform Link
win-app.exe Windows (x64) Link
macos-app-x64.dmg MacOS (x64) Link
macos-app-arm64.dmg MacOS (arm64) Link
linux-app.AppImage Linux (x64) Link

@edospadoni

Copy link
Copy Markdown
Member Author

Sostituita da una PR rigenerata su main aggiornato, dopo il merge di #192 e #213.

@edospadoni edospadoni closed this Sep 18, 2026
@edospadoni
edospadoni deleted the chore/eslint9-flat-config-v2 branch September 18, 2026 12:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant