snp-batch-validation/frontend/src/api/bypassApi.ts
HYOJIN 9c393f9137 fix: JSON 샘플 파싱 시 이중 직렬화 문제 수정
parseJson API 호출 시 이미 JSON 문자열인 body를
JSON.stringify로 다시 감싸는 문제 수정

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 16:31:13 +09:00

131 lines
4.0 KiB
TypeScript

// API 응답 타입
interface ApiResponse<T> {
success: boolean;
message: string;
data: T;
errorCode?: string;
}
// 타입 정의
export interface BypassParamDto {
id?: number;
paramName: string;
paramType: string; // STRING, INTEGER, LONG, BOOLEAN
paramIn: string; // PATH, QUERY, BODY
required: boolean;
description: string;
sortOrder: number;
}
export interface BypassFieldDto {
id?: number;
fieldName: string;
jsonProperty: string | null;
fieldType: string; // String, Integer, Long, Double, Boolean, LocalDateTime, List<Object>, Object
description: string;
sortOrder: number;
}
export interface BypassConfigRequest {
domainName: string;
displayName: string;
webclientBean: string;
externalPath: string;
httpMethod: string;
responseType: string;
description: string;
params: BypassParamDto[];
fields: BypassFieldDto[];
}
export interface BypassConfigResponse {
id: number;
domainName: string;
displayName: string;
webclientBean: string;
externalPath: string;
httpMethod: string;
responseType: string;
description: string;
generated: boolean;
generatedAt: string | null;
createdAt: string;
updatedAt: string;
params: BypassParamDto[];
fields: BypassFieldDto[];
}
export interface CodeGenerationResult {
controllerPath: string;
servicePath: string;
dtoPath: string;
message: string;
}
export interface WebClientBeanInfo {
name: string;
description: string;
}
// BASE URL
const BASE = '/snp-api/api/bypass-config';
// 헬퍼 함수 (batchApi.ts 패턴과 동일)
async function fetchJson<T>(url: string): Promise<T> {
const res = await fetch(url);
if (!res.ok) throw new Error(`API Error: ${res.status} ${res.statusText}`);
return res.json();
}
async function postJson<T>(url: string, body?: unknown): Promise<T> {
const res = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: body != null ? JSON.stringify(body) : undefined,
});
if (!res.ok) throw new Error(`API Error: ${res.status} ${res.statusText}`);
return res.json();
}
async function putJson<T>(url: string, body?: unknown): Promise<T> {
const res = await fetch(url, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: body != null ? JSON.stringify(body) : undefined,
});
if (!res.ok) throw new Error(`API Error: ${res.status} ${res.statusText}`);
return res.json();
}
async function deleteJson<T>(url: string): Promise<T> {
const res = await fetch(url, { method: 'DELETE' });
if (!res.ok) throw new Error(`API Error: ${res.status} ${res.statusText}`);
return res.json();
}
export const bypassApi = {
getConfigs: () =>
fetchJson<ApiResponse<BypassConfigResponse[]>>(BASE),
getConfig: (id: number) =>
fetchJson<ApiResponse<BypassConfigResponse>>(`${BASE}/${id}`),
createConfig: (data: BypassConfigRequest) =>
postJson<ApiResponse<BypassConfigResponse>>(BASE, data),
updateConfig: (id: number, data: BypassConfigRequest) =>
putJson<ApiResponse<BypassConfigResponse>>(`${BASE}/${id}`, data),
deleteConfig: (id: number) =>
deleteJson<ApiResponse<void>>(`${BASE}/${id}`),
generateCode: (id: number, force = false) =>
postJson<ApiResponse<CodeGenerationResult>>(`${BASE}/${id}/generate?force=${force}`),
parseJson: async (jsonSample: string): Promise<ApiResponse<BypassFieldDto[]>> => {
const res = await fetch(`${BASE}/parse-json`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: jsonSample, // 이미 JSON 문자열이므로 JSON.stringify 하지 않음
});
if (!res.ok) throw new Error(`API Error: ${res.status} ${res.statusText}`);
return res.json();
},
getWebclientBeans: () =>
fetchJson<ApiResponse<WebClientBeanInfo[]>>(`${BASE}/webclient-beans`),
};