Skip to content

Group the server's modules into domain folders - #84

Merged
firsttris merged 3 commits into
masterfrom
server-domains
Nov 4, 2026
Merged

firsttris merged 3 commits into
masterfrom
server-domains

Conversation

@firsttris

Copy link
Copy Markdown
Owner

apps/server/src had 45 modules side by side. This PR groups them into domain folders. Behaviour does not change: there are no code changes, only moves and the import paths that follow them.

New tree

apps/server/src/
  main.ts, bin.ts, bin-cli.ts   entry points (unchanged)
  __tests__/assert-error.ts     the one test helper every domain uses
  auth/            auth, passkeys, credentials (auth.json)
  config/          config (BASE_PATH, SNAPRAID_BIN), config-parser (config.json, snapraid.conf),
                   setup (setup wizard: mount candidates, create array), backup, maintenance-settings
  disks/           disk-check, disk-power, disk-removal, disk-replacement, spindown, parity-usage
  engine/          unchanged; plus __tests__/ with fake-engine.ts, engine-contract.ts and their tests
  executors/       unchanged
  http/            frontend (serves the built UI), websocket
  integrations/    array-snapshot, metrics (Prometheus), mcp, home-assistant, home-assistant-service (MQTT)
  notifications/   notifications (settings, SMTP/ntfy/webhook), notification-events
  parsers/         unchanged
  routes/          unchanged; plus __tests__/ with heal.test.ts and disk-management.test.ts (route tests)
  schedule/        scheduler
  smart/           smart-baseline, smart-history, smart-ignore, smart-selftest
  snapraid/        snapraid-runner, run-report, log-manager, status-cache, usage-history, recovery,
                   restore-ownership, duplicates
  system/          fs, command, atomic-write, app-files, version, docker, container-pause, demo

Decisions

  • Tests in a __tests__/ folder in each domain (smart/__tests__/smart-baseline.test.ts), the same way parsers/__tests__/ already works. bun test finds *.test.ts anywhere, so no config changes. A test still imports its own module as ../x.ts, the same as before. Only imports from other domains get one more ../. One src/__tests__/ mirroring the domains would have added a ../ to every import.
  • Home Assistant goes in integrations/, not notifications/. That is how the code uses it: home-assistant*.ts never touch notifications.ts. They are built from array-snapshot.ts and metrics.ts (ConfigMetrics), the same as the Prometheus metrics, and mcp.ts imports arrayState from home-assistant.ts. So these five modules sit together.
  • smart-ignore.ts goes in smart/, even though config-parser.ts and routes/config-operations.ts are what call it. The whole module is about SMART attributes.
  • container-pause.ts goes in system/ next to docker.ts. It is the only module that drives the Docker client; executors and the scheduler only hold and release it.
  • demo.ts goes in system/. It stands in for hardware (smartctl, devices, df, Docker) for six modules across domains.
  • parity-usage.ts goes in disks/. It reads df for the data and parity disks.
  • routes/, engine/, executors/ and parsers/ stay as they are, because no merge was obviously right.

Commits

  1. Move the server's modules into domain folders: only git mv. All 82 files are R100 (git show -M --name-status shows 82 × R100). This commit does not build on its own.

  2. Point the imports and paths at the new domain folders: only specifiers and paths change. 282 lines changed: 236 import lines, plus 46 path lines:

    • fixture URLs in 4 moved tests: ../parsers/__tests__/fixtures became ../../parsers/__tests__/fixtures
    • app-files.ts: new URL("../../../", import.meta.url) became "../../../../", because the module is one level deeper and the repository root has to stay the same
    • seed-demo.ts: imports and a comment
    • apps/server/src/… paths named in comments in packages/shared/src/i18n.ts, AccountDialog.tsx, RemoveDataDiskWizard.tsx, docker/Dockerfile, scripts/build-binary.sh and upstream-release.yml
    • paths in docs/architecture.md and docs/development.md, including the folder prefix in the module map

    Check: replace every relative specifier, apps/server/src/… path and module-map path with a placeholder in the removed and added lines, sort both sides, and they are identical (diff is empty). So no changed line differs except in a path. build-binary.sh, the Dockerfile's COPY, tsconfig.json and the e2e harness need no changes: they name src/, src/main.ts and src/bin.ts, which stay where they are. config.test.ts spawns join(import.meta.dir, "..", "config-parser.ts"), which still resolves because the test and the module moved together.

  3. Describe the server's domain folders in the docs: the source tree in development.md lists the folders, and the module map in architecture.md is ordered by folder. Docs only.

No behaviour change

