All files / web/src/api config.ts

95.65% Statements 44/46
91.3% Branches 21/23
100% Functions 1/1
95.65% Lines 44/46

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 591x     1x   1x 1x 1x 1x 1x 1x     1x 1x 59x 59x 1x     1x   1x 61x 61x   53x 53x   53x 53x 53x 61x   1x 1x 41x   41x 40x 5x 5x   35x 35x   36x 41x 1x 18x 8x 8x 8x 8x   10x 10x 18x 1x
import axios from 'axios'
import type { ApiResponse } from '@/types/api'
 
export const API_BASE_URL = import.meta.env.VITE_API_URL || ''
 
export const apiClient = axios.create({
  baseURL: API_BASE_URL,
  headers: {
    'Content-Type': 'application/json',
  },
})
 
// Request interceptor
apiClient.interceptors.request.use(
  (config) => {
    return config
  },
  (error) => {
    return Promise.reject(error)
  }
)
 
export const isApiResponse = (obj: any): obj is ApiResponse<any> => {
  if (!obj || typeof obj !== 'object') return false
  if (typeof obj.success !== 'boolean') return false
 
  const keys = Object.keys(obj)
  const allowedKeys = new Set(['success', 'data', 'message'])
 
  return keys.length > 0 &&
         keys.includes('success') &&
         keys.every(k => allowedKeys.has(k))
}
 
apiClient.interceptors.response.use(
  (response) => {
    const data = response.data
 
    if (isApiResponse(data)) {
      if (!data.success) {
        return Promise.reject(new Error(data.message || 'Request failed'))
      }
 
      response.data = data.data
    }
 
    return response
  },
  (error) => {
    if (error.response?.data && isApiResponse(error.response.data)) {
      const apiError = error.response.data
      console.error('API Error:', apiError.message || error.message)
      return Promise.reject(new Error(apiError.message || error.message))
    }
 
    console.error('API Error:', error)
    return Promise.reject(error)
  }
)