105 lines
2.8 KiB
TypeScript
105 lines
2.8 KiB
TypeScript
|
|
// 데이터플로우 관련 유틸리티 함수들
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 고유 ID 생성 함수
|
||
|
|
*/
|
||
|
|
export const generateUniqueId = (prefix: string, diagramId?: number): string => {
|
||
|
|
const timestamp = Date.now();
|
||
|
|
const random = Math.random().toString(36).substr(2, 9);
|
||
|
|
return `${prefix}-${diagramId || timestamp}-${random}`;
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 테이블 쌍별 관계 개수 계산
|
||
|
|
*/
|
||
|
|
export const calculateTableRelationshipCount = (relationships: Array<{ fromTable: string; toTable: string }>) => {
|
||
|
|
const tableRelationshipCount: { [key: string]: number } = {};
|
||
|
|
|
||
|
|
relationships.forEach((rel) => {
|
||
|
|
const tableKey = [rel.fromTable, rel.toTable].sort().join("-");
|
||
|
|
tableRelationshipCount[tableKey] = (tableRelationshipCount[tableKey] || 0) + 1;
|
||
|
|
});
|
||
|
|
|
||
|
|
return tableRelationshipCount;
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 연결된 컬럼 정보 계산
|
||
|
|
*/
|
||
|
|
export const calculateConnectedColumns = (
|
||
|
|
relationships: Array<{
|
||
|
|
fromTable: string;
|
||
|
|
toTable: string;
|
||
|
|
fromColumns: string[];
|
||
|
|
toColumns: string[];
|
||
|
|
}>,
|
||
|
|
) => {
|
||
|
|
const connectedColumnsInfo: {
|
||
|
|
[tableName: string]: { [columnName: string]: { direction: "source" | "target" | "both" } };
|
||
|
|
} = {};
|
||
|
|
|
||
|
|
relationships.forEach((rel) => {
|
||
|
|
const { fromTable, toTable, fromColumns, toColumns } = rel;
|
||
|
|
|
||
|
|
// 소스 테이블의 컬럼들을 source로 표시
|
||
|
|
if (!connectedColumnsInfo[fromTable]) connectedColumnsInfo[fromTable] = {};
|
||
|
|
fromColumns.forEach((col: string) => {
|
||
|
|
if (connectedColumnsInfo[fromTable][col]) {
|
||
|
|
connectedColumnsInfo[fromTable][col].direction = "both";
|
||
|
|
} else {
|
||
|
|
connectedColumnsInfo[fromTable][col] = { direction: "source" };
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// 타겟 테이블의 컬럼들을 target으로 표시
|
||
|
|
if (!connectedColumnsInfo[toTable]) connectedColumnsInfo[toTable] = {};
|
||
|
|
toColumns.forEach((col: string) => {
|
||
|
|
if (connectedColumnsInfo[toTable][col]) {
|
||
|
|
connectedColumnsInfo[toTable][col].direction = "both";
|
||
|
|
} else {
|
||
|
|
connectedColumnsInfo[toTable][col] = { direction: "target" };
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
return connectedColumnsInfo;
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 노드 위치 추출
|
||
|
|
*/
|
||
|
|
export const extractNodePositions = (
|
||
|
|
nodes: Array<{
|
||
|
|
data: { table: { tableName: string } };
|
||
|
|
position: { x: number; y: number };
|
||
|
|
}>,
|
||
|
|
): { [tableName: string]: { x: number; y: number } } => {
|
||
|
|
const nodePositions: { [tableName: string]: { x: number; y: number } } = {};
|
||
|
|
|
||
|
|
nodes.forEach((node) => {
|
||
|
|
if (node.data?.table?.tableName) {
|
||
|
|
nodePositions[node.data.table.tableName] = {
|
||
|
|
x: node.position.x,
|
||
|
|
y: node.position.y,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
return nodePositions;
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 테이블명 목록 추출
|
||
|
|
*/
|
||
|
|
export const extractTableNames = (
|
||
|
|
nodes: Array<{
|
||
|
|
id: string;
|
||
|
|
data: { table: { tableName: string } };
|
||
|
|
}>,
|
||
|
|
): string[] => {
|
||
|
|
return nodes
|
||
|
|
.filter((node) => node.id.startsWith("table-"))
|
||
|
|
.map((node) => node.data.table.tableName)
|
||
|
|
.sort();
|
||
|
|
};
|