refactor(server): extract device & system route groups (Refs #3502)#3527
Conversation
Continue the server.ts route extraction (issue #3502). Moves two cleanly-decoupled handler groups out of the inline monolith. device routes (routes/deviceRoutes.ts), mounted at '/': GET /device-config GET /device/backup POST /device/reboot POST /device/purge-nodedb system routes (routes/systemRoutes.ts), mounted at '/': GET /system/status GET /status GET /version/check POST /system/restart The Docker/version pure helpers (isRunningInDocker, compareVersions, checkDockerImageExists) plus serverStartTime move to a shared utils/systemInfo.ts, since the startup auto-upgrade scheduler (checkForAutoUpgrade) still references compareVersions/checkDockerImageExists. The restart handler's server-lifecycle gracefulShutdown is injected via setSystemCallbacks() so the route module stays free of the HTTP-server ref. Handler bodies moved verbatim; middleware preserved. Orphaned deviceBackupService/backupFileService imports removed from server.ts. Inline apiRouter handlers: 98 -> 90. Adds routes/deviceRoutes.test.ts and rewrites routes/systemRoutes.test.ts as supertest coverage of the new modules. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Claude finished @Yeraze's task —— View job PR Review:
|
| Severity | Count |
|---|---|
| Bug (pre-existing, carried verbatim) | 1 (singleton meshtasticManager in /status) |
| Test robustness | 2 (cache ordering, null backup path) |
| Style / minor | 2 (any type, no token cache) |
The core refactor is clean and the setSystemCallbacks injection pattern is the right approach. The singleton meshtasticManager usage on the /status endpoint is the most notable issue — it predates this PR but now lives in an extracted module, making it more visible and worth addressing.
Summary
Continues the server.ts route-extraction effort tracked in #3502. This batch extracts two cleanly-decoupled handler groups; the remaining inline groups are genuinely coupled to server.ts-local state (see below) and were intentionally left.
Groups extracted
routes/deviceRoutes.ts(mounted verbatim at/):GET /device-configGET /device/backupPOST /device/rebootPOST /device/purge-nodedbAll resolve the per-source manager via
resolveSourceManagerand delegate to importable services (deviceBackupService,backupFileService,databaseService) — zero server.ts coupling.routes/systemRoutes.ts(mounted verbatim at/):GET /system/statusGET /statusGET /version/checkPOST /system/restartSupporting helper moves:
isRunningInDocker,compareVersions,checkDockerImageExists, andserverStartTimemoved to a sharedutils/systemInfo.ts. The startup auto-upgrade scheduler (checkForAutoUpgrade, still in server.ts) keeps usingcompareVersions/checkDockerImageExistsvia the new import.gracefulShutdown(server-lifecycle: closes the module-local HTTPserver+ managers) is injected into the route module viasetSystemCallbacks(), matching the existingsetSettingsCallbackspattern — the route module never references the HTTP server.Handler bodies were moved verbatim; auth/validation middleware preserved identically. Orphaned
deviceBackupService/backupFileServiceimports removed from server.ts.Inline handler count
apiRouter.*handlersTests
routes/deviceRoutes.test.ts(config/backup/reboot/purge happy + error paths).routes/systemRoutes.test.tsas supertest coverage (status/version-check/restart incl. the gracefulShutdown callback and the module-level version-check cache ordering).tscclean. ESLint clean on new files.Remaining groups — too coupled to extract cleanly (left intentionally)
/channels(11) — large mixed-concern group (CRUD + import/export + decode/encode-url + MeshCore push). The 3 channel-move helpers (detectChannelMoves/snapshotChannelsBeforeChange/migrateMessagesIfChannelsMoved) are self-contained, but the handlers also reach intomeshcoreManagerRegistry,resolveSourceManager, and message-transform logic. Extractable but warrants its own dedicated PR for reviewability, not a "clean small batch."/nodes(17) — depends ongetEffectivePosition+ node-enrichment closures over server.ts state./admin(17) — session-passkey / admin-command state held in server.ts./config(15) — config-marshalling registry +resolveSourceConnectionConfig./settings/*(scheduler routes) — coupled to per-source scheduler state; the existingsettingsRoutes.tscallback-injection surface would need significant expansion./messages/send,/poll— manager/connection state./debug/ip— app/env locals.🤖 Generated with Claude Code