304 lines
7.9 KiB
JavaScript
304 lines
7.9 KiB
JavaScript
require('dotenv').config();
|
|
const express = require('express');
|
|
const { Pool } = require('pg');
|
|
|
|
// Install required packages
|
|
// npm install express pg
|
|
|
|
const app = express();
|
|
app.use(express.json());
|
|
|
|
// Configure PostgreSQL connection
|
|
const pool = new Pool({
|
|
user: process.env.PGUSER,
|
|
host: process.env.PGHOST,
|
|
database: process.env.PGDATABASE,
|
|
password: process.env.PGPASSWORD,
|
|
port: process.env.PGPORT,
|
|
});
|
|
|
|
|
|
// GET all records with pagination
|
|
app.get('/data', async (req, res) => {
|
|
console.log("Get all records with the table");
|
|
try {
|
|
const page = parseInt(req.query.page) || 1;
|
|
const limit = parseInt(req.query.limit) || 10;
|
|
const offset = (page - 1) * limit;
|
|
|
|
const query = {
|
|
text: 'SELECT * FROM test_db_table ORDER BY id LIMIT $1 OFFSET $2',
|
|
values: [limit, offset],
|
|
};
|
|
|
|
const result = await pool.query(query);
|
|
res.json(result.rows);
|
|
} catch (err) {
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
|
|
// GET record by ID
|
|
app.get('/data/:id', async (req, res) => {
|
|
console.log("Get record by ID");
|
|
try {
|
|
const { id } = req.params;
|
|
const query = {
|
|
text: 'SELECT * FROM test_db_table WHERE id = $1',
|
|
values: [id],
|
|
};
|
|
|
|
const result = await pool.query(query);
|
|
if (result.rows.length === 0) {
|
|
return res.status(404).json({ message: 'Record not found' });
|
|
}
|
|
res.json(result.rows[0]);
|
|
} catch (err) {
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
|
|
// POST new record
|
|
app.post('/data', async (req, res) => {
|
|
console.log("Post new record");
|
|
try {
|
|
const { x, y, z } = req.body;
|
|
const query = {
|
|
text: 'INSERT INTO test_db_table(x, y, z) VALUES($1, $2, $3) RETURNING *',
|
|
values: [x, y, z],
|
|
};
|
|
|
|
const result = await pool.query(query);
|
|
res.status(201).json(result.rows[0]);
|
|
} catch (err) {
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
|
|
// PUT update record
|
|
app.put('/data/:id', async (req, res) => {
|
|
console.log("Update record by ID");
|
|
try {
|
|
const { id } = req.params;
|
|
const { x, y, z } = req.body;
|
|
const query = {
|
|
text: 'UPDATE test_db_table SET x = $1, y = $2, z = $3 WHERE id = $4 RETURNING *',
|
|
values: [x, y, z, id],
|
|
};
|
|
|
|
const result = await pool.query(query);
|
|
if (result.rows.length === 0) {
|
|
return res.status(404).json({ message: 'Record not found' });
|
|
}
|
|
res.json(result.rows[0]);
|
|
} catch (err) {
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
|
|
// DELETE record
|
|
app.delete('/data/:id', async (req, res) => {
|
|
console.log("Delete record by ID");
|
|
try {
|
|
const { id } = req.params;
|
|
const query = {
|
|
text: 'DELETE FROM test_db_table WHERE id = $1 RETURNING *',
|
|
values: [id],
|
|
};
|
|
|
|
const result = await pool.query(query);
|
|
if (result.rows.length === 0) {
|
|
return res.status(404).json({ message: 'Record not found' });
|
|
}
|
|
res.json({ message: 'Record deleted successfully' });
|
|
} catch (err) {
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
|
|
// Advanced query endpoint with filtering and sorting
|
|
app.get('/data/search', async (req, res) => {
|
|
console.log("Advanced query endpoint with filtering and sorting");
|
|
try {
|
|
const {
|
|
min_x, max_x,
|
|
min_y, max_y,
|
|
min_z, max_z,
|
|
start_time, end_time,
|
|
sort_by, order = 'ASC'
|
|
} = req.query;
|
|
|
|
let conditions = [];
|
|
let values = [];
|
|
let valueIndex = 1;
|
|
|
|
if (min_x) {
|
|
conditions.push(`x >= $${valueIndex++}`);
|
|
values.push(min_x);
|
|
}
|
|
if (max_x) {
|
|
conditions.push(`x <= $${valueIndex++}`);
|
|
values.push(max_x);
|
|
}
|
|
// Similar for y and z ranges
|
|
if (start_time) {
|
|
conditions.push(`time >= $${valueIndex++}`);
|
|
values.push(start_time);
|
|
}
|
|
if (end_time) {
|
|
conditions.push(`time <= $${valueIndex++}`);
|
|
values.push(end_time);
|
|
}
|
|
|
|
const whereClause = conditions.length > 0
|
|
? 'WHERE ' + conditions.join(' AND ')
|
|
: '';
|
|
|
|
const orderClause = sort_by
|
|
? `ORDER BY ${sort_by} ${order}`
|
|
: 'ORDER BY id';
|
|
|
|
const query = {
|
|
text: `SELECT * FROM test_db_table ${whereClause} ${orderClause}`,
|
|
values: values,
|
|
};
|
|
|
|
const result = await pool.query(query);
|
|
res.json(result.rows);
|
|
} catch (err) {
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
|
|
|
|
// GET latest single record
|
|
app.get('/latest_data', async (req, res) => {
|
|
console.log("require the latest data on the database table");
|
|
try {
|
|
const query = {
|
|
text: 'SELECT * FROM test_db_table ORDER BY time DESC LIMIT 1'
|
|
};
|
|
|
|
const result = await pool.query(query);
|
|
if (result.rows.length === 0) {
|
|
return res.status(404).json({ message: 'No records found' });
|
|
}
|
|
res.json(result.rows[0]);
|
|
} catch (err) {
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
|
|
|
|
// This will handle both "/latest_data" and "/latest data"
|
|
app.get('/latest%20data', async (req, res) => {
|
|
console.log("require the latest data on the database table (20%))");
|
|
try {
|
|
const query = {
|
|
text: 'SELECT * FROM test_db_table ORDER BY time DESC LIMIT 1'
|
|
};
|
|
|
|
const result = await pool.query(query);
|
|
if (result.rows.length === 0) {
|
|
return res.status(404).json({ message: 'No records found' });
|
|
}
|
|
res.json(result.rows[0]);
|
|
} catch (err) {
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
|
|
// GET latest N records
|
|
app.get('/latest_data/:count', async (req, res) => {
|
|
try {
|
|
const count = parseInt(req.params.count) || 1;
|
|
// Add a reasonable limit to prevent excessive requests
|
|
const safeCount = Math.min(count, 100);
|
|
|
|
const query = {
|
|
text: 'SELECT * FROM test_db_table ORDER BY time DESC LIMIT $1',
|
|
values: [safeCount]
|
|
};
|
|
|
|
const result = await pool.query(query);
|
|
res.json(result.rows);
|
|
} catch (err) {
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
|
|
// GET latest data within a time window (e.g., last 5 minutes)
|
|
app.get('/latest_data/window', async (req, res) => {
|
|
try {
|
|
const minutes = parseInt(req.query.minutes) || 5;
|
|
// Add a reasonable limit to prevent excessive time windows
|
|
const safeMinutes = Math.min(minutes, 60);
|
|
|
|
const query = {
|
|
text: `
|
|
SELECT * FROM test_db_table
|
|
WHERE time >= NOW() - INTERVAL '${safeMinutes} minutes'
|
|
ORDER BY time DESC
|
|
`
|
|
};
|
|
|
|
const result = await pool.query(query);
|
|
res.json(result.rows);
|
|
} catch (err) {
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
|
|
// GET latest data with real-time updates using Server-Sent Events (SSE)
|
|
app.get('/latest_data/stream', async (req, res) => {
|
|
// Set headers for SSE
|
|
res.setHeader('Content-Type', 'text/event-stream');
|
|
res.setHeader('Cache-Control', 'no-cache');
|
|
res.setHeader('Connection', 'keep-alive');
|
|
|
|
// Send initial data
|
|
try {
|
|
const query = {
|
|
text: 'SELECT * FROM test_db_table ORDER BY time DESC LIMIT 1'
|
|
};
|
|
const result = await pool.query(query);
|
|
if (result.rows.length > 0) {
|
|
res.write(`data: ${JSON.stringify(result.rows[0])}\n\n`);
|
|
}
|
|
} catch (err) {
|
|
console.error('Error fetching initial data:', err);
|
|
}
|
|
|
|
// Set up polling interval (e.g., every 5 seconds)
|
|
const intervalId = setInterval(async () => {
|
|
try {
|
|
const query = {
|
|
text: 'SELECT * FROM test_db_table ORDER BY time DESC LIMIT 1'
|
|
};
|
|
const result = await pool.query(query);
|
|
if (result.rows.length > 0) {
|
|
res.write(`data: ${JSON.stringify(result.rows[0])}\n\n`);
|
|
}
|
|
} catch (err) {
|
|
console.error('Error fetching update:', err);
|
|
}
|
|
}, 5000);
|
|
|
|
// Clean up on client disconnect
|
|
req.on('close', () => {
|
|
clearInterval(intervalId);
|
|
});
|
|
});
|
|
|
|
|
|
// Error handling middleware
|
|
app.use((err, req, res, next) => {
|
|
console.error(err.stack);
|
|
res.status(500).json({ error: 'Something broke!' });
|
|
});
|
|
|
|
const PORT = process.env.PORT || 3000;
|
|
app.listen(PORT, () => {
|
|
console.log(`Server is running on port ${PORT}`);
|
|
});
|