import { and, eq, isNull } from 'drizzle-orm'; import { db } from '@/lib/db'; import { systemSettings } from '@/lib/db/schema'; import { createAuditLog } from '@/lib/audit'; import { NotFoundError } from '@/lib/errors'; import { emitToRoom } from '@/lib/socket/server'; interface AuditMeta { userId: string; portId: string; ipAddress: string; userAgent: string; } export async function listSettings(portId: string) { // Get port-specific settings const portSettings = await db .select() .from(systemSettings) .where(eq(systemSettings.portId, portId)) .orderBy(systemSettings.key); // Get global settings (portId is null) const globalSettings = await db .select() .from(systemSettings) .where(isNull(systemSettings.portId)) .orderBy(systemSettings.key); return { portSettings, globalSettings }; } export async function getSetting(key: string, portId: string) { // Try port-specific first, fall back to global const setting = await db.query.systemSettings.findFirst({ where: and(eq(systemSettings.key, key), eq(systemSettings.portId, portId)), }); if (setting) return setting; const global = await db.query.systemSettings.findFirst({ where: and(eq(systemSettings.key, key), isNull(systemSettings.portId)), }); return global ?? null; } export async function upsertSetting(key: string, value: unknown, portId: string, meta: AuditMeta) { const existing = await db.query.systemSettings.findFirst({ where: and(eq(systemSettings.key, key), eq(systemSettings.portId, portId)), }); if (existing) { await db .update(systemSettings) .set({ value, updatedBy: meta.userId, updatedAt: new Date() }) .where(and(eq(systemSettings.key, key), eq(systemSettings.portId, portId))); } else { await db.insert(systemSettings).values({ key, value, portId, updatedBy: meta.userId, }); } void createAuditLog({ userId: meta.userId, portId, action: existing ? 'update' : 'create', entityType: 'setting', entityId: key, oldValue: existing ? { value: existing.value } : undefined, newValue: { value }, ipAddress: meta.ipAddress, userAgent: meta.userAgent, }); emitToRoom(`port:${portId}`, 'system:alert', { alertType: 'setting:updated', message: `Setting "${key}" updated`, severity: 'info', }); return { key, value, portId }; } export async function deleteSetting(key: string, portId: string, meta: AuditMeta) { const existing = await db.query.systemSettings.findFirst({ where: and(eq(systemSettings.key, key), eq(systemSettings.portId, portId)), }); if (!existing) throw new NotFoundError('Setting'); await db .delete(systemSettings) .where(and(eq(systemSettings.key, key), eq(systemSettings.portId, portId))); void createAuditLog({ userId: meta.userId, portId, action: 'delete', entityType: 'setting', entityId: key, oldValue: { value: existing.value }, ipAddress: meta.ipAddress, userAgent: meta.userAgent, }); }