/** * API client for the orchestrator backend. */ import type { Job, ApiResponse, JobsListResponse, PipelineStatusResponse, JobSource, PipelineRun, AppSettings, ResumeProjectsSettings, UkVisaJobsSearchResponse, UkVisaJobsImportResponse, CreateJobInput, } from '../../shared/types'; const API_BASE = '/api'; async function fetchApi( endpoint: string, options?: RequestInit ): Promise { const response = await fetch(`${API_BASE}${endpoint}`, { ...options, headers: { 'Content-Type': 'application/json', ...options?.headers, }, }); const data: ApiResponse = await response.json(); if (!data.success) { throw new Error(data.error || 'API request failed'); } return data.data as T; } // Jobs API export async function getJobs(statuses?: string[]): Promise { const query = statuses?.length ? `?status=${statuses.join(',')}` : ''; return fetchApi(`/jobs${query}`); } export async function getJob(id: string): Promise { return fetchApi(`/jobs/${id}`); } export async function updateJob( id: string, update: Partial ): Promise { return fetchApi(`/jobs/${id}`, { method: 'PATCH', body: JSON.stringify(update), }); } export async function processJob(id: string, options?: { force?: boolean }): Promise { const query = options?.force ? '?force=1' : ''; return fetchApi(`/jobs/${id}/process${query}`, { method: 'POST', }); } export async function summarizeJob(id: string, options?: { force?: boolean }): Promise { const query = options?.force ? '?force=1' : ''; return fetchApi(`/jobs/${id}/summarize${query}`, { method: 'POST', }); } export async function generateJobPdf(id: string): Promise { return fetchApi(`/jobs/${id}/generate-pdf`, { method: 'POST', }); } export async function markAsApplied(id: string): Promise { return fetchApi(`/jobs/${id}/apply`, { method: 'POST', }); } export async function rejectJob(id: string): Promise { return fetchApi(`/jobs/${id}/reject`, { method: 'POST', }); } // Pipeline API export async function getPipelineStatus(): Promise { return fetchApi('/pipeline/status'); } export async function getPipelineRuns(): Promise { return fetchApi('/pipeline/runs'); } export async function runPipeline(config?: { topN?: number; minSuitabilityScore?: number; sources?: JobSource[]; }): Promise<{ message: string }> { return fetchApi<{ message: string }>('/pipeline/run', { method: 'POST', body: JSON.stringify(config || {}), }); } // UK Visa Jobs API export async function searchUkVisaJobs(input: { searchTerm?: string; page?: number; }): Promise { return fetchApi('/ukvisajobs/search', { method: 'POST', body: JSON.stringify(input), }); } export async function importUkVisaJobs(input: { jobs: CreateJobInput[]; }): Promise { return fetchApi('/ukvisajobs/import', { method: 'POST', body: JSON.stringify(input), }); } // Settings & Profile API export async function getSettings(): Promise { return fetchApi('/settings'); } export async function getProfileProjects(): Promise { return fetchApi('/profile/projects'); } export async function updateSettings(update: { model?: string | null modelScorer?: string | null modelTailoring?: string | null modelProjectSelection?: string | null pipelineWebhookUrl?: string | null jobCompleteWebhookUrl?: string | null resumeProjects?: ResumeProjectsSettings | null ukvisajobsMaxJobs?: number | null searchTerms?: string[] | null jobspyLocation?: string | null jobspyResultsWanted?: number | null jobspyHoursOld?: number | null jobspyCountryIndeed?: string | null jobspyLinkedinFetchDescription?: boolean | null }): Promise { return fetchApi('/settings', { method: 'PATCH', body: JSON.stringify(update), }); } // Database API export async function clearDatabase(): Promise<{ message: string; jobsDeleted: number; runsDeleted: number; }> { return fetchApi<{ message: string; jobsDeleted: number; runsDeleted: number; }>('/database', { method: 'DELETE', }); } export async function deleteJobsByStatus(status: string): Promise<{ message: string; count: number; }> { return fetchApi<{ message: string; count: number; }>(`/jobs/status/${status}`, { method: 'DELETE', }); } // Bulk operations (intentionally none - processing is manual)