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 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | 3x 3x 3x | // src/utils/httpClient.js
import axios from "axios";
import { ApacuanaAPIError } from "../errors/index";
import { getConfig } from "../config/index";
let axiosInstance;
/**
* Inicializa el cliente HTTP (Axios) para todas las peticiones del SDK.
* @throws {Error} Si la configuración es incompleta.
*/
export const initHttpClient = () => {
const config = getConfig();
if (
!config.apiUrl ||
!config.secretKey ||
!config.apiKey ||
!config.verificationId
) {
throw new Error(
"HttpClient: Configuración de inicialización incompleta. Llama a apacuana.init() primero."
);
}
axiosInstance = axios.create({
baseURL: config.apiUrl,
headers: {
"APACUANA-API-Key": config.apiKey,
"APACUANA-SECRET-Key": config.secretKey,
// La cabecera Authorization se deja vacía al inicio.
// Se actualizará de forma dinámica con setAuthToken().
},
timeout: 30000,
});
// Configura los interceptores de Axios
axiosInstance.interceptors.response.use(
(response) => {
// Maneja errores lógicos de la API (si el backend devuelve status 2xx con { success: false })
if (response.data && response.data.success === false) {
const errorMessage =
response.data?.msg ||
response.data?.message ||
"Error lógico desconocido desde la API.";
throw new ApacuanaAPIError(
errorMessage,
response.status,
response.data.code || "LOGICAL_API_ERROR"
);
}
return response;
},
(error) => {
// Maneja errores HTTP (status 4xx, 5xx) o errores de red
// eslint-disable-next-line no-console
console.error(
"[HTTP Client] Interceptor de error de Axios:",
error.response || error.message
);
if (error.response) {
const { status, data } = error.response;
const errorMessage =
data?.msg || data?.message || "Error desconocido desde la API.";
throw new ApacuanaAPIError(
errorMessage,
status,
data?.code || "API_ERROR"
);
}
if (error.request) {
// La petición fue hecha, pero no se recibió respuesta (red caída, CORS, timeout)
throw new ApacuanaAPIError(
"Error de conexión a la red, timeout o CORS.",
0,
"NETWORK_ERROR"
);
} else {
// Algo más ocurrió al configurar la petición
throw new ApacuanaAPIError(
`Error desconocido en la petición: ${error.message}`,
0,
"UNKNOWN_REQUEST_ERROR"
);
}
}
);
};
/**
* Establece el token de autenticación Bearer para las peticiones subsiguientes.
* @param {string} token - El token de sesión del usuario.
* @throws {Error} Si el token es inválido o el cliente no está inicializado.
*/
export const setAuthToken = (token) => {
if (!axiosInstance) {
throw new Error(
"HttpClient no inicializado. Llama a apacuana.init() primero."
);
}
if (!token || typeof token !== "string") {
throw new Error("Token de sesión inválido.");
}
// Actualizamos la cabecera Authorization de la instancia de Axios.
axiosInstance.defaults.headers.common.Authorization = `Bearer ${token}`;
// eslint-disable-next-line no-console
};
/**
* Envía una petición HTTP a un endpoint de la API.
* Inyecta automáticamente los parámetros de inicialización en el cuerpo de la petición.
* @param {string} path - La ruta del endpoint de la API.
* @param {object} [data={}] - Los datos para enviar en la petición.
* @param {string} [method='POST'] - El método HTTP.
* @returns {Promise<object>} Los datos de la respuesta del backend.
* @throws {ApacuanaAPIError} Si la petición falla.
*/
export const httpRequest = async (path, data = {}, method = "POST") => {
if (!axiosInstance) {
throw new Error(
"Apacuana SDK: Cliente HTTP no inicializado. " +
"Llama a apacuana.init() primero."
);
}
let dataToSend;
const requestConfig = {};
if (typeof FormData !== "undefined" && data instanceof FormData) {
dataToSend = data;
} else {
const hasFile = Object.values(data).some(
(value) => typeof File !== "undefined" && value instanceof File
);
if (hasFile) {
const formData = new FormData();
Object.keys(data).forEach((key) => {
formData.append(key, data[key]);
});
dataToSend = formData;
} else {
dataToSend = { ...data };
}
}
try {
let response;
switch (method.toUpperCase()) {
case "GET":
response = await axiosInstance.get(path, { params: dataToSend });
break;
case "POST":
response = await axiosInstance.post(path, dataToSend, requestConfig);
break;
case "PUT":
response = await axiosInstance.put(path, dataToSend, requestConfig);
break;
case "DELETE":
response = await axiosInstance.delete(path, {
data: dataToSend,
...requestConfig,
});
break;
default:
throw new ApacuanaAPIError(
`Método HTTP no soportado: ${method}`,
405,
"UNSUPPORTED_HTTP_METHOD"
);
}
return response.data;
} catch (error) {
console.error(`[HTTP Client] Fallo en la petición a ${path}:`, error);
throw error;
}
};
|