Add documentation comments to SignalR implementation

Added comprehensive code comments explaining:
- RuntimeControllerAspNetDotnetFirstSignalR: .NET-first startup flow and key differences from Socket.IO
- SignalRFacade: Type conversion handling and event propagation details
- signalr-bridge.js: Socket.IO compatibility layer and arg handling
- main.js: Keep-alive window pattern and SignalR startup sequence

Comments focus on explaining WHY decisions were made, not just WHAT the code does.
This commit is contained in:
Pierre Arnaud
2026-01-30 17:08:37 +01:00
parent 1fc881674d
commit 217fe83334
4 changed files with 41 additions and 1 deletions

View File

@@ -11,6 +11,13 @@ namespace ElectronNET.API
/// <summary>
/// SignalR-based facade that mimics the SocketIoFacade interface
/// for compatibility with existing Electron API code.
///
/// Key implementation details:
/// - Uses IHubContext to send events to Electron via 'event' hub method
/// - Receives events from Electron via ElectronHub.ElectronEvent() method
/// - Includes ConvertToType&lt;T&gt; helper to handle JsonElement and numeric type conversions
/// - Event args are passed as arrays to match SignalR serialization behavior
/// - Connection ID is set by ElectronHub when Electron client connects
/// </summary>
internal class SignalRFacade : IFacade
{

View File

@@ -14,6 +14,14 @@ namespace ElectronNET.AspNet.Runtime
using Microsoft.AspNetCore.SignalR;
using ElectronNET.AspNet.Hubs;
/// <summary>
/// Runtime controller for SignalR-based .NET-first startup mode.
/// Key differences from Socket.IO mode:
/// - Waits for ASP.NET server to start, then captures the dynamic port
/// - Launches Electron with the actual URL (no port scanning needed)
/// - Uses SignalRFacade instead of SocketIOFacade for bidirectional communication
/// - Waits for 'electron-host-ready' signal to ensure API modules are loaded before calling app callback
/// </summary>
internal class RuntimeControllerAspNetDotnetFirstSignalR : RuntimeControllerAspNetBase
{
private ElectronProcessBase electronProcess;

View File

@@ -1,4 +1,14 @@
// SignalR connection module for Electron.NET
/**
* SignalR connection module for Electron.NET
*
* This module provides a Socket.IO-compatible interface for SignalR communication.
* Key features:
* - Mimics Socket.IO's on() and emit() methods for compatibility with existing API modules
* - Handles event registration and propagation between Electron and .NET
* - Event args are always passed as arrays to match C# ElectronEvent(string, object[]) signature
* - Spreads args when calling handlers to match Socket.IO behavior
* - Supports automatic reconnection with configurable logging level
*/
const signalR = require('@microsoft/signalr');
// Safe console wrapper that catches EPIPE errors

View File

@@ -171,6 +171,8 @@ app.on('ready', async () => {
}
// Check if we're using SignalR-based startup
// SignalR mode is activated by --unpackeddotnetsignalr or --dotnetpackedsignalr flags
// .NET passes the actual server URL via --electronurl parameter (no port scanning needed)
if (unpackeddotnetsignalr || dotnetpackedsignalr) {
if (!electronUrl) {
console.error('[Electron] ERROR: SignalR mode requires --electronUrl parameter');
@@ -179,6 +181,7 @@ app.on('ready', async () => {
}
// Create a temporary invisible window to keep Electron alive during startup.
// Without any windows, Electron would quit immediately on macOS.
// This will be destroyed once the first real window is created.
const { BrowserWindow } = require('electron');
const keepAliveWindow = new BrowserWindow({
@@ -420,6 +423,18 @@ function startSocketApiBridge(port) {
});
}
/**
* Starts the SignalR API bridge for .NET-first SignalR mode.
*
* Flow:
* 1. Connect to SignalR hub at /electron-hub endpoint
* 2. Register as Electron client
* 3. Load all API modules (same modules as Socket.IO mode)
* 4. Signal 'electron-host-ready' to .NET to trigger app ready callback
*
* This ensures .NET doesn't call the app ready callback until all API modules
* are loaded and ready to handle requests from .NET code.
*/
async function startSignalRApiBridge(baseUrl) {
const { SignalRBridge } = require('./api/signalr-bridge');
const hubUrl = `${baseUrl}/electron-hub`;