feat(02-03): create context IPC handler and channel constants

- Add CONTEXT_LIST, CONTEXT_GET_ACTIVE, CONTEXT_SWITCH, CONTEXT_CHANGED channel constants
- Create context.ts IPC handler module with list, getActive, and switch operations
- Update handlers.ts to accept onContextSwitched callback and register context handlers
- Pass onContextSwitched from main index.ts to IPC initialization
- Context switching triggers onContextSwitched callback for event re-wiring
This commit is contained in:
matt 2026-02-12 01:10:08 +00:00
parent d10c56adb7
commit 4aafc9c4fc
4 changed files with 130 additions and 3 deletions

View file

@ -154,7 +154,7 @@ function initializeServices(): void {
updaterService = new UpdaterService();
// Initialize IPC handlers with registry
initializeIpcHandlers(contextRegistry, updaterService, sshConnectionManager);
initializeIpcHandlers(contextRegistry, updaterService, sshConnectionManager, onContextSwitched);
// Forward SSH state changes to renderer
sshConnectionManager.on('state-change', (status: unknown) => {

97
src/main/ipc/context.ts Normal file
View file

@ -0,0 +1,97 @@
/**
* Context IPC Handlers - Manages context switching and listing.
*
* Channels:
* - context:list - List all available contexts (local + SSH)
* - context:getActive - Get current active context ID
* - context:switch - Switch to a different context
*/
import {
CONTEXT_CHANGED,
CONTEXT_GET_ACTIVE,
CONTEXT_LIST,
CONTEXT_SWITCH,
} from '@preload/constants/ipcChannels';
import { createLogger } from '@shared/utils/logger';
import type { ServiceContext, ServiceContextRegistry } from '../services';
import type { IpcMain } from 'electron';
const logger = createLogger('IPC:context');
// =============================================================================
// Module State
// =============================================================================
let registry: ServiceContextRegistry;
let onContextSwitched: (context: ServiceContext) => void;
// =============================================================================
// Initialization
// =============================================================================
/**
* Initialize context handlers with required services.
* @param contextRegistry - The service context registry
* @param onSwitched - Callback to invoke after successful context switch
*/
export function initializeContextHandlers(
contextRegistry: ServiceContextRegistry,
onSwitched: (context: ServiceContext) => void
): void {
registry = contextRegistry;
onContextSwitched = onSwitched;
}
// =============================================================================
// Handler Registration
// =============================================================================
export function registerContextHandlers(ipcMain: IpcMain): void {
ipcMain.handle(CONTEXT_LIST, async () => {
try {
const contexts = registry.list();
return { success: true, data: contexts };
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
logger.error('Failed to list contexts:', message);
return { success: false, error: message };
}
});
ipcMain.handle(CONTEXT_GET_ACTIVE, async () => {
try {
const activeContextId = registry.getActiveContextId();
return { success: true, data: activeContextId };
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
logger.error('Failed to get active context:', message);
return { success: false, error: message };
}
});
ipcMain.handle(CONTEXT_SWITCH, async (_event, contextId: string) => {
try {
// Switch to the new context
const { current } = registry.switch(contextId);
// Invoke the context switched callback (re-wires file watcher events)
onContextSwitched(current);
return { success: true, data: { contextId } };
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
logger.error(`Context switch to "${contextId}" failed:`, message);
return { success: false, error: message };
}
});
logger.info('Context handlers registered');
}
export function removeContextHandlers(ipcMain: IpcMain): void {
ipcMain.removeHandler(CONTEXT_LIST);
ipcMain.removeHandler(CONTEXT_GET_ACTIVE);
ipcMain.removeHandler(CONTEXT_SWITCH);
}

View file

@ -17,6 +17,11 @@ import { createLogger } from '@shared/utils/logger';
import { ipcMain } from 'electron';
import { registerConfigHandlers, removeConfigHandlers } from './config';
import {
initializeContextHandlers,
registerContextHandlers,
removeContextHandlers,
} from './context';
const logger = createLogger('IPC:handlers');
import { registerNotificationHandlers, removeNotificationHandlers } from './notifications';
@ -45,7 +50,12 @@ import {
import { registerUtilityHandlers, removeUtilityHandlers } from './utility';
import { registerValidationHandlers, removeValidationHandlers } from './validation';
import type { ServiceContextRegistry, SshConnectionManager, UpdaterService } from '../services';
import type {
ServiceContext,
ServiceContextRegistry,
SshConnectionManager,
UpdaterService,
} from '../services';
/**
* Initializes IPC handlers with service registry.
@ -53,7 +63,8 @@ import type { ServiceContextRegistry, SshConnectionManager, UpdaterService } fro
export function initializeIpcHandlers(
registry: ServiceContextRegistry,
updater: UpdaterService,
sshManager: SshConnectionManager
sshManager: SshConnectionManager,
onContextSwitched: (context: ServiceContext) => void
): void {
// Initialize domain handlers with registry
initializeProjectHandlers(registry);
@ -62,6 +73,7 @@ export function initializeIpcHandlers(
initializeSubagentHandlers(registry);
initializeUpdaterHandlers(updater);
initializeSshHandlers(sshManager, registry);
initializeContextHandlers(registry, onContextSwitched);
// Register all handlers
registerProjectHandlers(ipcMain);
@ -74,6 +86,7 @@ export function initializeIpcHandlers(
registerConfigHandlers(ipcMain);
registerUpdaterHandlers(ipcMain);
registerSshHandlers(ipcMain);
registerContextHandlers(ipcMain);
logger.info('All handlers registered');
}
@ -93,6 +106,7 @@ export function removeIpcHandlers(): void {
removeConfigHandlers(ipcMain);
removeUpdaterHandlers(ipcMain);
removeSshHandlers(ipcMain);
removeContextHandlers(ipcMain);
logger.info('All handlers removed');
}

View file

@ -105,3 +105,19 @@ export const UPDATER_INSTALL = 'updater:install';
/** Status event channel (main -> renderer) */
export const UPDATER_STATUS = 'updater:status';
// =============================================================================
// Context API Channels
// =============================================================================
/** List all available contexts (local + SSH) */
export const CONTEXT_LIST = 'context:list';
/** Get active context ID */
export const CONTEXT_GET_ACTIVE = 'context:getActive';
/** Switch to a different context */
export const CONTEXT_SWITCH = 'context:switch';
/** Context changed event channel (main -> renderer) */
export const CONTEXT_CHANGED = 'context:changed';