2026-06-26 10:50:24 +02:00
|
|
|
|
/**
|
|
|
|
|
|
* Projects Routes – CRUD for projects
|
|
|
|
|
|
*/
|
|
|
|
|
|
import type { FastifyInstance } from 'fastify';
|
|
|
|
|
|
import type { DatabaseInterface, DBProject } from '../database/DatabaseInterface.js';
|
2026-06-30 11:32:33 +02:00
|
|
|
|
import { requireAuth } from '../auth/authMiddleware.js';
|
|
|
|
|
|
import type { AuthService } from '../auth/AuthService.js';
|
2026-06-26 10:50:24 +02:00
|
|
|
|
|
2026-06-30 11:32:33 +02:00
|
|
|
|
export function registerProjectRoutes(fastify: FastifyInstance, db: DatabaseInterface, authService: AuthService) {
|
2026-06-30 12:16:49 +02:00
|
|
|
|
// List projects owned by the authenticated user
|
2026-06-30 11:32:33 +02:00
|
|
|
|
fastify.get('/api/projects', async (request, reply) => {
|
2026-06-30 12:16:49 +02:00
|
|
|
|
const user = requireAuth(request, reply, authService);
|
|
|
|
|
|
if (!user) return;
|
|
|
|
|
|
return db.listProjects(user.id);
|
2026-06-26 10:50:24 +02:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Get single project
|
|
|
|
|
|
fastify.get('/api/projects/:id', async (request, reply) => {
|
2026-06-30 11:32:33 +02:00
|
|
|
|
if (!requireAuth(request, reply, authService)) return;
|
2026-06-26 10:50:24 +02:00
|
|
|
|
const { id } = request.params as { id: string };
|
|
|
|
|
|
const project = db.getProject(id);
|
|
|
|
|
|
if (!project) return reply.code(404).send({ error: 'Project not found' });
|
|
|
|
|
|
return project;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Create project
|
|
|
|
|
|
fastify.post('/api/projects', async (request, reply) => {
|
2026-06-30 12:16:49 +02:00
|
|
|
|
const user = requireAuth(request, reply, authService);
|
|
|
|
|
|
if (!user) return;
|
2026-06-26 10:50:24 +02:00
|
|
|
|
const body = request.body as Partial<DBProject>;
|
|
|
|
|
|
if (!body.name) return reply.code(400).send({ error: 'Name is required' });
|
2026-06-30 12:16:49 +02:00
|
|
|
|
return reply.code(201).send(db.createProject({ ...body, owner_id: user.id }));
|
2026-06-26 10:50:24 +02:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Update project
|
|
|
|
|
|
fastify.patch('/api/projects/:id', async (request, reply) => {
|
2026-06-30 11:32:33 +02:00
|
|
|
|
if (!requireAuth(request, reply, authService)) return;
|
2026-06-26 10:50:24 +02:00
|
|
|
|
const { id } = request.params as { id: string };
|
|
|
|
|
|
const body = request.body as Partial<DBProject>;
|
|
|
|
|
|
const updated = db.updateProject(id, body);
|
|
|
|
|
|
if (!updated) return reply.code(404).send({ error: 'Project not found' });
|
|
|
|
|
|
return updated;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Delete project
|
|
|
|
|
|
fastify.delete('/api/projects/:id', async (request, reply) => {
|
2026-06-30 11:32:33 +02:00
|
|
|
|
if (!requireAuth(request, reply, authService)) return;
|
2026-06-26 10:50:24 +02:00
|
|
|
|
const { id } = request.params as { id: string };
|
|
|
|
|
|
const ok = db.deleteProject(id);
|
|
|
|
|
|
if (!ok) return reply.code(404).send({ error: 'Project not found' });
|
|
|
|
|
|
return reply.code(204).send();
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|