c41e5063b7
Removed entire kbx-foundation-v36 directory as it's been replaced by the new KBX Foundation v4 patterns implemented in this session: - Registry-driven screen definitions - Density-aware UI adapter components - Feature module templates (ShadowRun, Models) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
64 lines
2.0 KiB
TypeScript
64 lines
2.0 KiB
TypeScript
import axios, { AxiosError, type AxiosRequestConfig } from 'axios'
|
|
import { isKbxProblem, kbxUnexpectedProblem, type KbxProblem, type KbxSystemProblem } from '@kbx/contracts'
|
|
|
|
export const kbxHttp = axios.create({
|
|
timeout: 30_000,
|
|
headers: { 'X-KBX-Client': 'web' },
|
|
})
|
|
|
|
kbxHttp.interceptors.request.use(config => {
|
|
config.headers['X-Correlation-Id'] ??= crypto.randomUUID()
|
|
return config
|
|
})
|
|
|
|
kbxHttp.interceptors.response.use(
|
|
response => response,
|
|
(error: AxiosError) => {
|
|
const correlationId = String(error.config?.headers?.['X-Correlation-Id'] ?? crypto.randomUUID())
|
|
|
|
if (!error.response) {
|
|
const problem: KbxSystemProblem = {
|
|
type: 'system',
|
|
code: 'NETWORK_UNAVAILABLE',
|
|
title: '서버와 연결할 수 없습니다.',
|
|
detail: '입력한 내용은 유지됩니다. 네트워크 상태를 확인한 후 다시 시도하세요.',
|
|
correlationId,
|
|
retryable: true,
|
|
}
|
|
return Promise.reject(problem)
|
|
}
|
|
|
|
const data = error.response.data
|
|
if (isKbxProblem(data)) {
|
|
const problem: KbxProblem = {
|
|
...data,
|
|
correlationId: data.correlationId ?? correlationId,
|
|
}
|
|
return Promise.reject(problem)
|
|
}
|
|
|
|
if (error.response.status === 403) {
|
|
return Promise.reject({
|
|
type: 'permission', code: 'PERMISSION_DENIED', title: '이 작업을 수행할 권한이 없습니다.', correlationId,
|
|
} satisfies KbxProblem)
|
|
}
|
|
if (error.response.status === 404) {
|
|
return Promise.reject({
|
|
type: 'not-found', code: 'RESOURCE_NOT_FOUND', title: '요청한 데이터를 찾을 수 없습니다.', correlationId,
|
|
} satisfies KbxProblem)
|
|
}
|
|
|
|
return Promise.reject(kbxUnexpectedProblem(correlationId, `HTTP ${error.response.status}`, error.response.status >= 500))
|
|
},
|
|
)
|
|
|
|
export function withIdempotency(config: AxiosRequestConfig = {}, key = crypto.randomUUID()): AxiosRequestConfig {
|
|
return {
|
|
...config,
|
|
headers: {
|
|
...(config.headers ?? {}),
|
|
'Idempotency-Key': key,
|
|
},
|
|
}
|
|
}
|