Skip to content

Architecture

github-actions[bot] edited this page Apr 26, 2026 · 1 revision

Architecture

A high-level orientation. The full design is in docs/ARCHITECTURE.md.

Layered View

┌────────────────────────────────────────────┐
│  Browser SPA (public/)                     │
│  - Vite, BaseView/BaseModal framework      │
│  - WebSocket client (BackendAPIClient)     │
└────────────────────────────────────────────┘
                  │  WebSocket + REST
                  ▼
┌────────────────────────────────────────────┐
│  api/   HttpServer · WebSocketServer       │
│         CommandRegistry · CommandHandler   │
└────────────────────────────────────────────┘
                  │
                  ▼
┌────────────────────────────────────────────┐
│  Domain services                           │
│  midi/  devices · routing · playback ·     │
│         adaptation · messages · files · gm │
│  transports/  BLE · RTP-MIDI · Serial      │
│  lighting/    drivers · effects engine     │
│  audio/       DelayCalibrator              │
│  files/       FileManager · BlobStore      │
└────────────────────────────────────────────┘
                  │
                  ▼
┌────────────────────────────────────────────┐
│  repositories/ (business-named wrappers)   │
│  persistence/  Database · BackupScheduler  │
│                tables/* · dbHelpers        │
│  SQLite (better-sqlite3, WAL mode)         │
└────────────────────────────────────────────┘

Core Building Blocks

File Responsibility
src/core/Application.js Composition root, lifecycle (start/stop)
src/core/ServiceContainer.js DI container, lazy factories, circular-dep detection
src/core/EventBus.js In-process pub/sub between command handlers and services
src/core/Logger.js JSON logging with rotation
src/core/Config.js Layered config (file → .env → env vars)
src/core/errors/ Structured error hierarchy

Patterns Used

  • Dependency Injection via ServiceContainer — every service is registered explicitly; no service-locator anti-patterns.
  • Command pattern — every WebSocket message is a named command resolved by CommandRegistry, which auto-discovers modules under src/api/commands/.
  • Repository pattern — domain code talks to *Repository classes; the SQLite schema is hidden behind per-table managers in src/persistence/tables/.
  • Observer / EventBus — decouples command handlers from real-time fan-out (UI updates, MIDI input echoes, lifecycle hooks).
  • Driver pattern — lighting backends extend BaseLightingDriver; transports follow the same shape (BluetoothManager, NetworkManager, SerialMidiManager).

Request Flow

  1. Browser opens WebSocket (auth via ?token= if GMBOOP_API_TOKEN is set).
  2. UI sends { command, id, ...params }.
  3. WebSocketServerCommandHandler → resolves command in CommandRegistry.
  4. Handler calls one or more services / repositories.
  5. Services emit EventBus events; the WS layer broadcasts them to subscribed clients.
  6. Response { type: "response", id, data } returns to the caller.

Frontend Architecture

  • Custom BaseView / BaseModal framework (no React/Vue).
  • Each feature lives under public/js/features/ (40+ modules, e.g. midi-editor/, lighting/, auto-assign/).
  • BackendAPIClient wraps the WebSocket with request correlation, auto-retry, and event subscriptions.
  • i18n via JSON dictionaries in public/locales/ (28 languages).

Persistence

  • SQLite via better-sqlite3 in WAL mode.
  • Migrations in migrations/ (29 files; 001_baseline.sql is the consolidated baseline).
  • Daily automated backups via BackupScheduler.
  • File blobs use a content-addressable store (SHA-256 keys) in src/files/BlobStore.js for deduplication.

Architecture Decision Records

ADRs are tracked under docs/adr/ — read these before proposing structural changes.

Clone this wiki locally