TypeScript · 3694 bytes Raw Blame History
1 import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
2 import type { NetworkStatus, NodeStatus } from '../../shared/types.js';
3
4 export async function statusRoutes(fastify: FastifyInstance) {
5 // Health check endpoint (no auth required)
6 fastify.get('/health', async (request: FastifyRequest, reply: FastifyReply) => {
7 try {
8 const isAlive = await fastify.zephyrfs.ping();
9
10 if (isAlive) {
11 return {
12 status: 'healthy',
13 timestamp: new Date(),
14 services: {
15 web: 'online',
16 zephyrfs: 'online',
17 },
18 };
19 } else {
20 reply.code(503);
21 return {
22 status: 'unhealthy',
23 timestamp: new Date(),
24 services: {
25 web: 'online',
26 zephyrfs: 'offline',
27 },
28 };
29 }
30 } catch (error) {
31 fastify.log.error(error, 'Health check failed');
32 reply.code(503);
33 return {
34 status: 'unhealthy',
35 timestamp: new Date(),
36 services: {
37 web: 'online',
38 zephyrfs: 'error',
39 },
40 error: error.message,
41 };
42 }
43 });
44
45 // Get network status
46 fastify.get('/status/network', {
47 preHandler: fastify.authenticate,
48 }, async (request: FastifyRequest, reply: FastifyReply) => {
49 try {
50 const networkStatus = await fastify.zephyrfs.getNetworkStatus();
51 return networkStatus;
52 } catch (error) {
53 fastify.log.error(error, 'Failed to get network status');
54 throw fastify.httpErrors.internalServerError('Failed to get network status');
55 }
56 });
57
58 // Get node status
59 fastify.get('/status/node', {
60 preHandler: fastify.authenticate,
61 }, async (request: FastifyRequest, reply: FastifyReply) => {
62 try {
63 const nodeStatus = await fastify.zephyrfs.getNodeStatus();
64 return nodeStatus;
65 } catch (error) {
66 fastify.log.error(error, 'Failed to get node status');
67 throw fastify.httpErrors.internalServerError('Failed to get node status');
68 }
69 });
70
71 // WebSocket endpoint for real-time status updates
72 fastify.register(async function (fastify) {
73 fastify.get('/status/ws', { websocket: true }, (connection, request) => {
74 const sendUpdate = async () => {
75 try {
76 const [networkStatus, nodeStatus] = await Promise.all([
77 fastify.zephyrfs.getNetworkStatus(),
78 fastify.zephyrfs.getNodeStatus(),
79 ]);
80
81 connection.socket.send(JSON.stringify({
82 type: 'status_update',
83 data: {
84 network: networkStatus,
85 node: nodeStatus,
86 timestamp: new Date(),
87 },
88 }));
89 } catch (error) {
90 fastify.log.error(error, 'Failed to send status update');
91 connection.socket.send(JSON.stringify({
92 type: 'error',
93 data: {
94 message: 'Failed to get status update',
95 timestamp: new Date(),
96 },
97 }));
98 }
99 };
100
101 // Send initial status
102 sendUpdate();
103
104 // Send updates every 5 seconds
105 const interval = setInterval(sendUpdate, 5000);
106
107 connection.socket.on('close', () => {
108 clearInterval(interval);
109 });
110
111 connection.socket.on('message', (message) => {
112 try {
113 const data = JSON.parse(message.toString());
114
115 if (data.type === 'ping') {
116 connection.socket.send(JSON.stringify({
117 type: 'pong',
118 timestamp: new Date(),
119 }));
120 }
121 } catch (error) {
122 fastify.log.warn(error, 'Invalid WebSocket message received');
123 }
124 });
125 });
126 });
127 }