UNPKG

vibetunnel

Version:

Terminal sharing server with web interface - supports macOS, Linux, and headless environments

54 lines 6.53 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.controlEventEmitter = void 0; exports.createControlRoutes = createControlRoutes; /** * Control Event Stream Route * * Provides a server-sent event stream for real-time control messages * including Git notifications and system events. */ const events_1 = require("events"); const express_1 = require("express"); const logger_js_1 = require("../utils/logger.js"); const logger = (0, logger_js_1.createLogger)('control-stream'); // Event emitter for control events exports.controlEventEmitter = new events_1.EventEmitter(); function createControlRoutes() { const router = (0, express_1.Router)(); // SSE endpoint for control events router.get('/control/stream', (req, res) => { // Set headers for SSE res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive', 'X-Accel-Buffering': 'no', // Disable Nginx buffering }); // Send initial connection message res.write(':ok\n\n'); logger.debug('Control event stream connected'); // Subscribe to control events const handleEvent = (event) => { try { res.write(`data: ${JSON.stringify(event)}\n\n`); } catch (error) { logger.error('Failed to send control event:', error); } }; exports.controlEventEmitter.on('event', handleEvent); // Send periodic heartbeat to keep connection alive const heartbeatInterval = setInterval(() => { res.write(':heartbeat\n\n'); }, 30000); // 30 seconds // Clean up on disconnect req.on('close', () => { logger.debug('Control event stream disconnected'); exports.controlEventEmitter.off('event', handleEvent); clearInterval(heartbeatInterval); }); }); return router; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udHJvbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zZXJ2ZXIvcm91dGVzL2NvbnRyb2wudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBc0JBLGtEQTJDQztBQWpFRDs7Ozs7R0FLRztBQUNILG1DQUFzQztBQUN0QyxxQ0FBaUM7QUFFakMsa0RBQWtEO0FBRWxELE1BQU0sTUFBTSxHQUFHLElBQUEsd0JBQVksRUFBQyxnQkFBZ0IsQ0FBQyxDQUFDO0FBRTlDLG1DQUFtQztBQUN0QixRQUFBLG1CQUFtQixHQUFHLElBQUkscUJBQVksRUFBRSxDQUFDO0FBUXRELFNBQWdCLG1CQUFtQjtJQUNqQyxNQUFNLE1BQU0sR0FBRyxJQUFBLGdCQUFNLEdBQUUsQ0FBQztJQUV4QixrQ0FBa0M7SUFDbEMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDLEdBQXlCLEVBQUUsR0FBRyxFQUFFLEVBQUU7UUFDL0Qsc0JBQXNCO1FBQ3RCLEdBQUcsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFO1lBQ2pCLGNBQWMsRUFBRSxtQkFBbUI7WUFDbkMsZUFBZSxFQUFFLFVBQVU7WUFDM0IsVUFBVSxFQUFFLFlBQVk7WUFDeEIsbUJBQW1CLEVBQUUsSUFBSSxFQUFFLDBCQUEwQjtTQUN0RCxDQUFDLENBQUM7UUFFSCxrQ0FBa0M7UUFDbEMsR0FBRyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUVyQixNQUFNLENBQUMsS0FBSyxDQUFDLGdDQUFnQyxDQUFDLENBQUM7UUFFL0MsOEJBQThCO1FBQzlCLE1BQU0sV0FBVyxHQUFHLENBQUMsS0FBbUIsRUFBRSxFQUFFO1lBQzFDLElBQUksQ0FBQztnQkFDSCxHQUFHLENBQUMsS0FBSyxDQUFDLFNBQVMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDbEQsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2YsTUFBTSxDQUFDLEtBQUssQ0FBQywrQkFBK0IsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUN2RCxDQUFDO1FBQ0gsQ0FBQyxDQUFDO1FBRUYsMkJBQW1CLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxXQUFXLENBQUMsQ0FBQztRQUU3QyxtREFBbUQ7UUFDbkQsTUFBTSxpQkFBaUIsR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFO1lBQ3pDLEdBQUcsQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUM5QixDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxhQUFhO1FBRXhCLHlCQUF5QjtRQUN6QixHQUFHLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxHQUFHLEVBQUU7WUFDbkIsTUFBTSxDQUFDLEtBQUssQ0FBQyxtQ0FBbUMsQ0FBQyxDQUFDO1lBQ2xELDJCQUFtQixDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsV0FBVyxDQUFDLENBQUM7WUFDOUMsYUFBYSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDbkMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvbnRyb2wgRXZlbnQgU3RyZWFtIFJvdXRlXG4gKlxuICogUHJvdmlkZXMgYSBzZXJ2ZXItc2VudCBldmVudCBzdHJlYW0gZm9yIHJlYWwtdGltZSBjb250cm9sIG1lc3NhZ2VzXG4gKiBpbmNsdWRpbmcgR2l0IG5vdGlmaWNhdGlvbnMgYW5kIHN5c3RlbSBldmVudHMuXG4gKi9cbmltcG9ydCB7IEV2ZW50RW1pdHRlciB9IGZyb20gJ2V2ZW50cyc7XG5pbXBvcnQgeyBSb3V0ZXIgfSBmcm9tICdleHByZXNzJztcbmltcG9ydCB0eXBlIHsgQXV0aGVudGljYXRlZFJlcXVlc3QgfSBmcm9tICcuLi9taWRkbGV3YXJlL2F1dGguanMnO1xuaW1wb3J0IHsgY3JlYXRlTG9nZ2VyIH0gZnJvbSAnLi4vdXRpbHMvbG9nZ2VyLmpzJztcblxuY29uc3QgbG9nZ2VyID0gY3JlYXRlTG9nZ2VyKCdjb250cm9sLXN0cmVhbScpO1xuXG4vLyBFdmVudCBlbWl0dGVyIGZvciBjb250cm9sIGV2ZW50c1xuZXhwb3J0IGNvbnN0IGNvbnRyb2xFdmVudEVtaXR0ZXIgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29udHJvbEV2ZW50IHtcbiAgY2F0ZWdvcnk6IHN0cmluZztcbiAgYWN0aW9uOiBzdHJpbmc7XG4gIGRhdGE/OiB1bmtub3duO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ29udHJvbFJvdXRlcygpOiBSb3V0ZXIge1xuICBjb25zdCByb3V0ZXIgPSBSb3V0ZXIoKTtcblxuICAvLyBTU0UgZW5kcG9pbnQgZm9yIGNvbnRyb2wgZXZlbnRzXG4gIHJvdXRlci5nZXQoJy9jb250cm9sL3N0cmVhbScsIChyZXE6IEF1dGhlbnRpY2F0ZWRSZXF1ZXN0LCByZXMpID0+IHtcbiAgICAvLyBTZXQgaGVhZGVycyBmb3IgU1NFXG4gICAgcmVzLndyaXRlSGVhZCgyMDAsIHtcbiAgICAgICdDb250ZW50LVR5cGUnOiAndGV4dC9ldmVudC1zdHJlYW0nLFxuICAgICAgJ0NhY2hlLUNvbnRyb2wnOiAnbm8tY2FjaGUnLFxuICAgICAgQ29ubmVjdGlvbjogJ2tlZXAtYWxpdmUnLFxuICAgICAgJ1gtQWNjZWwtQnVmZmVyaW5nJzogJ25vJywgLy8gRGlzYWJsZSBOZ2lueCBidWZmZXJpbmdcbiAgICB9KTtcblxuICAgIC8vIFNlbmQgaW5pdGlhbCBjb25uZWN0aW9uIG1lc3NhZ2VcbiAgICByZXMud3JpdGUoJzpva1xcblxcbicpO1xuXG4gICAgbG9nZ2VyLmRlYnVnKCdDb250cm9sIGV2ZW50IHN0cmVhbSBjb25uZWN0ZWQnKTtcblxuICAgIC8vIFN1YnNjcmliZSB0byBjb250cm9sIGV2ZW50c1xuICAgIGNvbnN0IGhhbmRsZUV2ZW50ID0gKGV2ZW50OiBDb250cm9sRXZlbnQpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJlcy53cml0ZShgZGF0YTogJHtKU09OLnN0cmluZ2lmeShldmVudCl9XFxuXFxuYCk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBsb2dnZXIuZXJyb3IoJ0ZhaWxlZCB0byBzZW5kIGNvbnRyb2wgZXZlbnQ6JywgZXJyb3IpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBjb250cm9sRXZlbnRFbWl0dGVyLm9uKCdldmVudCcsIGhhbmRsZUV2ZW50KTtcblxuICAgIC8vIFNlbmQgcGVyaW9kaWMgaGVhcnRiZWF0IHRvIGtlZXAgY29ubmVjdGlvbiBhbGl2ZVxuICAgIGNvbnN0IGhlYXJ0YmVhdEludGVydmFsID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgcmVzLndyaXRlKCc6aGVhcnRiZWF0XFxuXFxuJyk7XG4gICAgfSwgMzAwMDApOyAvLyAzMCBzZWNvbmRzXG5cbiAgICAvLyBDbGVhbiB1cCBvbiBkaXNjb25uZWN0XG4gICAgcmVxLm9uKCdjbG9zZScsICgpID0+IHtcbiAgICAgIGxvZ2dlci5kZWJ1ZygnQ29udHJvbCBldmVudCBzdHJlYW0gZGlzY29ubmVjdGVkJyk7XG4gICAgICBjb250cm9sRXZlbnRFbWl0dGVyLm9mZignZXZlbnQnLCBoYW5kbGVFdmVudCk7XG4gICAgICBjbGVhckludGVydmFsKGhlYXJ0YmVhdEludGVydmFsKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgcmV0dXJuIHJvdXRlcjtcbn1cbiJdfQ==