bae705aa97
- Add NFC ePassport roadmap (ICAO 9303, eIDAS) - Add TensorFlow.js edge face detection (BlazeFace) - Add structured audit logger (GDPR-compliant) - Risk scoring support Part of KYC Apple Native UX v1.1.0
116 lines
3.1 KiB
JavaScript
116 lines
3.1 KiB
JavaScript
const express = require('express');
|
|
const { Pool } = require('pg');
|
|
const neo4j = require('neo4j-driver');
|
|
const redis = require('redis');
|
|
|
|
const app = express();
|
|
app.use(express.json());
|
|
|
|
// PostgreSQL
|
|
const pgPool = new Pool({
|
|
host: 'localhost',
|
|
port: 5433,
|
|
database: 'quixzoom',
|
|
user: 'quixzoom',
|
|
password: 'quixzoom_secure_2026'
|
|
});
|
|
|
|
// Neo4j
|
|
const neo4jDriver = neo4j.driver('bolt://localhost:7687', neo4j.auth.basic('neo4j', 'quixzoom_neo4j_2026'));
|
|
|
|
// Redis
|
|
const redisClient = redis.createClient({ url: 'redis://localhost:6380' });
|
|
redisClient.connect().catch(console.error);
|
|
|
|
// Health check
|
|
app.get('/health', async (req, res) => {
|
|
const status = {
|
|
status: 'ok',
|
|
timestamp: new Date().toISOString(),
|
|
services: {}
|
|
};
|
|
|
|
try {
|
|
await pgPool.query('SELECT 1');
|
|
status.services.postgresql = 'ok';
|
|
} catch (e) {
|
|
status.services.postgresql = 'error';
|
|
}
|
|
|
|
try {
|
|
const session = neo4jDriver.session();
|
|
await session.run('RETURN 1');
|
|
await session.close();
|
|
status.services.neo4j = 'ok';
|
|
} catch (e) {
|
|
status.services.neo4j = 'error';
|
|
}
|
|
|
|
try {
|
|
await redisClient.ping();
|
|
status.services.redis = 'ok';
|
|
} catch (e) {
|
|
status.services.redis = 'error';
|
|
}
|
|
|
|
res.json(status);
|
|
});
|
|
|
|
// Stats
|
|
app.get('/stats', async (req, res) => {
|
|
try {
|
|
const pgResult = await pgPool.query(`
|
|
SELECT
|
|
(SELECT COUNT(*) FROM objects) as objects,
|
|
(SELECT COUNT(*) FROM observations) as observations,
|
|
(SELECT COUNT(*) FROM zoomers) as zoomers,
|
|
(SELECT COUNT(*) FROM events) as events
|
|
`);
|
|
|
|
res.json({
|
|
postgresql: pgResult.rows[0],
|
|
timestamp: new Date().toISOString()
|
|
});
|
|
} catch (e) {
|
|
res.status(500).json({ error: e.message });
|
|
}
|
|
});
|
|
|
|
// Create object
|
|
app.post('/objects', async (req, res) => {
|
|
try {
|
|
const { object_id, type, latitude, longitude, attributes } = req.body;
|
|
|
|
const result = await pgPool.query(
|
|
'INSERT INTO objects (object_id, type, latitude, longitude, attributes) VALUES ($1, $2, $3, $4, $5) RETURNING *',
|
|
[object_id, type, latitude, longitude, JSON.stringify(attributes || {})]
|
|
);
|
|
|
|
await pgPool.query(
|
|
'INSERT INTO events (sequence_number, type, stream_id, aggregate_id, payload, timestamp) VALUES ((SELECT COALESCE(MAX(sequence_number), 0) + 1 FROM events), $1, $2, $3, $4, NOW())',
|
|
['ObjectRegistered', 'objects', object_id, JSON.stringify({ type, latitude, longitude, attributes })]
|
|
);
|
|
|
|
res.json(result.rows[0]);
|
|
} catch (e) {
|
|
res.status(500).json({ error: e.message });
|
|
}
|
|
});
|
|
|
|
// List objects
|
|
app.get('/objects', async (req, res) => {
|
|
try {
|
|
const result = await pgPool.query('SELECT * FROM objects ORDER BY created_at DESC LIMIT 100');
|
|
res.json(result.rows);
|
|
} catch (e) {
|
|
res.status(500).json({ error: e.message });
|
|
}
|
|
});
|
|
|
|
const PORT = process.env.PORT || 3000;
|
|
app.listen(PORT, () => {
|
|
console.log('[API] QUIXZOOM API Server running on port ' + PORT);
|
|
console.log('[API] Health: http://localhost:' + PORT + '/health');
|
|
console.log('[API] Stats: http://localhost:' + PORT + '/stats');
|
|
});
|