@masuidrive/ticket
Version:
Real-time ticket tracking viewer with Vite + Express
167 lines • 6.2 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TicketServer = void 0;
const express_1 = __importDefault(require("express"));
const cors_1 = __importDefault(require("cors"));
const http_1 = require("http");
const ws_1 = require("ws");
const fileService_1 = require("./fileService");
const fileWatcher_1 = require("./fileWatcher");
class TicketServer {
constructor(port = 4932, projectRoot) {
this.clients = new Set();
this.port = port;
this.app = (0, express_1.default)();
this.fileService = new fileService_1.FileService(projectRoot);
this.fileWatcher = new fileWatcher_1.FileWatcher(projectRoot);
this.setupMiddleware();
this.setupRoutes();
this.setupWebSocket();
this.setupFileWatcher();
}
setupMiddleware() {
this.app.use((0, cors_1.default)());
this.app.use(express_1.default.json());
}
setupRoutes() {
// Root endpoint - API documentation
this.app.get('/', (req, res) => {
res.json({
name: 'Ticket Viewer Server',
version: '1.0.0',
endpoints: {
'GET /': 'This documentation',
'GET /health': 'Health check endpoint',
'GET /api/ticket': 'Get current ticket content (YAML frontmatter + markdown)',
'GET /api/ticket/exists': 'Check if current-ticket.md exists',
'WS ws://localhost:4932': 'WebSocket endpoint for real-time updates'
},
description: 'Server that serves current-ticket.md content with real-time updates'
});
});
// Health check endpoint
this.app.get('/health', (req, res) => {
res.json({ status: 'ok', timestamp: new Date().toISOString() });
});
// Get current ticket content
this.app.get('/api/ticket', async (req, res) => {
try {
const content = await this.fileService.readTicketFile();
if (!content) {
return res.status(404).json({
error: 'Ticket file not found',
message: 'No current-ticket.md file exists in the project root'
});
}
res.json(content);
}
catch (error) {
console.error('Error reading ticket file:', error);
res.status(500).json({
error: 'Internal server error',
message: 'Failed to read ticket file'
});
}
});
// Check if ticket file exists
this.app.get('/api/ticket/exists', async (req, res) => {
try {
const exists = await this.fileService.fileExists('current-ticket.md');
res.json({ exists });
}
catch (error) {
console.error('Error checking file existence:', error);
res.status(500).json({
error: 'Internal server error',
message: 'Failed to check file existence'
});
}
});
}
setupWebSocket() {
this.server = (0, http_1.createServer)(this.app);
this.wss = new ws_1.WebSocketServer({ server: this.server });
this.wss.on('connection', (ws) => {
console.log('New WebSocket client connected');
this.clients.add(ws);
ws.on('close', () => {
console.log('WebSocket client disconnected');
this.clients.delete(ws);
});
ws.on('error', (error) => {
console.error('WebSocket error:', error);
this.clients.delete(ws);
});
// Send initial content
this.fileService.readTicketFile().then(content => {
if (content) {
ws.send(JSON.stringify({
type: 'update',
data: content
}));
}
}).catch(error => {
console.error('Error sending initial content:', error);
});
});
}
setupFileWatcher() {
this.fileWatcher.watchFile('current-ticket.md');
this.fileWatcher.on('fileChanged', async () => {
console.log('Ticket file changed');
await this.broadcastUpdate();
});
this.fileWatcher.on('fileAdded', async () => {
console.log('Ticket file added');
await this.broadcastUpdate();
});
this.fileWatcher.on('fileRemoved', () => {
console.log('Ticket file removed');
this.broadcast({
type: 'removed',
data: null
});
});
this.fileWatcher.on('error', (error) => {
console.error('File watcher error:', error);
});
}
async broadcastUpdate() {
try {
const content = await this.fileService.readTicketFile();
if (content) {
this.broadcast({
type: 'update',
data: content
});
}
}
catch (error) {
console.error('Error broadcasting update:', error);
}
}
broadcast(message) {
const messageStr = JSON.stringify(message);
this.clients.forEach(client => {
if (client.readyState === ws_1.WebSocket.OPEN) {
client.send(messageStr);
}
});
}
start() {
this.server.listen(this.port, () => {
console.log(`Ticket server running on http://localhost:${this.port}`);
console.log(`WebSocket endpoint: ws://localhost:${this.port}`);
});
}
stop() {
this.fileWatcher.stop();
this.wss.close();
this.server.close();
}
}
exports.TicketServer = TicketServer;
//# sourceMappingURL=server.js.map