Skip to content

Latest commit

 

History

History
302 lines (226 loc) · 8.07 KB

File metadata and controls

302 lines (226 loc) · 8.07 KB

Architecture Overview

Voltz is built on a sophisticated service-oriented architecture that promotes modularity, maintainability, and scalability. This document provides a comprehensive overview of the framework's architectural principles and core components.

Core Principles

1. Service-Oriented Architecture (SOA)

Voltz follows SOA principles where functionality is organized into discrete services that communicate through well-defined interfaces. This approach provides:

  • Modularity: Clear separation of concerns
  • Reusability: Services can be used across different parts of the application
  • Testability: Services can be tested in isolation
  • Maintainability: Changes to one service don't affect others

2. Dependency Injection (DI)

The framework uses a sophisticated dependency injection container that manages service dependencies:

  • Explicit Declaration: Dependencies must be declared in the decorator parameter list
  • Lifecycle Management: Proper initialization and cleanup of services
  • Singleton Support: Services can be configured as singletons or transient instances

3. Type Safety

Full TypeScript integration ensures type safety across all layers:

  • Compile-time Checking: Catch errors during development
  • IntelliSense Support: Rich IDE support with autocomplete
  • Refactoring Safety: Safe code refactoring with type checking

Architecture Layers

Main Process Layer

The main process is the heart of the Electron application, running in Node.js environment.

Main Process
├── Core Framework
│   ├── Container (DI)
│   ├── Module Registry
│   ├── Window Manager
│   └── Application Store
├── Decorators
│   ├── @IpcController
│   ├── @IpcService
│   ├── @IpcHandle/@IpcOn
│   └── @LifecycleService
└── Application Modules
    ├── Controllers
    └── Services

Core Components

Container (src/main/core/container.ts)

  • Dependency injection container
  • Service registration and resolution
  • Explicit dependency declaration in decorators
  • Singleton and transient service support

Module Registry (src/main/core/registry.ts)

  • Central registry for all services and controllers
  • Automatic module discovery and loading
  • Lifecycle management for services
  • IPC handler setup and coordination

Window Manager (src/main/core/window-manager.ts)

  • Window creation and management
  • Window configuration handling
  • Cross-window communication support

Application Store (src/main/core/store.ts)

  • Persistent data storage
  • Type-safe configuration management
  • Application settings persistence

Preload Layer

The preload layer acts as a secure bridge between the main and renderer processes.

Preload Layer
├── Context Bridge
├── IPC Communication
├── Type Definitions
└── Security Isolation

Key Features:

  • Context Isolation: Secure communication without exposing Node.js APIs
  • Type-Safe APIs: Full TypeScript support for exposed APIs
  • Selective Exposure: Only necessary APIs are exposed to the renderer

Renderer Layer

The renderer process runs the React-based user interface.

Renderer Process
├── React Application
├── UI Components (shadcn/ui)
├── TailwindCSS Styling
├── Hooks and Utilities
└── Type-Safe IPC Calls

Component Interaction Flow

1. Service Registration Flow

graph TD
    A[Module Discovery] --> B[Decorator Processing]
    B --> C[Dependency Resolution]
    C --> D[Service Registration]
    D --> E[Lifecycle Initialization]
Loading
  1. Module Discovery: The registry scans for modules using glob patterns
  2. Decorator Processing: TypeScript decorators are processed to extract metadata
  3. Dependency Resolution: Constructor dependencies are resolved using reflection
  4. Service Registration: Services are registered in the DI container
  5. Lifecycle Initialization: Services with lifecycle hooks are initialized

2. IPC Communication Flow

graph LR
    A[Renderer Request] --> B[Preload Bridge]
    B --> C[Main Process IPC]
    C --> D[Controller Method]
    D --> E[Service Logic]
    E --> F[Response]
    F --> G[Renderer Update]
Loading
  1. Renderer Request: UI component calls exposed API
  2. Preload Bridge: Request passes through secure context bridge
  3. Main Process IPC: IPC handler receives the request
  4. Controller Method: Decorated controller method processes request
  5. Service Logic: Controller delegates to appropriate service
  6. Response: Result is sent back through the chain

3. Lifecycle Management Flow

graph TD
    A[Application Start] --> B[Module Registration]
    B --> C[Service Initialization]
    C --> D[onInit Hooks]
    D --> E[Application Ready]
    E --> F[Runtime Operations]
    F --> G[Application Shutdown]
    G --> H[onDestroy Hooks]
    H --> I[Cleanup Complete]
Loading

Decorator System

Voltz uses TypeScript decorators to provide a clean, declarative way to configure services and controllers.

Service Decorators

@IpcService()

@IpcService()
@LifecycleService()
export class UserService implements LifecycleAware {
  // Service implementation
}

@LifecycleService() / @LifecycleAware()

@LifecycleService()
export class DatabaseService implements LifecycleAware {
  async onInit(): Promise<void> {
    // Initialize database connection
  }

  async onDestroy(): Promise<void> {
    // Close database connection
  }
}

Controller Decorators

@IpcController(dependencies)

@IpcController(['UserService', 'ValidationService'])
@LifecycleService()
export class UserController {
  constructor(
    private userService: UserService,
    private validationService: ValidationService
  ) {}
}

@IpcHandle(channel) / @IpcOn(channel)

@IpcHandle('user:create')
async createUser(event: IpcMainInvokeEvent, userData: UserData): Promise<User> {
  return this.userService.createUser(userData)
}

@IpcOn('user:updated')
handleUserUpdate(event: IpcMainEvent, userId: string): void {
  this.notificationService.notifyUserUpdate(userId)
}

Dependency Injection Deep Dive

Explicit Dependency Declaration

All dependencies must be explicitly declared in the controller decorator:

// Dependencies must be explicitly declared
@IpcController(['OrderService', 'PaymentService', 'EmailService'])
export class OrderController {
  constructor(
    private orderService: OrderService,
    private paymentService: PaymentService,
    private emailService: EmailService
  ) {}
}

Service Registration

You can register services using the dependency names:

@IpcController(['UserService', 'CustomUtilityService'])
export class UserController {
  constructor(
    private userService: UserService,
    private utilityService: CustomUtilityService
  ) {}
}

Singleton Pattern

Default singleton behavior prevents unnecessary object creation:

  • Services are created once and reused
  • Reduces memory overhead
  • Maintains state across application lifecycle

Security Model

Process Isolation

Voltz maintains Electron's security model:

webPreferences: {
  nodeIntegration: false,        // Disable Node.js in renderer
  contextIsolation: true,        // Enable context isolation
  preload: path.join(__dirname, 'preload.js')  // Secure bridge
}

Controlled API Exposure

Only necessary APIs are exposed to the renderer:

contextBridge.exposeInMainWorld('electron', {
  // Only expose specific, safe methods
  getUserData: () => ipcRenderer.invoke('user:getData'),
  updateSettings: (settings) => ipcRenderer.invoke('settings:update', settings)
})

Type Safety

TypeScript ensures that IPC communication is type-safe:

interface ElectronAPI {
  getUserData: () => Promise<UserData>
  updateSettings: (settings: AppSettings) => Promise<void>
}

This architecture provides a solid foundation for building complex desktop applications while maintaining code quality, type safety, and developer productivity.