Files
kandev/apps/web/lib/http/index.ts
T
2026-01-14 20:52:22 +00:00

186 lines
5.6 KiB
TypeScript

import { getBackendConfig } from '@/lib/config';
import type {
BoardSnapshot,
ListAgentsResponse,
ListAgentDiscoveryResponse,
ListBoardsResponse,
ListEnvironmentsResponse,
ListExecutorsResponse,
ListRepositoriesResponse,
ListWorkspacesResponse,
Comment,
ListCommentsResponse,
RepositoryBranchesResponse,
Task,
UserSettingsResponse,
Workspace,
} from '@/lib/types/http';
export type ApiRequestOptions = {
baseUrl?: string;
cache?: RequestCache;
init?: RequestInit;
};
function resolveUrl(pathOrUrl: string, baseUrl: string) {
if (pathOrUrl.startsWith('http://') || pathOrUrl.startsWith('https://')) {
return pathOrUrl;
}
return `${baseUrl}${pathOrUrl}`;
}
async function fetchJson<T>(pathOrUrl: string, options?: ApiRequestOptions): Promise<T> {
const baseUrl = options?.baseUrl ?? getBackendConfig().apiBaseUrl;
const response = await fetch(resolveUrl(pathOrUrl, baseUrl), {
...options?.init,
cache: options?.cache,
headers: {
'Content-Type': 'application/json',
...(options?.init?.headers ?? {}),
},
});
if (!response.ok) {
throw new Error(`Request failed: ${response.status} ${response.statusText}`);
}
if (response.status === 204) {
return undefined as T;
}
const text = await response.text();
if (!text) {
return undefined as T;
}
return JSON.parse(text) as T;
}
export async function createWorkspace(
payload: { name: string; description?: string },
options?: ApiRequestOptions
) {
return fetchJson<Workspace>('/api/v1/workspaces', {
...options,
init: { method: 'POST', body: JSON.stringify(payload), ...(options?.init ?? {}) },
});
}
export async function listWorkspaces(options?: ApiRequestOptions) {
return fetchJson<ListWorkspacesResponse>('/api/v1/workspaces', options);
}
export async function listBoards(workspaceId: string, options?: ApiRequestOptions) {
const baseUrl = options?.baseUrl ?? getBackendConfig().apiBaseUrl;
const url = new URL(`${baseUrl}/api/v1/boards`);
url.searchParams.set('workspace_id', workspaceId);
return fetchJson<ListBoardsResponse>(url.toString(), options);
}
export async function fetchBoardSnapshot(boardId: string, options?: ApiRequestOptions) {
return fetchJson<BoardSnapshot>(`/api/v1/boards/${boardId}/snapshot`, options);
}
export async function listRepositories(workspaceId: string, options?: ApiRequestOptions) {
return fetchJson<ListRepositoriesResponse>(`/api/v1/workspaces/${workspaceId}/repositories`, options);
}
export async function listRepositoryBranches(repositoryId: string, options?: ApiRequestOptions) {
return fetchJson<RepositoryBranchesResponse>(`/api/v1/repositories/${repositoryId}/branches`, options);
}
export async function createTask(
payload: {
workspace_id: string;
board_id: string;
column_id: string;
title: string;
description?: string;
position?: number;
repository_url?: string;
branch?: string;
agent_profile_id?: string;
environment_id?: string;
executor_id?: string;
state?: Task['state'];
},
options?: ApiRequestOptions
) {
return fetchJson<Task>('/api/v1/tasks', {
...options,
init: { method: 'POST', body: JSON.stringify(payload), ...(options?.init ?? {}) },
});
}
export async function updateTask(
taskId: string,
payload: {
title?: string;
description?: string;
position?: number;
agent_profile_id?: string;
assigned_to?: string;
state?: Task['state'];
},
options?: ApiRequestOptions
) {
return fetchJson<Task>(`/api/v1/tasks/${taskId}`, {
...options,
init: { method: 'PATCH', body: JSON.stringify(payload), ...(options?.init ?? {}) },
});
}
export async function deleteTask(taskId: string, options?: ApiRequestOptions) {
return fetchJson<void>(`/api/v1/tasks/${taskId}`, {
...options,
init: { method: 'DELETE', ...(options?.init ?? {}) },
});
}
export async function moveTask(
taskId: string,
payload: { board_id: string; column_id: string; position: number },
options?: ApiRequestOptions
) {
return fetchJson<Task>(`/api/v1/tasks/${taskId}/move`, {
...options,
init: { method: 'POST', body: JSON.stringify(payload), ...(options?.init ?? {}) },
});
}
export async function fetchUserSettings(options?: ApiRequestOptions) {
return fetchJson<UserSettingsResponse>('/api/v1/user/settings', options);
}
export async function updateUserSettings(
payload: { workspace_id: string; board_id: string; repository_ids: string[] },
options?: ApiRequestOptions
) {
return fetchJson<UserSettingsResponse>('/api/v1/user/settings', {
...options,
init: { method: 'PATCH', body: JSON.stringify(payload), ...(options?.init ?? {}) },
});
}
export async function fetchTask(taskId: string, options?: ApiRequestOptions) {
return fetchJson<Task>(`/api/v1/tasks/${taskId}`, options);
}
export async function listTaskComments(taskId: string, options?: ApiRequestOptions) {
return fetchJson<ListCommentsResponse>(`/api/v1/tasks/${taskId}/comments`, options);
}
export async function listExecutors(options?: ApiRequestOptions): Promise<ListExecutorsResponse> {
return fetchJson<ListExecutorsResponse>('/api/v1/executors', options);
}
export async function listEnvironments(options?: ApiRequestOptions): Promise<ListEnvironmentsResponse> {
return fetchJson<ListEnvironmentsResponse>('/api/v1/environments', options);
}
export async function listAgents(options?: ApiRequestOptions): Promise<ListAgentsResponse> {
return fetchJson<ListAgentsResponse>('/api/v1/agents', options);
}
export async function listAgentDiscovery(
options?: ApiRequestOptions
): Promise<ListAgentDiscoveryResponse> {
return fetchJson<ListAgentDiscoveryResponse>('/api/v1/agents/discovery', options);
}