add vikunja integration
This commit is contained in:
112
backend/src/services/vikunja.service.ts
Normal file
112
backend/src/services/vikunja.service.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import axios from 'axios';
|
||||
import environment from '../config/environment';
|
||||
import logger from '../utils/logger';
|
||||
|
||||
export interface VikunjaTask {
|
||||
id: number;
|
||||
title: string;
|
||||
done: boolean;
|
||||
due_date: string | null;
|
||||
priority: number;
|
||||
project_id: number;
|
||||
}
|
||||
|
||||
export interface VikunjaProject {
|
||||
id: number;
|
||||
title: string;
|
||||
}
|
||||
|
||||
function buildHeaders(): Record<string, string> {
|
||||
return {
|
||||
'Authorization': `Bearer ${environment.vikunja.apiToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
}
|
||||
|
||||
async function getMyTasks(): Promise<VikunjaTask[]> {
|
||||
const { vikunja } = environment;
|
||||
if (!vikunja.url) {
|
||||
throw new Error('VIKUNJA_URL is not configured');
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await axios.get<VikunjaTask[]>(
|
||||
`${vikunja.url}/api/v1/tasks/all`,
|
||||
{ headers: buildHeaders() },
|
||||
);
|
||||
return (response.data ?? []).filter((t) => !t.done);
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
logger.error('Vikunja getMyTasks failed', {
|
||||
status: error.response?.status,
|
||||
statusText: error.response?.statusText,
|
||||
});
|
||||
}
|
||||
logger.error('VikunjaService.getMyTasks failed', { error });
|
||||
throw new Error('Failed to fetch Vikunja tasks');
|
||||
}
|
||||
}
|
||||
|
||||
async function getOverdueTasks(): Promise<VikunjaTask[]> {
|
||||
const tasks = await getMyTasks();
|
||||
const now = new Date();
|
||||
return tasks.filter((t) => {
|
||||
if (!t.due_date) return false;
|
||||
return new Date(t.due_date) < now;
|
||||
});
|
||||
}
|
||||
|
||||
async function getProjects(): Promise<VikunjaProject[]> {
|
||||
const { vikunja } = environment;
|
||||
if (!vikunja.url) {
|
||||
throw new Error('VIKUNJA_URL is not configured');
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await axios.get<VikunjaProject[]>(
|
||||
`${vikunja.url}/api/v1/projects`,
|
||||
{ headers: buildHeaders() },
|
||||
);
|
||||
return response.data ?? [];
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
logger.error('Vikunja getProjects failed', {
|
||||
status: error.response?.status,
|
||||
statusText: error.response?.statusText,
|
||||
});
|
||||
}
|
||||
logger.error('VikunjaService.getProjects failed', { error });
|
||||
throw new Error('Failed to fetch Vikunja projects');
|
||||
}
|
||||
}
|
||||
|
||||
async function createTask(projectId: number, title: string, dueDate?: string): Promise<VikunjaTask> {
|
||||
const { vikunja } = environment;
|
||||
if (!vikunja.url) {
|
||||
throw new Error('VIKUNJA_URL is not configured');
|
||||
}
|
||||
|
||||
try {
|
||||
const body: Record<string, unknown> = { title };
|
||||
if (dueDate) {
|
||||
body.due_date = dueDate;
|
||||
}
|
||||
const response = await axios.put<VikunjaTask>(
|
||||
`${vikunja.url}/api/v1/projects/${projectId}/tasks`,
|
||||
body,
|
||||
{ headers: buildHeaders() },
|
||||
);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
logger.error('Vikunja createTask failed', {
|
||||
status: error.response?.status,
|
||||
statusText: error.response?.statusText,
|
||||
});
|
||||
}
|
||||
logger.error('VikunjaService.createTask failed', { error });
|
||||
throw new Error('Failed to create Vikunja task');
|
||||
}
|
||||
}
|
||||
|
||||
export default { getMyTasks, getOverdueTasks, getProjects, createTask };
|
||||
Reference in New Issue
Block a user