improvement for the backend api

This commit is contained in:
ivannoskov
2025-11-19 12:56:04 +03:00
parent b0a9934220
commit d4672ea32b
40 changed files with 2383 additions and 3313 deletions

View File

@@ -89,8 +89,14 @@ const routeMockRequest = async (
if (endpoint === "/auth/init") {
return mockApiHandlers.authInit();
}
if (endpoint === "/auth/complete") {
return mockApiHandlers.authComplete(body);
if (endpoint.startsWith("/auth/complete")) {
// Extract token from query params
const token =
params.token ||
(endpoint.includes("?")
? new URLSearchParams(endpoint.split("?")[1]).get("token")
: null);
return mockApiHandlers.authComplete({ token });
}
if (endpoint === "/auth/refresh") {
return mockApiHandlers.authRefresh(body);
@@ -100,53 +106,51 @@ const routeMockRequest = async (
}
// Target Channels
if (endpoint === "/target-channels" && method === "GET") {
return mockApiHandlers.getTargetChannels(params);
if (endpoint === "/target_channels" && method === "GET") {
return mockApiHandlers.getTargetChannels();
}
if (endpoint.startsWith("/target-channels/") && method === "GET") {
const id = endpoint.split("/")[2];
return mockApiHandlers.getTargetChannel(id);
}
if (endpoint.startsWith("/target-channels/") && method === "PATCH") {
const id = endpoint.split("/")[2];
return mockApiHandlers.updateTargetChannel(id, body);
}
if (endpoint.startsWith("/target-channels/") && method === "DELETE") {
if (endpoint.startsWith("/target_channels/") && method === "DELETE") {
const id = endpoint.split("/")[2];
return mockApiHandlers.deleteTargetChannel(id);
}
// External Channels
if (endpoint === "/external-channels" && method === "GET") {
return mockApiHandlers.getExternalChannels(params);
if (endpoint.startsWith("/external_channels/target/") && method === "GET") {
const targetChannelId = endpoint.split("/")[3];
return mockApiHandlers.getExternalChannels(targetChannelId);
}
if (endpoint === "/external-channels" && method === "POST") {
if (endpoint === "/external_channels" && method === "POST") {
return mockApiHandlers.createExternalChannel(body);
}
if (
endpoint.startsWith("/external-channels/") &&
!endpoint.includes("/import") &&
endpoint.startsWith("/external_channels/") &&
!endpoint.includes("/target/") &&
!endpoint.includes("/links") &&
method === "GET"
) {
const id = endpoint.split("/")[2];
return mockApiHandlers.getExternalChannel(id);
}
if (endpoint.startsWith("/external-channels/") && method === "PATCH") {
if (
endpoint.startsWith("/external_channels/") &&
endpoint.includes("/links") &&
method === "PATCH"
) {
const id = endpoint.split("/")[2];
return mockApiHandlers.updateExternalChannelLinks(id, body);
}
if (
endpoint.startsWith("/external_channels/") &&
!endpoint.includes("/links") &&
method === "PATCH"
) {
const id = endpoint.split("/")[2];
return mockApiHandlers.updateExternalChannel(id, body);
}
if (endpoint.startsWith("/external-channels/") && method === "DELETE") {
if (endpoint.startsWith("/external_channels/") && method === "DELETE") {
const id = endpoint.split("/")[2];
return mockApiHandlers.deleteExternalChannel(id);
}
if (endpoint === "/external-channels/import" && method === "POST") {
// FormData для импорта
const formData = body as any;
return mockApiHandlers.importExternalChannels(
formData.file,
formData.target_channel_id
);
}
// Creatives
if (endpoint === "/creatives" && method === "GET") {
@@ -168,28 +172,36 @@ const routeMockRequest = async (
return mockApiHandlers.deleteCreative(id);
}
// Purchases
if (endpoint === "/purchases" && method === "GET") {
return mockApiHandlers.getPurchases(params);
// Placements
if (endpoint === "/placements" && method === "GET") {
return mockApiHandlers.getPlacements(params);
}
if (endpoint === "/purchases" && method === "POST") {
return mockApiHandlers.createPurchase(body);
if (endpoint === "/placements" && method === "POST") {
return mockApiHandlers.createPlacement(body);
}
if (endpoint.match(/^\/purchases\/[^\/]+$/) && method === "GET") {
if (endpoint.match(/^\/placements\/[^\/]+$/) && method === "GET") {
const id = endpoint.split("/")[2];
return mockApiHandlers.getPurchase(id);
return mockApiHandlers.getPlacement(id);
}
if (endpoint.match(/^\/purchases\/[^\/]+$/) && method === "PATCH") {
if (endpoint.match(/^\/placements\/[^\/]+$/) && method === "PATCH") {
const id = endpoint.split("/")[2];
return mockApiHandlers.updatePurchase(id, body);
return mockApiHandlers.updatePlacement(id, body);
}
if (endpoint.match(/^\/purchases\/[^\/]+$/) && method === "DELETE") {
if (endpoint.match(/^\/placements\/[^\/]+$/) && method === "DELETE") {
const id = endpoint.split("/")[2];
return mockApiHandlers.deletePurchase(id);
return mockApiHandlers.deletePlacement(id);
}
if (endpoint.includes("/refresh-views") && method === "POST") {
if (endpoint.includes("/views/fetch") && method === "POST") {
const id = endpoint.split("/")[2];
return mockApiHandlers.refreshPurchaseViews(id);
return mockApiHandlers.fetchPlacementViews(id);
}
if (endpoint.includes("/views/history") && method === "GET") {
const id = endpoint.split("/")[2];
return mockApiHandlers.getPlacementViewsHistory(id, params);
}
if (endpoint.includes("/views/manual") && method === "POST") {
const id = endpoint.split("/")[2];
return mockApiHandlers.setPlacementViewsManually(id, params?.views_count);
}
// Analytics
@@ -264,6 +276,27 @@ export const apiRequest = async <T = any>(
// Handle errors
if (!response.ok) {
// FastAPI returns errors in format { "detail": "..." }
// Transform to our ApiError format
if (data.detail) {
throw {
error: {
code:
response.status === 401
? "UNAUTHORIZED"
: response.status === 403
? "FORBIDDEN"
: response.status === 404
? "NOT_FOUND"
: response.status === 422
? "VALIDATION_ERROR"
: "API_ERROR",
message: data.detail,
},
detail: data.detail,
};
}
// If it's already in our format, throw as is
const error: ApiError = data;
throw error;
}
@@ -314,13 +347,7 @@ export const api = {
formData: FormData,
options?: RequestOptions
): Promise<T> => {
if (USE_MOCKS) {
// Handle mock file upload
const file = formData.get("file") as File;
const targetChannelId = formData.get("target_channel_id") as string;
return mockApiHandlers.importExternalChannels(file, targetChannelId) as T;
}
// File import is now done on client side, no need for mock handling
const url = `${API_URL}${endpoint}`;
const token = getAuthToken();