refactor: upgrade ESLint 9→10 and simplify React lint toolchain

- Upgrade eslint and @eslint/js to v10
- Replace eslint-plugin-react-x + eslint-plugin-react-dom + eslint-plugin-react-hooks
  with unified @eslint-react/eslint-plugin
- Raise dev Node.js requirement to ^22.13.0 || >=24 (runtime packages unaffected)
- Add .npmrc with engine-strict=true
- Move all @eslint-react rule overrides to eslint.config.js,
  eliminating plugin-specific inline eslint-disable comments
- Fix real issues caught by new rules: useless assignments,
  leaked setTimeout, ref naming, useState setter naming
This commit is contained in:
Simon
2026-04-08 20:31:31 +08:00
parent a43e653a74
commit 4f80ec1459
17 changed files with 1649 additions and 1687 deletions

View File

@@ -56,7 +56,7 @@ export class RemotePageController {
}
async getBrowserState(): Promise<BrowserState> {
let browserState = {} as BrowserState
let browserState: BrowserState
debug('getBrowserState', this.currentTabId)
const currentUrl = await this.getCurrentUrl()

View File

@@ -49,7 +49,9 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
const [showToken, setShowToken] = useState(false)
const [showApiKey, setShowApiKey] = useState(false)
useEffect(() => {
const [prevConfig, setPrevConfig] = useState(config)
if (prevConfig !== config) {
setPrevConfig(config)
setBaseURL(config?.baseURL || DEMO_BASE_URL)
setModel(config?.model || DEMO_MODEL)
setApiKey(config?.apiKey)
@@ -59,7 +61,7 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
setExperimentalLlmsTxt(config?.experimentalLlmsTxt ?? false)
setExperimentalIncludeAllTabs(config?.experimentalIncludeAllTabs ?? false)
setDisableNamedToolChoice(config?.disableNamedToolChoice ?? false)
}, [config])
}
// Poll for user auth token every second until found
useEffect(() => {

View File

@@ -71,7 +71,6 @@ export function HistoryDetail({
{/* Events (read-only) */}
<div className="flex-1 overflow-y-auto p-3 space-y-2">
{session.history.map((event, index) => (
// eslint-disable-next-line react-x/no-array-index-key
<EventCard key={index} event={event} />
))}
</div>

View File

@@ -34,7 +34,6 @@ export function HistoryList({
}, [])
useEffect(() => {
// eslint-disable-next-line react-hooks/set-state-in-effect
load()
}, [load])

View File

@@ -133,7 +133,6 @@ export default function App() {
)}
{history.map((event, index) => (
// eslint-disable-next-line react-x/no-array-index-key
<EventCard key={index} event={event} />
))}

View File

@@ -206,9 +206,9 @@ export function useHubWs(
const [wsState, setWsState] = useState<HubWsState>(() => (wsPort ? 'connecting' : 'disconnected'))
const hubWsRef = useRef<HubWs | null>(null)
const latest = useRef({ execute, stop, configure, config })
const latestRef = useRef({ execute, stop, configure, config })
useEffect(() => {
latest.current = { execute, stop, configure, config }
latestRef.current = { execute, stop, configure, config }
})
useEffect(() => {
@@ -218,14 +218,14 @@ export function useHubWs(
Number(wsPort),
{
onExecute: async (task, incomingConfig) => {
const { execute, configure, config } = latest.current
const { execute, configure, config } = latestRef.current
if (incomingConfig) {
await configure({ ...config, ...incomingConfig } as ExtConfig)
}
const result = await execute(task)
return { success: result.success, data: result.data }
},
onStop: () => latest.current.stop(),
onStop: () => latestRef.current.stop(),
},
setWsState
)

View File

@@ -178,7 +178,6 @@ export default function App() {
{showEmptyState && <EmptyState />}
{history.map((event, index) => (
// eslint-disable-next-line react-x/no-array-index-key
<EventCard key={index} event={event} />
))}