Files
lemonspace_app/components/canvas/canvas-connection-validation.ts

77 lines
2.2 KiB
TypeScript

import type { Connection, Edge as RFEdge, Node as RFNode } from "@xyflow/react";
import {
validateCanvasConnectionPolicy,
type CanvasConnectionValidationReason,
} from "@/lib/canvas-connection-policy";
export function validateCanvasConnection(
connection: Connection,
nodes: RFNode[],
edges: RFEdge[],
edgeToReplaceId?: string,
): CanvasConnectionValidationReason | null {
if (!connection.source || !connection.target) return "incomplete";
if (connection.source === connection.target) return "self-loop";
const sourceNode = nodes.find((node) => node.id === connection.source);
const targetNode = nodes.find((node) => node.id === connection.target);
if (!sourceNode || !targetNode) return "unknown-node";
return validateCanvasConnectionByType({
sourceType: sourceNode.type ?? "",
targetType: targetNode.type ?? "",
targetNodeId: connection.target,
edges,
edgeToReplaceId,
});
}
export function validateCanvasConnectionByType(args: {
sourceType: string;
targetType: string;
targetNodeId: string;
edges: RFEdge[];
edgeToReplaceId?: string;
}): CanvasConnectionValidationReason | null {
const targetIncomingCount = args.edges.filter(
(edge) => edge.target === args.targetNodeId && edge.id !== args.edgeToReplaceId,
).length;
return validateCanvasConnectionPolicy({
sourceType: args.sourceType,
targetType: args.targetType,
targetIncomingCount,
});
}
export function validateCanvasEdgeSplit(args: {
nodes: RFNode[];
edges: RFEdge[];
splitEdge: RFEdge;
middleNode: RFNode;
}): CanvasConnectionValidationReason | null {
const sourceNode = args.nodes.find((node) => node.id === args.splitEdge.source);
const targetNode = args.nodes.find((node) => node.id === args.splitEdge.target);
if (!sourceNode || !targetNode) {
return "unknown-node";
}
return (
validateCanvasConnectionByType({
sourceType: sourceNode.type ?? "",
targetType: args.middleNode.type ?? "",
targetNodeId: args.middleNode.id,
edges: args.edges,
}) ??
validateCanvasConnectionByType({
sourceType: args.middleNode.type ?? "",
targetType: targetNode.type ?? "",
targetNodeId: targetNode.id,
edges: args.edges,
edgeToReplaceId: args.splitEdge.id,
})
);
}