import { prisma } from '../lib/prisma'; import { AppError } from '../types/index'; import type { NodeType } from '../lib/constants'; const mapInclude = { nodes: { include: { module: true }, }, edges: true, }; export async function listMaps() { return prisma.serviceMap.findMany({ orderBy: { createdAt: 'desc' }, select: { id: true, name: true, description: true, createdAt: true, updatedAt: true }, }); } export async function getMap(id: string) { const map = await prisma.serviceMap.findUnique({ where: { id }, include: mapInclude }); if (!map) throw new AppError('Map not found', 404, 'NOT_FOUND'); return map; } export async function createMap(data: { name: string; description?: string }) { return prisma.serviceMap.create({ data, include: mapInclude }); } export async function updateMap(id: string, data: Partial<{ name: string; description: string }>) { await getMap(id); return prisma.serviceMap.update({ where: { id }, data, include: mapInclude }); } export async function deleteMap(id: string) { await getMap(id); return prisma.serviceMap.delete({ where: { id } }); } // ---- Nodes ---- export async function addNode( mapId: string, data: { label: string; nodeType: NodeType; positionX: number; positionY: number; metadata?: string; color?: string; icon?: string; moduleId?: string; } ) { await getMap(mapId); return prisma.serviceNode.create({ data: { mapId, ...data }, include: { module: true }, }); } export async function populateFromRack(mapId: string) { await getMap(mapId); const modules = await prisma.module.findMany({ orderBy: [{ rack: { displayOrder: 'asc' } }, { uPosition: 'asc' }], include: { rack: true }, }); const existing = await prisma.serviceNode.findMany({ where: { mapId, moduleId: { not: null } }, select: { moduleId: true }, }); const existingModuleIds = new Set(existing.map((n) => n.moduleId as string)); const newModules = modules.filter((m) => !existingModuleIds.has(m.id)); if (newModules.length === 0) return getMap(mapId); const byRack = new Map(); for (const mod of newModules) { if (!byRack.has(mod.rackId)) byRack.set(mod.rackId, []); byRack.get(mod.rackId)!.push(mod); } const NODE_W = 200; const NODE_H = 80; const COL_GAP = 260; const ROW_GAP = 110; const nodesToCreate: Array<{ mapId: string; label: string; nodeType: NodeType; positionX: number; positionY: number; moduleId: string; }> = []; let colIdx = 0; for (const rackModules of byRack.values()) { rackModules.forEach((mod, rowIdx) => { nodesToCreate.push({ mapId, label: mod.name, nodeType: 'DEVICE' as NodeType, positionX: colIdx * (NODE_W + COL_GAP), positionY: rowIdx * (NODE_H + ROW_GAP), moduleId: mod.id, }); }); colIdx++; } await prisma.serviceNode.createMany({ data: nodesToCreate }); return getMap(mapId); } export async function updateNode( id: string, data: Partial<{ label: string; positionX: number; positionY: number; metadata: string; color: string; icon: string; moduleId: string | null; }> ) { const existing = await prisma.serviceNode.findUnique({ where: { id } }); if (!existing) throw new AppError('Node not found', 404, 'NOT_FOUND'); return prisma.serviceNode.update({ where: { id }, data, include: { module: true } }); } export async function deleteNode(id: string) { const existing = await prisma.serviceNode.findUnique({ where: { id } }); if (!existing) throw new AppError('Node not found', 404, 'NOT_FOUND'); return prisma.serviceNode.delete({ where: { id } }); } // ---- Edges ---- export async function addEdge( mapId: string, data: { sourceId: string; targetId: string; label?: string; edgeType?: string; animated?: boolean; metadata?: string; } ) { await getMap(mapId); return prisma.serviceEdge.create({ data: { mapId, ...data } }); } export async function updateEdge( id: string, data: Partial<{ label: string; edgeType: string; animated: boolean; metadata: string }> ) { const existing = await prisma.serviceEdge.findUnique({ where: { id } }); if (!existing) throw new AppError('Edge not found', 404, 'NOT_FOUND'); return prisma.serviceEdge.update({ where: { id }, data }); } export async function deleteEdge(id: string) { const existing = await prisma.serviceEdge.findUnique({ where: { id } }); if (!existing) throw new AppError('Edge not found', 404, 'NOT_FOUND'); return prisma.serviceEdge.delete({ where: { id } }); }