/** * Reusable query functions - eliminates SQL duplication across routes. */ const updateEntity = async (db, table, id, updates, getById) => { if (Object.keys(updates).length === 0) return getById(db, id) const { buildUpdateQuery } = await import('./queryBuilder.js') const { query, params } = buildUpdateQuery(table, null, updates) if (!query) return getById(db, id) await db.run(query, [...params, id]) return getById(db, id) } export async function getDeviceById(db, id) { const result = await db.get('SELECT id, name, device_type, vendor, lat, lng, stream_url, source_type, config FROM devices WHERE id = ?', [id]) return result || null } export async function getAllDevices(db) { return db.all('SELECT id, name, device_type, vendor, lat, lng, stream_url, source_type, config FROM devices ORDER BY id') } export async function createDevice(db, data) { const id = crypto.randomUUID() await db.run( 'INSERT INTO devices (id, name, device_type, vendor, lat, lng, stream_url, source_type, config) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', [id, data.name, data.device_type, data.vendor, data.lat, data.lng, data.stream_url, data.source_type, data.config], ) return getDeviceById(db, id) } export async function updateDevice(db, id, updates) { return updateEntity(db, 'devices', id, updates, getDeviceById) } export async function getUserById(db, id) { const result = await db.get('SELECT id, identifier, role, auth_provider, password_hash FROM users WHERE id = ?', [id]) return result || null } export async function getUserByIdentifier(db, identifier) { const result = await db.get('SELECT id, identifier, role, password_hash FROM users WHERE identifier = ?', [identifier]) return result || null } export async function createUser(db, data) { const id = crypto.randomUUID() await db.run( 'INSERT INTO users (id, identifier, password_hash, role, created_at, auth_provider, oidc_issuer, oidc_sub) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [id, data.identifier, data.password_hash, data.role, data.created_at, data.auth_provider || 'local', data.oidc_issuer || null, data.oidc_sub || null], ) return db.get('SELECT id, identifier, role, auth_provider FROM users WHERE id = ?', [id]) } export async function updateUser(db, id, updates) { if (Object.keys(updates).length === 0) return getUserById(db, id) const { buildUpdateQuery } = await import('./queryBuilder.js') const { query, params } = buildUpdateQuery('users', null, updates) if (!query) return getUserById(db, id) await db.run(query, [...params, id]) return db.get('SELECT id, identifier, role, auth_provider FROM users WHERE id = ?', [id]) } export async function getPoiById(db, id) { const result = await db.get('SELECT id, lat, lng, label, icon_type FROM pois WHERE id = ?', [id]) return result || null } export async function getAllPois(db) { return db.all('SELECT id, lat, lng, label, icon_type FROM pois ORDER BY id') } export async function createPoi(db, data) { const id = crypto.randomUUID() await db.run( 'INSERT INTO pois (id, lat, lng, label, icon_type) VALUES (?, ?, ?, ?, ?)', [id, data.lat, data.lng, data.label || '', data.icon_type || 'pin'], ) return getPoiById(db, id) } export async function updatePoi(db, id, updates) { return updateEntity(db, 'pois', id, updates, getPoiById) } export async function getSessionById(db, id) { const result = await db.get('SELECT id, user_id, expires_at FROM sessions WHERE id = ?', [id]) return result || null } export async function createDbSession(db, data) { await db.run( 'INSERT INTO sessions (id, user_id, created_at, expires_at) VALUES (?, ?, ?, ?)', [data.id, data.user_id, data.created_at, data.expires_at], ) } export async function deleteSession(db, id) { await db.run('DELETE FROM sessions WHERE id = ?', [id]) }