const express = require("express"); const db = require("../db/polygons"); const router = express.Router(); router.get("/", (req, res) => { const search = typeof req.query.q === "string" ? req.query.q.trim() : ""; let sql = ` SELECT e.*, COUNT(eg.geometry_id) AS geometry_count FROM entities e LEFT JOIN entity_geometries eg ON eg.entity_id = e.id WHERE e.is_deleted = 0 `; const params = []; if (search) { sql += " AND (e.name LIKE ? OR e.slug LIKE ?)"; const pattern = `%${search}%`; params.push(pattern, pattern); } sql += ` GROUP BY e.id ORDER BY e.name COLLATE NOCASE ASC `; const rows = db.prepare(sql).all(...params); res.json(rows.map(normalizeEntityRow)); }); router.get("/search", (req, res) => { const name = typeof req.query.name === "string" ? req.query.name.trim() : ""; const limit = normalizeLimit(req.query.limit, 25, 100); if (!name) { return res.json([]); } const pattern = `%${name}%`; const rows = db.prepare(` SELECT e.*, COUNT(eg.geometry_id) AS geometry_count FROM entities e LEFT JOIN entity_geometries eg ON eg.entity_id = e.id WHERE e.is_deleted = 0 AND e.name LIKE ? GROUP BY e.id ORDER BY e.name COLLATE NOCASE ASC LIMIT ? `).all(pattern, limit); res.json(rows.map(normalizeEntityRow)); }); router.get("/:id", (req, res) => { const row = db.prepare(` SELECT e.*, COUNT(eg.geometry_id) AS geometry_count FROM entities e LEFT JOIN entity_geometries eg ON eg.entity_id = e.id WHERE e.id = ? AND e.is_deleted = 0 GROUP BY e.id `).get(req.params.id); if (!row) { return res.status(404).json({ error: "Entity not found" }); } res.json(normalizeEntityRow(row)); }); module.exports = router; function normalizeEntityRow(row) { return { id: row.id, name: row.name, slug: row.slug, description: row.description, type_id: row.type_id, status: row.status, created_at: row.created_at, updated_at: row.updated_at, geometry_count: Number(row.geometry_count || 0), }; } function normalizeLimit(value, fallback = 25, max = 100) { const num = Number(value); if (!Number.isFinite(num)) return fallback; const intValue = Math.trunc(num); if (intValue <= 0) return fallback; return Math.min(intValue, max); }