Run on this branch after rebasing onto master:

Check Result
bun test (apps/server) 234 pass / 2 skip / 0 fail, 818 expect() calls, 38 files. Same as master
tsc --noEmit (apps/server) clean
bun install --frozen-lockfile no changes
apps/web: biome check, typecheck, test, build clean; 60 tests in 13 files pass (the i18n test reads ../server/src recursively)
scripts/build-binary.sh builds; --version prints 1.3.3; serves the UI (/ 200, <title>SnapRAID UI</title>) and the API; the MCP endpoint lists and reads the embedded docs (docs://snapraid-ui/*)
e2e local target (bun --bun playwright test) 32 passed, 2 skipped (binary.spec runs only for the binary, docker.spec needs a Docker daemon)
e2e binary target (E2E_BINARY=../dist/snapraid-ui-linux-x86_64) 33 passed, 1 skipped (docker.spec)

Possible later splits (not done here)

  • config/maintenance-settings.ts holds the settings of four domains: Docker pause, spindown, metrics and MCP. It could become one settings file per domain.
  • system/demo.ts stands in for SMART, disks, df and Docker. Each stand-in could move next to the domain it replaces.
  • config/setup.ts mixes mount discovery (df) for the setup wizard with creating an array, which is config. The first half could move to disks/.
  • routes/snapraid.ts (job routes plus heal) imports from nearly every domain. It is the obvious next split.

Generated by Claude Code

apps/server/src had 45 modules side by side. They now sit in folders by
what they are about: auth, config, disks, http, integrations,
notifications, schedule, smart, snapraid and system; main.ts, bin.ts and
bin-cli.ts stay at src/. The tests follow their module into a __tests__
folder of its domain, as parsers/__tests__ already did.

Only git mv, no file changes its content; the imports follow in the next
commit, so this commit alone does not build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y3rdfbWb1xDUdPRng7TX9Z
Only specifiers and paths change: the relative imports, the fixtures
the moved tests read (../../parsers/__tests__/fixtures), the repository
root app-files.ts resolves from (one level deeper now), and the server
paths named in comments, the Dockerfile, build-binary.sh, the
upstream-release workflow and the docs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y3rdfbWb1xDUdPRng7TX9Z
The source tree in development.md lists the folders instead of the
loose modules, and the module map in architecture.md is ordered by
folder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y3rdfbWb1xDUdPRng7TX9Z

Copy link
Copy Markdown
Owner Author

TDD review: no findings

I reviewed the move (33a8a20 only git mv, 82× R100; 9e6b9c0 only paths and imports; f0ed1f0 only docs) for errors that tsc does not see. I did not find any error that a failing test proves.

What I checked:

  • Paths resolved at runtime: system/app-files.ts now goes ../../../../ up from one level deeper and lands on the repository root. A probe test (bun:test, source mode) confirms that PACKAGE_JSON → apps/web/package.json, DOCS_DIR → docs/ and FRONTEND_ENTRY → apps/web/.output/server/index.mjs resolve correctly and that APP_VERSION is set. In the binary, ROOT is fixed at /$bunfs/root/, so the move does not change it.
  • Fixture paths in tests: the new URL("../../parsers/__tests__/fixtures/…", import.meta.url) paths in demo, run-result, log-manager and notifications all point to existing files. config.test.ts starts ../config-parser.ts through import.meta.dir correctly.
  • Test discovery: master and this branch both run 236 tests across 38 files (234 pass, 2 skip, 0 fail). There are no mock.module(...) calls, so no mock can point to an old path.
  • References in the repository: every apps/server/src/… path in the code, docs, workflows, Dockerfile and scripts exists on the branch, and no full old path is left. The new anchor #snapraid-engine exists. No production code imports from __tests__/.
  • Docker/binary: the Dockerfile copies all of apps/server/src/ and starts src/main.ts. build-binary.sh builds src/bin.ts. Neither path moved.

Checks: bun test and tsc --noEmit in apps/server are green. CI on f0ed1f0 is green: backend, frontend, install, and e2e local/image/binary, each in two shards.

No fix commits were needed.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

TDD-Review abgeschlossen: keine belegten Findings (Details im vorigen Kommentar). Server-Tests gleich wie master (234 pass, 2 skip), CI grün: backend, frontend, install, e2e local/binary/image je 2/2.

Merge per Squash.


Generated by Claude Code

@firsttris
firsttris merged commit 868246c into master Nov 4, 2026
9 checks passed
@firsttris
firsttris deleted the server-domains branch November 4, 2026 05:32
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.

2 participants