UNPKG

git-contextor

Version:

A code context tool with vector search and real-time monitoring, with optional Git integration.

450 lines (408 loc) 13.9 kB
const express = require('express'); const router = express.Router(); const logger = require('../../cli/utils/logger'); /** * @swagger * /api/tunnel: * post: * summary: Start a tunnel * description: Start a new tunnel with specified service * tags: * - Tunnel * requestBody: * required: true * content: * application/json: * schema: * type: object * properties: * service: * type: string * enum: [corrently, managed, localtunnel, ngrok] * default: corrently * subdomain: * type: string * description: Custom subdomain (if supported) * description: * type: string * description: Tunnel description * required: * - service * responses: * 200: * description: Tunnel started successfully * content: * application/json: * schema: * type: object * properties: * success: * type: boolean * service: * type: string * url: * type: string * status: * type: string * id: * type: string * 400: * description: Bad request * 500: * description: Internal server error */ router.post('/', async (req, res) => { try { const { service = 'corrently', subdomain, description } = req.body; if (!req.sharingService) { return res.status(500).json({ error: 'Sharing service not available' }); } // Pass additional parameters for managed tunneling const result = await req.sharingService.startTunnel(service, { subdomain, description }); const tunnelStatus = req.sharingService.getTunnelStatus(); res.json({ success: true, service: tunnelStatus.service, url: tunnelStatus.url, status: tunnelStatus.status, id: tunnelStatus.id || null, password: tunnelStatus.password || null }); } catch (error) { logger.error('Tunnel start error:', error); res.status(500).json({ error: 'Failed to start tunnel', message: error.message }); } }); /** * @swagger * /api/tunnel: * get: * summary: Get tunnel status * description: Get current tunnel status and details * tags: * - Tunnel * responses: * 200: * description: Tunnel status retrieved successfully * content: * application/json: * schema: * type: object * properties: * status: * type: string * service: * type: string * url: * type: string * id: * type: string * password: * type: string * 500: * description: Internal server error */ router.get('/', async (req, res) => { try { if (!req.sharingService) { return res.status(500).json({ error: 'Sharing service not available' }); } const tunnelStatus = req.sharingService.getTunnelStatus(); res.json(tunnelStatus); } catch (error) { logger.error('Tunnel status error:', error); res.status(500).json({ error: 'Failed to get tunnel status', message: error.message }); } }); /** * @swagger * /api/tunnel: * delete: * summary: Stop tunnel * description: Stop the currently running tunnel * tags: * - Tunnel * responses: * 200: * description: Tunnel stopped successfully * content: * application/json: * schema: * type: object * properties: * success: * type: boolean * message: * type: string * 500: * description: Internal server error */ router.delete('/', async (req, res) => { try { if (!req.sharingService) { return res.status(500).json({ error: 'Sharing service not available' }); } await req.sharingService.stopTunnel(); res.json({ success: true, message: 'Tunnel stopped successfully' }); } catch (error) { logger.error('Tunnel stop error:', error); res.status(500).json({ error: 'Failed to stop tunnel', message: error.message }); } }); /** * @swagger * /api/tunnels: * get: * summary: List all tunnels * description: Get list of all available tunnels (for managed tunneling) * tags: * - Tunnel * responses: * 200: * description: Tunnels retrieved successfully * content: * application/json: * schema: * type: object * properties: * tunnels: * type: array * items: * type: object * properties: * id: * type: string * url: * type: string * status: * type: string * created_at: * type: string * 500: * description: Internal server error */ router.get('/all', async (req, res) => { try { if (!req.sharingService) { return res.status(500).json({ error: 'Sharing service not available' }); } // For now, just return the current tunnel status // In a full implementation, this would query the managed service for all tunnels const tunnelStatus = req.sharingService.getTunnelStatus(); const tunnels = []; if (tunnelStatus.status !== 'stopped') { tunnels.push({ id: tunnelStatus.id || 'local', url: tunnelStatus.url, status: tunnelStatus.status, service: tunnelStatus.service, created_at: new Date().toISOString() }); } res.json({ tunnels }); } catch (error) { logger.error('Tunnel list error:', error); res.status(500).json({ error: 'Failed to list tunnels', message: error.message }); } }); /** * @swagger * /api/tunnel/test: * post: * summary: Test tunnel connection * description: Test connection to a tunnel provider * tags: * - Tunnel * requestBody: * required: true * content: * application/json: * schema: * type: object * properties: * provider: * type: string * enum: [corrently, managed, localtunnel] * default: corrently * apiKey: * type: string * description: API key for the tunnel service * responses: * 200: * description: Connection test successful * content: * application/json: * schema: * type: object * properties: * success: * type: boolean * user: * type: string * plan: * type: string * usage: * type: object * 400: * description: Bad request * 500: * description: Connection test failed */ router.post('/test', async (req, res) => { try { const { provider, apiKey } = req.body; if (!provider || !apiKey) { return res.status(400).json({ error: 'Provider and API key are required' }); } if (provider === 'corrently') { const CorrentlyTunnelProvider = require('../../tunneling/CorrentlyTunnelProvider'); const tunnelProvider = new CorrentlyTunnelProvider({ apiKey: apiKey, serverUrl: 'https://tunnel.corrently.cloud' }); // Test connection const health = await tunnelProvider.testConnection(); const userInfo = await tunnelProvider.getUserInfo(); res.json({ success: true, user: userInfo.email, plan: userInfo.plan, usage: userInfo.usage, health: health }); } else { res.status(400).json({ error: `Testing not supported for provider: ${provider}` }); } } catch (error) { logger.error('Tunnel test error:', error); res.status(500).json({ error: 'Connection test failed', message: error.message }); } }); module.exports = (services) => { const { sharingService } = services; if (!sharingService) { throw new Error('SharingService is required for tunnel routes'); } // Create a new router with the sharingService available const tunnelRouter = express.Router(); // Redefine all routes with proper sharingService access tunnelRouter.get('/', async (req, res) => { try { const tunnelStatus = sharingService.getTunnelStatus(); res.json(tunnelStatus); } catch (error) { logger.error('Error fetching tunnel status:', error); res.status(500).json({ error: 'Failed to fetch tunnel status' }); } }); tunnelRouter.post('/', async (req, res) => { try { const { service = 'corrently', subdomain, description } = req.body; // Pass additional parameters for managed tunneling const result = await sharingService.startTunnel(service, { subdomain, description }); const tunnelStatus = sharingService.getTunnelStatus(); res.json({ success: true, service: service, ...tunnelStatus }); } catch (error) { logger.error('Error starting tunnel:', error); res.status(500).json({ success: false, error: error.message || 'Failed to start tunnel' }); } }); tunnelRouter.delete('/', async (req, res) => { try { await sharingService.stopTunnel(); res.json({ success: true, message: 'Tunnel stopped successfully' }); } catch (error) { logger.error('Error stopping tunnel:', error); res.status(500).json({ success: false, error: error.message || 'Failed to stop tunnel' }); } }); tunnelRouter.get('/all', async (req, res) => { try { // For now, just return the current tunnel status // In a full implementation, this would query the managed service for all tunnels const tunnelStatus = sharingService.getTunnelStatus(); const tunnels = []; if (tunnelStatus.status !== 'stopped') { tunnels.push({ id: tunnelStatus.id || 'local', url: tunnelStatus.url, status: tunnelStatus.status, service: tunnelStatus.service, created_at: new Date().toISOString() }); } res.json({ tunnels }); } catch (error) { logger.error('Error fetching tunnels:', error); res.status(500).json({ error: 'Failed to fetch tunnels' }); } }); tunnelRouter.post('/test', async (req, res) => { try { const { provider, apiKey } = req.body; if (!provider || !apiKey) { return res.status(400).json({ error: 'Provider and apiKey are required' }); } if (provider === 'corrently') { // Test corrently connection by making a simple API call const CorrentlyTunnelProvider = require('../../tunneling/CorrentlyTunnelProvider'); const testProvider = new CorrentlyTunnelProvider({ apiKey, serverUrl: 'https://tunnel.corrently.cloud' }); // Try to get account info as a test const accountInfo = await testProvider.getAccountInfo(); res.json({ success: true, message: 'Connection successful', user: accountInfo.user || 'Unknown' }); } else { res.status(400).json({ error: 'Only corrently provider testing is supported' }); } } catch (error) { logger.error('Tunnel test error:', error); res.status(500).json({ error: 'Connection test failed', message: error.message }); } }); return tunnelRouter; };