diff --git a/DESIGN_CHOICES.md b/DESIGN_CHOICES.md new file mode 100644 index 0000000..da90831 --- /dev/null +++ b/DESIGN_CHOICES.md @@ -0,0 +1,10 @@ +# Design Choices + +## Configuration Persistence +- **Choice**: Persist `ScholarConfig` to `scholar.json` in the project root. +- **Rationale**: The CLI `init` command description explicitly mentions initializing `scholar.json`. Saving it in the project root ensures it's easily discoverable and follows standard Node.js practices for local configuration. +- **Implementation**: Used `node:fs/promises`'s `writeFile` in the `GatewayServer`'s `init_config` request handler. This ensures that the response and event broadcast only happen after a successful write, maintaining consistency. + +## Error Handling in WebSocket Requests +- **Choice**: Use `.then().catch()` for asynchronous file operations within the request handler. +- **Rationale**: This prevents the server from hanging if an error occurs during file I/O and allows sending a meaningful error response to the client. diff --git a/src/daemon/gateway/server.ts b/src/daemon/gateway/server.ts index 518e220..4a2d4d9 100644 --- a/src/daemon/gateway/server.ts +++ b/src/daemon/gateway/server.ts @@ -1,4 +1,5 @@ import { WebSocketServer, WebSocket } from 'ws'; +import { writeFile } from 'node:fs/promises'; import { createResponse, createEvent } from '../../core/protocol.js'; import type { ProtocolMessage, RequestMessage } from '../../core/protocol.js'; @@ -49,11 +50,16 @@ export class GatewayServer { break; case 'init_config': console.log('Received config init payload:', request.payload); - // Implementation for saving the config logic would go here - ws.send(JSON.stringify(createResponse(request.id, true, { status: 'saved' }))); - - // Broadcast an event to all connected clients that config changed - this.broadcastEvent('config_updated', { version: request.payload?.version || '1.0' }); + this.saveConfig(request.payload) + .then(() => { + ws.send(JSON.stringify(createResponse(request.id, true, { status: 'saved' }))); + // Broadcast an event to all connected clients that config changed + this.broadcastEvent('config_updated', { version: request.payload?.version || '1.0' }); + }) + .catch((err) => { + console.error('Failed to save config:', err); + ws.send(JSON.stringify(createResponse(request.id, false, undefined, `Failed to save config: ${err.message}`))); + }); break; default: ws.send(JSON.stringify(createResponse(request.id, false, undefined, 'Unknown command'))); @@ -73,6 +79,12 @@ export class GatewayServer { public stop() { this.wss.close(); } + + private async saveConfig(config: any) { + const configPath = './scholar.json'; + await writeFile(configPath, JSON.stringify(config, null, 4), 'utf-8'); + console.log(`Config saved to ${configPath}`); + } } // Support running the daemon directly