| |
| |
| |
| |
|
|
| const express = require('express'); |
| const neo4j = require('neo4j-driver'); |
|
|
| const app = express(); |
| const PORT = process.env.GRAPH_VIEWER_PORT || 7861; |
|
|
| |
| const driver = neo4j.driver( |
| 'bolt://localhost:7687', |
| neo4j.auth.basic('', '') |
| ); |
|
|
| |
| const cors = require('cors'); |
| const rateLimit = require('express-rate-limit'); |
|
|
| |
| app.use(cors({ |
| origin: ['obsidian://*', 'https://*.hf.space'] |
| })); |
|
|
| |
| app.use(rateLimit({ |
| windowMs: 15 * 60 * 1000, |
| max: 100 |
| })); |
|
|
| |
| app.use(express.static('public')); |
|
|
| |
| app.get('/api/graph', async (req, res) => { |
| const session = driver.session(); |
| try { |
| const result = await session.run('MATCH (n) RETURN n'); |
| const edgesResult = await session.run('MATCH ()-[r]->() RETURN r'); |
| |
| res.json({ |
| nodes: result.records.map(record => record.get('n').properties), |
| edges: edgesResult.records.map(record => ({ |
| ...record.get('r').properties, |
| type: record.get('r').type |
| })) |
| }); |
| } catch (error) { |
| res.status(500).json({ error: error.message }); |
| } finally { |
| await session.close(); |
| } |
| }); |
|
|
| |
| app.get('/api/graph/:project', async (req, res) => { |
| const session = driver.session(); |
| try { |
| const { project } = req.params; |
| |
| const result = await session.run( |
| 'MATCH (n {project: $project}) RETURN n', |
| { project } |
| ); |
| |
| const edgesResult = await session.run( |
| 'MATCH (n {project: $project})-[r]->(m {project: $project}) RETURN r', |
| { project } |
| ); |
| |
| res.json({ |
| nodes: result.records.map(record => record.get('n').properties), |
| edges: edgesResult.records.map(record => ({ |
| ...record.get('r').properties, |
| type: record.get('r').type |
| })) |
| }); |
| } catch (error) { |
| res.status(500).json({ error: error.message }); |
| } finally { |
| await session.close(); |
| } |
| }); |
|
|
| |
| app.get('/health', async (req, res) => { |
| let memgraphReady = false; |
| const session = driver.session(); |
| try { |
| const result = await session.run('RETURN 1'); |
| memgraphReady = result.records.length > 0; |
| } catch (e) { |
| memgraphReady = false; |
| } finally { |
| await session.close(); |
| } |
|
|
| res.json({ |
| status: memgraphReady ? 'healthy' : 'degraded', |
| version: '1.2.0', |
| build_date: new Date().toISOString().split('T')[0], |
| services: { |
| memgraph: memgraphReady, |
| graph_viewer: true, |
| omniroute: 'check-port-20128' |
| }, |
| timestamp: new Date().toISOString() |
| }); |
| }); |
|
|
| |
| app.listen(PORT, '0.0.0.0', () => { |
| console.log(`๐ Graph Viewer running on port ${PORT}`); |
| console.log(` http://localhost:${PORT}`); |
| console.log(` API: http://localhost:${PORT}/api/graph`); |
| }); |
|
|
| |
| process.on('SIGTERM', () => { |
| driver.close(); |
| }); |
|
|
| module.exports = app; |
|
|