import api from '../api/client'; import { MigrationReviewQueueItem, MigrationErrorItem, PaginatedResponse, MigrationReviewStatus, CommitBatchDto, } from '@/types/migration'; interface WrappedData { data?: unknown; } const extractNestedData = (value: unknown): T => { let current: unknown = value; for (let i = 0; i < 5; i += 1) { if (!current || typeof current !== 'object' || !('data' in current)) { return current as T; } current = (current as WrappedData).data; } return current as T; }; const normalizePaginatedResponse = (value: unknown): PaginatedResponse => { const extracted = extractNestedData(value); if (!extracted || typeof extracted !== 'object') { return { items: [], total: 0, page: 1, limit: 0, totalPages: 0, }; } const response = extracted as Partial> & { data?: unknown }; if (Array.isArray(response.items)) { return { items: response.items, total: response.total ?? response.items.length, page: response.page ?? 1, limit: response.limit ?? response.items.length, totalPages: response.totalPages ?? 1, }; } if (Array.isArray(response.data)) { return { items: response.data as T[], total: response.total ?? response.data.length, page: response.page ?? 1, limit: response.limit ?? response.data.length, totalPages: response.totalPages ?? 1, }; } return { items: [], total: 0, page: 1, limit: 0, totalPages: 0, }; }; export const migrationService = { getReviewQueue: async (params: { page?: number; limit?: number; status?: MigrationReviewStatus; }): Promise> => { const { data } = await api.get('/migration/queue', { params }); return normalizePaginatedResponse(data); }, getQueueItem: async (id: number): Promise => { const { data } = await api.get(`/migration/queue/${id}`); return extractNestedData(data); }, getErrors: async (params: { page?: number; limit?: number }): Promise> => { const { data } = await api.get('/migration/errors', { params }); return normalizePaginatedResponse(data); }, approveQueueItem: async (id: number, payload: Record, idempotencyKey: string) => { const { data } = await api.post(`/migration/queue/${id}/approve`, payload, { headers: { 'idempotency-key': idempotencyKey, }, }); return data?.data || data; }, rejectQueueItem: async (id: number) => { const { data } = await api.post(`/migration/queue/${id}/reject`); return data?.data || data; }, commitBatch: async (payload: CommitBatchDto, idempotencyKey: string) => { const { data } = await api.post(`/migration/commit_batch`, payload, { headers: { 'idempotency-key': idempotencyKey, }, }); return data?.data || data; }, getStagingFileUrl: (filePath: string) => { // Generate the URL directly since it returns a file stream. // Ensure we encode the file path correctly. // It assumes your axios baseURL is set to your nestjs API. // If working with raw or