refactor: Decouple frontend API calls from a shared client instance

This commit is contained in:
2025-12-04 21:59:39 +01:00
parent d06fc133e7
commit 4308ff220b
13 changed files with 248 additions and 136 deletions
+104 -4
View File
@@ -1,4 +1,5 @@
import api from './api';
export { api };
import type {
ApiTokenRecord,
AssetResponse,
@@ -6,11 +7,12 @@ import type {
CapabilitySetResponse,
DownloadLink,
DocumentResponse,
FolderTreeNode,
Identifier,
PasskeySummary,
TenantSnippet,
TagResponse,
CorrespondentResponse,
FolderTreeResponseItem,
} from './apiTypes';
import type { AxiosError, AxiosInstance, InternalAxiosRequestConfig, AxiosRequestConfig } from 'axios';
@@ -56,7 +58,7 @@ const normalizeDownload = (input?: DownloadLink | null): DownloadLink | null =>
export const fetchDocument = async (id: Identifier): Promise<DocumentResponse> => {
const { data } = await api.get<{ document?: DocumentResponse }>(`/documents/${id}`);
const doc = data?.document || (data as unknown as DocumentResponse);
const doc = data?.document || (data as DocumentResponse);
if (doc?.current_version?.download) {
doc.current_version.download = normalizeDownload(doc.current_version.download);
}
@@ -77,8 +79,8 @@ export const listDocuments = async (params: Record<string, unknown> = {}): Promi
return Array.isArray(data) ? data : [];
};
export const getFolderTree = async (): Promise<FolderTreeNode[]> => {
const { data } = await api.get<FolderTreeNode[]>('/folders/tree');
export const getFolderTree = async (): Promise<FolderTreeResponseItem[]> => {
const { data } = await api.get<FolderTreeResponseItem[]>('/folders/tree');
return Array.isArray(data) ? data : [];
};
@@ -342,4 +344,102 @@ api.interceptors.response.use(
},
);
export const uploadDocument = async (
formData: FormData,
): Promise<{ reused?: boolean; document?: unknown; status?: number }> => {
const { data, status } = await api.post<{ reused?: boolean; document?: unknown }>('/documents', formData);
return { ...data, status };
};
export const resolveFolderPath = async (
payload: { parent_id?: Identifier | null; segments: string[] },
): Promise<{ folder?: { id?: Identifier | null } }> => {
const { data } = await api.post<{ folder?: { id?: Identifier | null } }>('/folders/path', payload);
return data;
};
export const bulkTagDocuments = async (
payload: { document_ids: Identifier[]; tag_ids: Identifier[]; action: 'add' | 'remove' },
): Promise<void> => {
await api.post('/documents/bulk/tags', payload);
};
export const bulkReanalyzeDocuments = async (
payload: { document_ids: Identifier[]; force?: boolean },
): Promise<{ queued?: number }> => {
const { data } = await api.post<{ queued?: number }>('/documents/bulk/reanalyze', payload);
return data;
};
export const listTags = async (): Promise<TagResponse[]> => {
const { data } = await api.get<TagResponse[]>('/tags');
return Array.isArray(data) ? data : [];
};
export const updateTag = async (
tagId: Identifier,
payload: { label?: string; color?: string | null },
): Promise<void> => {
await api.patch(`/tags/${tagId}`, payload);
};
export const deleteTag = async (tagId: Identifier): Promise<void> => {
await api.delete(`/tags/${tagId}`);
};
export const listCorrespondents = async (): Promise<CorrespondentResponse[]> => {
const { data } = await api.get<CorrespondentResponse[]>('/correspondents');
return Array.isArray(data) ? data : [];
};
export const createCorrespondent = async (payload: { name: string }): Promise<CorrespondentResponse> => {
const { data } = await api.post<CorrespondentResponse>('/correspondents', payload);
return data;
};
export const updateCorrespondent = async (
correspondentId: Identifier,
payload: { name?: string },
): Promise<void> => {
await api.patch(`/correspondents/${correspondentId}`, payload);
};
export const deleteCorrespondent = async (correspondentId: Identifier): Promise<void> => {
await api.delete(`/correspondents/${correspondentId}`);
};
export const addDocumentCorrespondent = async (
documentId: Identifier,
correspondentId: Identifier,
): Promise<void> => {
await api.post(`/documents/${documentId}/correspondents`, {
assignments: [{ correspondent_id: correspondentId }],
replace: false,
});
};
export const removeDocumentCorrespondent = async (
documentId: Identifier,
correspondentId: Identifier,
): Promise<void> => {
await api.delete(`/documents/${documentId}/correspondents/${correspondentId}`);
};
export const switchTenant = async (tenantId: Identifier): Promise<{ access_token: string; tenant: any; tenants?: any[] }> => {
const { data } = await api.post<{ access_token: string; tenant: any; tenants?: any[] }>('/auth/select-tenant', {
tenant_id: tenantId,
});
return data;
};
export const listFolderContents = async <T = any>(
path: string,
params?: Record<string, unknown>,
): Promise<T> => {
const { data } = await api.get<T>(`/folders/${path}/contents`, { params });
return data;
};
export type { ApiTokenRecord } from './apiTypes';
+5 -1
View File
@@ -14,7 +14,7 @@ export interface TagResponse {
color?: string | null;
}
interface CorrespondentResponse {
export interface CorrespondentResponse {
id: string;
name: string;
metadata: Record<string, unknown>;
@@ -69,6 +69,10 @@ export interface FolderTreeNode extends FolderInfo {
children?: FolderTreeNode[];
}
export interface FolderTreeResponseItem extends FolderInfo {
children?: string[];
}
export interface CapabilitySetResponse {
id: string;
slug: string;