/** * 노드 플로우 API */ import { apiClient } from "./client"; export interface NodeFlow { flowId: number; flowName: string; flowDescription: string; flowData: string | any; // JSONB는 문자열 또는 객체로 반환될 수 있음 createdAt: string; updatedAt: string; } interface ApiResponse { success: boolean; data?: T; message?: string; } /** * 플로우 목록 조회 */ export async function getNodeFlows(): Promise { const response = await apiClient.get>("/dataflow/node-flows"); if (response.data.success && response.data.data) { return response.data.data; } throw new Error(response.data.message || "플로우 목록을 불러올 수 없습니다."); } /** * 플로우 상세 조회 */ export async function getNodeFlow(flowId: number): Promise { const response = await apiClient.get>(`/dataflow/node-flows/${flowId}`); if (response.data.success && response.data.data) { return response.data.data; } throw new Error(response.data.message || "플로우를 불러올 수 없습니다."); } /** * 플로우 저장 (신규) */ export async function createNodeFlow(data: { flowName: string; flowDescription: string; flowData: string; }): Promise<{ flowId: number }> { const response = await apiClient.post>("/dataflow/node-flows", data); if (response.data.success && response.data.data) { return response.data.data; } throw new Error(response.data.message || "플로우를 저장할 수 없습니다."); } /** * 플로우 수정 */ export async function updateNodeFlow(data: { flowId: number; flowName: string; flowDescription: string; flowData: string; }): Promise<{ flowId: number }> { const response = await apiClient.put>("/dataflow/node-flows", data); if (response.data.success && response.data.data) { return response.data.data; } throw new Error(response.data.message || "플로우를 수정할 수 없습니다."); } /** * 플로우 삭제 */ export async function deleteNodeFlow(flowId: number): Promise { const response = await apiClient.delete>(`/dataflow/node-flows/${flowId}`); if (!response.data.success) { throw new Error(response.data.message || "플로우를 삭제할 수 없습니다."); } } /** * 플로우 실행 */ export async function executeNodeFlow(flowId: number, contextData: Record): Promise { const response = await apiClient.post>( `/dataflow/node-flows/${flowId}/execute`, contextData, ); if (response.data.success && response.data.data) { return response.data.data; } throw new Error(response.data.message || "플로우를 실행할 수 없습니다."); } /** * 플로우 실행 결과 인터페이스 */ export interface ExecutionResult { success: boolean; message: string; executionTime: number; nodes: NodeExecutionSummary[]; summary: { total: number; success: number; failed: number; skipped: number; }; } export interface NodeExecutionSummary { nodeId: string; nodeName: string; nodeType: string; status: "success" | "failed" | "skipped" | "pending"; duration?: number; error?: string; } /** * 플로우 소스 테이블 정보 인터페이스 */ export interface FlowSourceTableInfo { sourceTable: string | null; sourceNodeType: string | null; sourceNodeId?: string; displayName?: string; message?: string; } /** * 플로우 소스 테이블 조회 * 플로우의 첫 번째 소스 노드(tableSource, externalDBSource)에서 테이블명 추출 */ export async function getFlowSourceTable(flowId: number): Promise { try { const response = await apiClient.get>( `/dataflow/node-flows/${flowId}/source-table`, ); if (response.data.success && response.data.data) { return response.data.data; } return { sourceTable: null, sourceNodeType: null, message: response.data.message || "소스 테이블 정보를 가져올 수 없습니다.", }; } catch (error) { console.error("플로우 소스 테이블 조회 실패:", error); return { sourceTable: null, sourceNodeType: null, message: "API 호출 중 오류가 발생했습니다.", }; } }