/** * Validates that the given data conforms to the expected Dashboard JSON structure. * Checks for the presence and correct types of `nodes` and `edges` arrays, * and validates that each node has `id`, `type`, `name` and each edge has `source`, `target`, `type`. * Returns all validation errors found, not just the first. */ export function validateDashboard(data) { const errors = []; if (data === null || data === undefined || typeof data !== 'object' || Array.isArray(data)) { errors.push('Dashboard data must be a non-null object'); return { valid: false, errors }; } const record = data; // Validate nodes if (!('nodes' in record) || !Array.isArray(record.nodes)) { errors.push('Dashboard data must contain a "nodes" array'); } else { const nodes = record.nodes; for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; if (node === null || node === undefined || typeof node !== 'object' || Array.isArray(node)) { errors.push(`nodes[${i}] must be an object`); continue; } const nodeRecord = node; const requiredFields = ['id', 'type', 'name']; for (const field of requiredFields) { if (!(field in nodeRecord) || typeof nodeRecord[field] !== 'string') { errors.push(`nodes[${i}] is missing required field "${field}"`); } } } } // Validate edges if (!('edges' in record) || !Array.isArray(record.edges)) { errors.push('Dashboard data must contain an "edges" array'); } else { const edges = record.edges; for (let i = 0; i < edges.length; i++) { const edge = edges[i]; if (edge === null || edge === undefined || typeof edge !== 'object' || Array.isArray(edge)) { errors.push(`edges[${i}] must be an object`); continue; } const edgeRecord = edge; const requiredFields = ['source', 'target', 'type']; for (const field of requiredFields) { if (!(field in edgeRecord) || typeof edgeRecord[field] !== 'string') { errors.push(`edges[${i}] is missing required field "${field}"`); } } } } return { valid: errors.length === 0, errors, }; }