/
ncit
/
c4panelmodel
Обзор
Документация
Войти
/
ncit
/
c4panelmodel
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
src/lib/server/services/diff.ts
97 строк
4 KB
ncit
feat: implement full IcePanel feature clone (Phases 1-8)
09 июн 2026, 11:13
09 июн 2026, 11:13
858c15a
Код
Авторство
О чём код?
import { db } from '$lib/server/db'; /** * Compute diffs between two model states (for draft review). */ export interface ModelDiff { addedObjects: { id: string; name: string; type: string }[]; removedObjects: { id: string; name: string; type: string }[]; modifiedObjects: { id: string; name: string; changes: string[] }[]; addedConnections: { id: string; source: string; target: string; label: string | null }[]; removedConnections: { id: string; source: string; target: string; label: string | null }[]; } interface ModelSnapshot { objects: { id: string; name: string; type: string; displayDescription?: string | null; status?: string }[]; connections: { id: string; sourceId: string; targetId: string; label?: string | null; source?: { name: string }; target?: { name: string } }[]; } export function computeDiff(before: ModelSnapshot, after: ModelSnapshot): ModelDiff { const beforeObjMap = new Map(before.objects.map((o) => [o.id, o])); const afterObjMap = new Map(after.objects.map((o) => [o.id, o])); const addedObjects: ModelDiff['addedObjects'] = []; const removedObjects: ModelDiff['removedObjects'] = []; const modifiedObjects: ModelDiff['modifiedObjects'] = []; for (const [id, obj] of afterObjMap) { if (!beforeObjMap.has(id)) { addedObjects.push({ id, name: obj.name, type: obj.type }); } } for (const [id, obj] of beforeObjMap) { if (!afterObjMap.has(id)) { removedObjects.push({ id, name: obj.name, type: obj.type }); } else { const afterObj = afterObjMap.get(id)!; const changes: string[] = []; if (obj.name !== afterObj.name) changes.push(`name: "${obj.name}" → "${afterObj.name}"`); if (obj.displayDescription !== afterObj.displayDescription) changes.push('description changed'); if (obj.status !== afterObj.status) changes.push(`status: ${obj.status} → ${afterObj.status}`); if (changes.length) modifiedObjects.push({ id, name: obj.name, changes }); } } const beforeConnMap = new Map(before.connections.map((c) => [c.id, c])); const afterConnMap = new Map(after.connections.map((c) => [c.id, c])); const addedConnections: ModelDiff['addedConnections'] = []; const removedConnections: ModelDiff['removedConnections'] = []; for (const [id, conn] of afterConnMap) { if (!beforeConnMap.has(id)) { addedConnections.push({ id, source: conn.source?.name ?? conn.sourceId, target: conn.target?.name ?? conn.targetId, label: conn.label ?? null }); } } for (const [id, conn] of beforeConnMap) { if (!afterConnMap.has(id)) { removedConnections.push({ id, source: conn.source?.name ?? conn.sourceId, target: conn.target?.name ?? conn.targetId, label: conn.label ?? null }); } } return { addedObjects, removedObjects, modifiedObjects, addedConnections, removedConnections }; } /** * Compute diff between current project state and a draft. */ export async function diffDraftWithMain(projectId: string, draftId: string): Promise<ModelDiff> { const draft = await db.draft.findFirst({ where: { id: draftId, projectId } }); if (!draft) throw new Error('Draft not found'); const currentObjects = await db.modelObject.findMany({ where: { projectId }, select: { id: true, name: true, type: true, displayDescription: true, status: true } }); const currentConns = await db.connection.findMany({ where: { projectId }, include: { source: { select: { name: true } }, target: { select: { name: true } } } }); const draftChanges = draft.changes as any; const draftObjects = (draftChanges.objects ?? []).map((o: any) => ({ id: o.id, name: o.name, type: o.type, displayDescription: o.displayDescription, status: o.status })); const draftConns = (draftChanges.connections ?? []).map((c: any) => ({ id: c.id, sourceId: c.sourceId, targetId: c.targetId, label: c.label, source: { name: c.sourceId }, target: { name: c.targetId } })); return computeDiff( { objects: currentObjects, connections: currentConns }, { objects: draftObjects, connections: draftConns } ); }