ERP-node/frontend/lib/api/externalCall.ts

195 lines
5.0 KiB
TypeScript

/**
* 외부 호출 API 클라이언트
*/
// 백엔드 타입과 동일한 인터페이스 정의
export interface ExternalCallResult {
success: boolean;
statusCode?: number;
response?: string;
error?: string;
executionTime: number;
timestamp: string;
}
export interface ExternalCallTestRequest {
settings: Record<string, unknown>;
templateData?: Record<string, unknown>;
}
export interface ExternalCallExecuteRequest {
diagramId: number;
relationshipId: string;
settings: Record<string, unknown>;
templateData?: Record<string, unknown>;
}
export interface ValidationResult {
valid: boolean;
errors: string[];
}
/**
* 외부 호출 API 클래스
*/
// API URL 동적 설정 - 기존 client.ts와 동일한 로직
const getApiBaseUrl = (): string => {
// 1. 환경변수가 있으면 우선 사용
if (process.env.NEXT_PUBLIC_API_URL) {
return process.env.NEXT_PUBLIC_API_URL;
}
// 2. 클라이언트 사이드에서 동적 설정
if (typeof window !== "undefined") {
const currentHost = window.location.hostname;
const currentPort = window.location.port;
// 로컬 개발환경: localhost:9771 또는 localhost:3000 → localhost:8080
if (
(currentHost === "localhost" || currentHost === "127.0.0.1") &&
(currentPort === "9771" || currentPort === "3000")
) {
return "http://localhost:8080/api";
}
}
// 3. 기본값
return "http://localhost:8080/api";
};
export class ExternalCallAPI {
private static readonly BASE_URL = `${getApiBaseUrl()}/external-calls`;
/**
* 외부 호출 테스트 실행
*/
static async testExternalCall(request: ExternalCallTestRequest): Promise<{
success: boolean;
result?: ExternalCallResult;
error?: string;
}> {
try {
const response = await fetch(`${this.BASE_URL}/test`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(request),
});
// 응답이 JSON인지 확인
const contentType = response.headers.get("content-type");
if (!contentType || !contentType.includes("application/json")) {
const text = await response.text();
throw new Error(`서버에서 JSON이 아닌 응답을 반환했습니다: ${text.substring(0, 100)}...`);
}
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || `HTTP ${response.status}`);
}
return data;
} catch (error) {
console.error("외부 호출 테스트 실패:", error);
return {
success: false,
error: error instanceof Error ? error.message : "알 수 없는 오류가 발생했습니다.",
};
}
}
/**
* 외부 호출 실행
*/
static async executeExternalCall(request: ExternalCallExecuteRequest): Promise<{
success: boolean;
result?: ExternalCallResult;
error?: string;
}> {
try {
const response = await fetch(`${this.BASE_URL}/execute`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(request),
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || `HTTP ${response.status}`);
}
return data;
} catch (error) {
console.error("외부 호출 실행 실패:", error);
return {
success: false,
error: error instanceof Error ? error.message : "알 수 없는 오류가 발생했습니다.",
};
}
}
/**
* 지원되는 외부 호출 타입 목록 조회
*/
static async getSupportedTypes(): Promise<{
success: boolean;
supportedTypes?: Record<string, any>;
error?: string;
}> {
try {
const response = await fetch(`${this.BASE_URL}/types`);
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || `HTTP ${response.status}`);
}
return data;
} catch (error) {
console.error("지원 타입 조회 실패:", error);
return {
success: false,
error: error instanceof Error ? error.message : "알 수 없는 오류가 발생했습니다.",
};
}
}
/**
* 외부 호출 설정 검증
*/
static async validateSettings(settings: Record<string, unknown>): Promise<{
success: boolean;
validation?: ValidationResult;
error?: string;
}> {
try {
const response = await fetch(`${this.BASE_URL}/validate`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ settings }),
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || `HTTP ${response.status}`);
}
return data;
} catch (error) {
console.error("설정 검증 실패:", error);
return {
success: false,
error: error instanceof Error ? error.message : "알 수 없는 오류가 발생했습니다.",
};
}
}
}