10 KiB
10 KiB
Frontend Architecture
This document defines the target structure for the Angular renderer and the boundaries between web-safe code, Electron adapters, reusable logic, and feature UI.
Goals
- Keep feature code easy to navigate by grouping it around user-facing domains.
- Push platform-specific behavior behind explicit adapters.
- Move pure logic into helpers and dedicated model files instead of embedding it in components and large services.
- Split large services into smaller units with one clear responsibility each.
Target Structure
src/app/
app.ts
domains/
<domain>/
application/ # facades and use-case orchestration
domain/ # models and pure domain logic
infrastructure/ # adapters, api clients, persistence
feature/ # smart domain UI containers
ui/ # dumb/presentational domain UI
infrastructure/
persistence/ # shared storage adapters and persistence facades
realtime/ # shared signaling, peer transport, media runtime state
core/
constants.ts # cross-domain technical constants only
helpers/ # transitional pure helpers still being moved out
models/ # reusable cross-domain contracts only
platform/
platform.service.ts # runtime/environment detection adapters
external-link.service.ts # browser/electron navigation adapters
electron/ # renderer-side adapters for preload / Electron APIs
realtime/ # compatibility/public import boundary for realtime
services/ # technical cross-domain services only
features/ # transitional feature area while slices move into domains/*/feature
shared/
ui/ # shared presentational primitives
utils/ # shared pure utilities
store/ # ngrx reducers, effects, selectors, actions
Layering Rules
Dependency direction must stay one-way:
domains/*/feature,domains/*/ui, and transitionalfeatures/may depend ondomains/,infrastructure/,core/,shared/, andstore/.domains/*/applicationmay depend on its owndomain/,infrastructure/, top-levelinfrastructure/,core/, andstore/.domains/*/domainshould stay framework-light and hold domain models plus pure logic.domains/*/infrastructuremay depend oncore/platform/, browser APIs, HTTP, persistence, and external adapters.- Top-level
infrastructure/should hold shared technical runtime implementations;core/should hold cross-domain utilities, compatibility entry points, and platform adapters rather than full runtime subsystems. core/models/should only hold shared cross-domain contracts. Domain-specific models belong inside their domain folder.
Responsibility Split
Use these roles consistently when a domain starts to absorb too many concerns:
application: Angular-facing facades and use-case orchestration.domain: contracts, policies, calculations, mapping rules, and other pure domain logic.infrastructure: platform adapters, storage, transport, HTTP, IPC, and persistence boundaries.feature: smart components that wire store, routing, and facades.ui: presentational components with minimal business knowledge.
Platform Boundary
Renderer code should not access window.electronAPI directly except inside the Electron adapter layer.
Current convention:
- Use
core/platform/electron/electron-api.models.tsfor Angular-side Electron typings. - Use
core/platform/electron/electron-bridge.service.tsto reach preload APIs from Angular code. - Keep runtime detection and browser/Electron wrappers such as
core/platform/platform.service.tsandcore/platform/external-link.service.tsinsidecore/platform/rather thancore/services/. - Keep Electron-only persistence and file-system logic inside dedicated adapter services such as
domains/attachment/infrastructure/attachment-storage.service.ts.
This keeps feature and domain code platform-agnostic and makes the browser runtime easier to reason about.
Models And Pure Logic
- Attachment runtime types now live in
domains/attachment/domain/attachment.models.ts. - Attachment download-policy rules now live in
domains/attachment/domain/attachment.logic.ts. - Attachment file-path sanitizing and storage-bucket selection live in
domains/attachment/infrastructure/attachment-storage.helpers.ts. - New domain types should be placed in a dedicated model file inside their domain folder when they are not shared across domains.
- Only cross-domain contracts should stay in
core/models/.
Incremental Refactor Path
The repo is large enough that refactoring must stay incremental. Preferred order:
- Extract platform adapters from direct renderer global access.
- Split persistence and cache behavior out of large orchestration services.
- Move reusable types and helper logic into dedicated files.
- Break remaining multi-responsibility facades into managers or coordinators.
Current Baseline
The current refactor establishes these patterns:
- Shared Electron bridge for Angular services and root app wiring.
- Attachment now lives under
domains/attachment/withapplication/attachment.facade.tsas the public Angular-facing boundary. - Attachment application orchestration is now split across
domains/attachment/application/attachment-manager.service.ts,attachment-transfer.service.ts,attachment-persistence.service.ts, andattachment-runtime.store.ts. - Attachment runtime types and pure transfer-policy logic live in
domains/attachment/domain/. - Attachment disk persistence and storage helpers live in
domains/attachment/infrastructure/. - Shared browser/Electron persistence adapters now live in
infrastructure/persistence/, withDatabaseServiceas the renderer-facing facade over IndexedDB and Electron CQRS-backed SQLite. - Auth HTTP/login orchestration now lives under
domains/auth/application/auth.service.ts. - Chat GIF search and KLIPY integration now live under
domains/chat/application/klipy.service.ts. - Voice-session now lives under
domains/voice-session/withapplication/voice-session.facade.tsas the public Angular-facing boundary. - Voice-session models and pure route/room mapping logic live in
domains/voice-session/domain/. - Voice workspace UI state now lives in
domains/voice-session/application/voice-workspace.service.ts, and persisted voice/screen-share preferences now live indomains/voice-session/infrastructure/voice-settings.storage.ts. - Voice activity tracking now lives in
domains/voice-connection/application/voice-activity.service.ts. - Server-directory now lives under
domains/server-directory/withapplication/server-directory.facade.tsas the public Angular-facing boundary. - Server-directory endpoint state now lives in
domains/server-directory/application/server-endpoint-state.service.ts. - Server-directory contracts and user-facing compatibility messaging live in
domains/server-directory/domain/. - Endpoint default URL normalization and built-in endpoint templates live in
domains/server-directory/domain/server-endpoint-defaults.ts. - Endpoint localStorage persistence, HTTP fan-out, compatibility checks, and health probes live in
domains/server-directory/infrastructure/. infrastructure/realtime/realtime-session.service.tsnow holds the shared realtime runtime service.core/realtime/index.tsis the compatibility/public import surface and re-exports that runtime service asRealtimeSessionFacadefor technical cross-domain consumers.domains/voice-connection/now exposesapplication/voice-connection.facade.tsas the voice-specific Angular-facing boundary.domains/screen-share/now exposesapplication/screen-share.facade.tsplusapplication/screen-share-source-picker.service.ts, anddomain/screen-share.config.tsis the real source for screen-share presets/options plusELECTRON_ENTIRE_SCREEN_SOURCE_NAME.- Shared transport contracts and the low-level signaling and peer-connection stack now live under
infrastructure/realtime/. - Realtime debug network metric collection now lives in
infrastructure/realtime/logging/debug-network-metrics.ts; the debug console reads that infrastructure state rather than keeping the metric store insidecore/services/. - Shared media handling, voice orchestration helpers, noise reduction, and screen-share capture adapters now live in
infrastructure/realtime/media/. - The old
domains/webrtc/*andcore/services/webrtc.service.tscompatibility shims have been removed after all in-repo callers moved tocore/realtime,domains/voice-connection/, anddomains/screen-share/. - Multi-server signaling topology and signaling-manager lifecycle extracted from
WebRTCServiceintoServerSignalingCoordinator. - Angular-facing signal and connection-state bookkeeping extracted from
WebRTCServiceintoWebRtcStateController. - Peer/media event streams, peer messaging, remote stream access, and screen-share entry points extracted from
WebRTCServiceintoPeerMediaFacade. - Lower-level signaling connect/send/identify helpers extracted from
WebRTCServiceintoSignalingTransportHandler. - Incoming signaling message semantics extracted from
WebRTCServiceintoIncomingSignalingMessageHandler. - Outbound server-membership signaling commands extracted from
WebRTCServiceintoServerMembershipSignalingHandler. - Remote screen-share request state and control-plane handling extracted from
WebRTCServiceintoRemoteScreenShareRequestController. - Voice session and heartbeat orchestration extracted from
WebRTCServiceintoVoiceSessionController. - Desktop client-version lookup and endpoint compatibility checks for server-directory live in
domains/server-directory/infrastructure/server-endpoint-compatibility.service.ts. - Endpoint health probing and fallback transport for server-directory live in
domains/server-directory/infrastructure/server-endpoint-health.service.ts. - Server-directory HTTP fan-out, endpoint resolution, and API response normalization live in
domains/server-directory/infrastructure/server-directory-api.service.ts.
Next Candidates
- Migrate remaining voice and room UI from transitional
features/into domain-localfeature/andui/folders. - Migrate remaining WebRTC-facing UI from transitional
features/andshared/locations into domain-localfeature/andui/folders where it improves ownership.