Commit 2: REST-API für Geräte und Dienste (Zod-Validierung, Drizzle-Repositories)

This commit is contained in:
2026-07-19 01:53:43 +02:00
parent 3a7f423f60
commit a5b998b421
11 changed files with 418 additions and 5 deletions

View File

@@ -0,0 +1,53 @@
import type { FastifyInstance } from "fastify";
import { DeviceCreateSchema, DeviceUpdateSchema } from "@launchpad/shared";
import * as deviceRepo from "../db/repositories/devices.js";
import * as serviceRepo from "../db/repositories/services.js";
export async function deviceRoutes(app: FastifyInstance): Promise<void> {
app.get("/api/devices", async () => {
return deviceRepo.listDevices().map((device) => ({
...device,
services: serviceRepo.listServicesByDevice(device.id),
}));
});
app.get("/api/devices/:id", async (request, reply) => {
const { id } = request.params as { id: string };
const device = deviceRepo.getDevice(id);
if (!device) {
return reply.code(404).send({ error: "Gerät nicht gefunden" });
}
return { ...device, services: serviceRepo.listServicesByDevice(id) };
});
app.post("/api/devices", async (request, reply) => {
const parsed = DeviceCreateSchema.safeParse(request.body);
if (!parsed.success) {
return reply.code(400).send({ error: "Ungültige Eingabe", issues: parsed.error.issues });
}
const device = deviceRepo.createDevice(parsed.data);
return reply.code(201).send(device);
});
app.patch("/api/devices/:id", async (request, reply) => {
const { id } = request.params as { id: string };
const parsed = DeviceUpdateSchema.safeParse(request.body);
if (!parsed.success) {
return reply.code(400).send({ error: "Ungültige Eingabe", issues: parsed.error.issues });
}
const device = deviceRepo.updateDevice(id, parsed.data);
if (!device) {
return reply.code(404).send({ error: "Gerät nicht gefunden" });
}
return device;
});
app.delete("/api/devices/:id", async (request, reply) => {
const { id } = request.params as { id: string };
const deleted = deviceRepo.deleteDevice(id);
if (!deleted) {
return reply.code(404).send({ error: "Gerät nicht gefunden" });
}
return reply.code(204).send();
});
}

View File

@@ -0,0 +1,67 @@
import type { FastifyInstance } from "fastify";
import { ServiceCreateSchema, ServiceUpdateSchema } from "@launchpad/shared";
import * as deviceRepo from "../db/repositories/devices.js";
import * as serviceRepo from "../db/repositories/services.js";
interface ServiceListQuery {
deviceId?: string;
category?: string;
favorite?: string;
}
export async function serviceRoutes(app: FastifyInstance): Promise<void> {
app.get("/api/services", async (request) => {
const query = request.query as ServiceListQuery;
return serviceRepo.listServices({
deviceId: query.deviceId,
category: query.category,
favorite: query.favorite === undefined ? undefined : query.favorite === "true",
});
});
app.get("/api/services/:id", async (request, reply) => {
const { id } = request.params as { id: string };
const service = serviceRepo.getService(id);
if (!service) {
return reply.code(404).send({ error: "Dienst nicht gefunden" });
}
return service;
});
app.post("/api/services", async (request, reply) => {
const parsed = ServiceCreateSchema.safeParse(request.body);
if (!parsed.success) {
return reply.code(400).send({ error: "Ungültige Eingabe", issues: parsed.error.issues });
}
const device = deviceRepo.getDevice(parsed.data.deviceId);
if (!device) {
return reply.code(400).send({ error: `Gerät ${parsed.data.deviceId} existiert nicht` });
}
const service = serviceRepo.createService(parsed.data);
return reply.code(201).send(service);
});
app.patch("/api/services/:id", async (request, reply) => {
const { id } = request.params as { id: string };
const parsed = ServiceUpdateSchema.safeParse(request.body);
if (!parsed.success) {
return reply.code(400).send({ error: "Ungültige Eingabe", issues: parsed.error.issues });
}
const service = serviceRepo.updateService(id, parsed.data);
if (!service) {
return reply.code(404).send({ error: "Dienst nicht gefunden" });
}
return service;
});
app.delete("/api/services/:id", async (request, reply) => {
const { id } = request.params as { id: string };
const deleted = serviceRepo.deleteService(id);
if (!deleted) {
return reply.code(404).send({ error: "Dienst nicht gefunden" });
}
return reply.code(204).send();
});
}