manage_ram_scanner/server.js

135 lines
3.7 KiB
JavaScript

const express = require('express');
const sqlite3 = require('sqlite3').verbose();
const path = require('path');
const app = express();
// Middleware
app.use(express.json());
app.use(express.static('public'));
// Initialize SQLite database
const db = new sqlite3.Database('./products.db', (err) => {
if (err) console.error(err.message);
console.log('Connected to products database.');
});
// Create products table
db.run(`CREATE TABLE IF NOT EXISTS products (
id INTEGER PRIMARY KEY AUTOINCREMENT,
mpn TEXT NOT NULL,
sn TEXT NOT NULL,
createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,
createdBy TEXT NOT NULL
)`);
// API Routes
// Create products (batch insert)
app.post('/api/product/create', (req, res) => {
const products = req.body;
if (!Array.isArray(products) || products.length === 0) {
return res.status(400).json({ error: 'Expected an array of products' });
}
const stmt = db.prepare('INSERT INTO products (mpn, sn, createdBy) VALUES (?, ?, ?)');
let inserted = 0;
let errors = [];
products.forEach((product, index) => {
if (!product.mpn || !product.sn || !product.createdBy) {
errors.push(`Product at index ${index} is missing required fields`);
return;
}
stmt.run(product.mpn, product.sn, product.createdBy, (err) => {
if (err) errors.push(`Error inserting product at index ${index}: ${err.message}`);
else inserted++;
});
});
stmt.finalize(() => {
res.json({
success: true,
inserted,
errors: errors.length > 0 ? errors : undefined
});
});
});
// Get products with pagination, search, and sort
app.get('/api/product/get', (req, res) => {
const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 50;
const search = req.query.search || '';
const sortBy = req.query.sortBy || 'id';
const sortOrder = req.query.sortOrder || 'DESC';
const offset = (page - 1) * limit;
// Validate sortBy to prevent SQL injection
const validColumns = ['id', 'mpn', 'sn', 'createdAt', 'createdBy'];
const column = validColumns.includes(sortBy) ? sortBy : 'id';
const order = sortOrder.toUpperCase() === 'ASC' ? 'ASC' : 'DESC';
let query = 'SELECT * FROM products';
let countQuery = 'SELECT COUNT(*) as total FROM products';
let params = [];
if (search) {
const searchCondition = ` WHERE mpn LIKE ? OR sn LIKE ? OR createdBy LIKE ? OR id LIKE ?`;
query += searchCondition;
countQuery += searchCondition;
const searchParam = `%${search}%`;
params = [searchParam, searchParam, searchParam, searchParam];
}
query += ` ORDER BY ${column} ${order} LIMIT ? OFFSET ?`;
params.push(limit, offset);
db.get(countQuery, search ? params.slice(0, 4) : [], (err, countRow) => {
if (err) {
return res.status(500).json({ error: err.message });
}
db.all(query, params, (err, rows) => {
if (err) {
return res.status(500).json({ error: err.message });
}
res.json({
products: rows,
total: countRow.total,
page,
limit,
totalPages: Math.ceil(countRow.total / limit)
});
});
});
});
// Delete product
app.delete('/api/product/delete/:id', (req, res) => {
const id = req.params.id;
db.run('DELETE FROM products WHERE id = ?', id, function(err) {
if (err) {
return res.status(500).json({ error: err.message });
}
if (this.changes === 0) {
return res.status(404).json({ error: 'Product not found' });
}
res.json({ success: true, deleted: this.changes });
});
});
// Serve HTML UI
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
const PORT = process.env.PORT || 4444;
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});