ruch
Version:
Revolutionary React TypeScript CLI with hexagonal architecture & AI-powered development assistance. Create maintainable, scalable applications with domain-driven design and integrated AI tooling.
154 lines • 6.87 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.DomainGraph = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const reactflow_1 = __importStar(require("reactflow"));
require("reactflow/dist/style.css");
const DomainNode_1 = require("./DomainNode");
const DependencyEdge_1 = require("./DependencyEdge");
const nodeTypes = {
domain: DomainNode_1.DomainNode,
};
const edgeTypes = {
dependency: DependencyEdge_1.DependencyEdge,
};
const DomainGraph = ({ graphData, settings, onNodeClick, onEdgeClick, }) => {
const [selectedNode, setSelectedNode] = (0, react_1.useState)(null);
const [selectedEdge, setSelectedEdge] = (0, react_1.useState)(null);
// Convert graph data to React Flow format
const { nodes: initialNodes, edges: initialEdges } = (0, react_1.useMemo)(() => {
const nodes = graphData.nodes.map((node, index) => ({
id: node.id,
type: 'domain',
position: {
x: (index % 4) * 250 + 100,
y: Math.floor(index / 4) * 200 + 100,
},
data: {
label: node.label,
domainType: node.type || 'feature',
isSelected: selectedNode === node.id,
settings,
},
}));
const edges = graphData.edges.map((edge, index) => ({
id: `${edge.source}-${edge.target}-${index}`,
source: edge.source,
target: edge.target,
type: 'dependency',
animated: edge.type === 'direct-import',
markerEnd: {
type: reactflow_1.MarkerType.ArrowClosed,
width: 20,
height: 20,
color: '#64748b',
},
data: {
dependencyType: edge.type,
metadata: edge.metadata,
isSelected: selectedEdge === `${edge.source}-${edge.target}-${index}`,
settings,
},
}));
return { nodes, edges };
}, [graphData, selectedNode, selectedEdge, settings]);
const [nodes, setNodes, onNodesChange] = (0, reactflow_1.useNodesState)(initialNodes);
const [edges, setEdges, onEdgesChange] = (0, reactflow_1.useEdgesState)(initialEdges);
const onConnect = (0, react_1.useCallback)((params) => setEdges((eds) => (0, reactflow_1.addEdge)(params, eds)), [setEdges]);
const handleNodeClick = (0, react_1.useCallback)((event, node) => {
setSelectedNode(node.id);
onNodeClick?.(node.id);
}, [onNodeClick]);
const handleEdgeClick = (0, react_1.useCallback)((event, edge) => {
setSelectedEdge(edge.id);
onEdgeClick?.(edge.id);
}, [onEdgeClick]);
// Detect circular dependencies for highlighting
const circularDependencies = (0, react_1.useMemo)(() => {
const visited = new Set();
const recursionStack = new Set();
const cycles = [];
const dfs = (nodeId) => {
visited.add(nodeId);
recursionStack.add(nodeId);
const outgoingEdges = edges.filter((edge) => edge.source === nodeId);
for (const edge of outgoingEdges) {
if (!visited.has(edge.target)) {
if (dfs(edge.target)) {
cycles.push(nodeId);
return true;
}
}
else if (recursionStack.has(edge.target)) {
cycles.push(nodeId);
return true;
}
}
recursionStack.delete(nodeId);
return false;
};
nodes.forEach((node) => {
if (!visited.has(node.id)) {
dfs(node.id);
}
});
return cycles;
}, [nodes, edges]);
// Update nodes with cycle information
const nodesWithCycles = (0, react_1.useMemo)(() => {
return nodes.map((node) => ({
...node,
data: {
...node.data,
isInCycle: settings.highlightCycles && circularDependencies.includes(node.id),
},
}));
}, [nodes, circularDependencies, settings.highlightCycles]);
return ((0, jsx_runtime_1.jsx)("div", { style: { width: '100%', height: '100%' }, children: (0, jsx_runtime_1.jsxs)(reactflow_1.default, { nodes: nodesWithCycles, edges: edges, onNodesChange: onNodesChange, onEdgesChange: onEdgesChange, onConnect: onConnect, onNodeClick: handleNodeClick, onEdgeClick: handleEdgeClick, nodeTypes: nodeTypes, edgeTypes: edgeTypes, fitView: true, attributionPosition: "bottom-left", children: [(0, jsx_runtime_1.jsx)(reactflow_1.Controls, {}), (0, jsx_runtime_1.jsx)(reactflow_1.MiniMap, { nodeColor: (node) => {
const domainType = node.data?.domainType || 'feature';
switch (domainType) {
case 'core':
return '#ef4444';
case 'shared':
return '#3b82f6';
default:
return '#10b981';
}
}, nodeStrokeWidth: 3, zoomable: true, pannable: true }), (0, jsx_runtime_1.jsx)(reactflow_1.Background, { variant: reactflow_1.BackgroundVariant.Dots, gap: 12, size: 1 })] }) }));
};
exports.DomainGraph = DomainGraph;
//# sourceMappingURL=DomainGraph.js.map