import { Body, Controller, Get, HttpCode, HttpStatus, Inject, Param, Post, Query, } from "@nestjs/common"; import { SwarmOptInInput, SwarmListQuery } from "@courtmitra/contracts"; import { parseOrThrow } from "../common/zod-validation.pipe.js"; import { SwarmService } from "./swarm.service.js"; @Controller() export class SwarmController { constructor(@Inject(SwarmService) private readonly swarm: SwarmService) {} /** * GET /api/swarms * List swarms with optional filters. */ @Get("swarms") async list(@Query() query: unknown) { const q = parseOrThrow(SwarmListQuery, query); return this.swarm.list({ domain: q.domain, entityId: q.entityId, status: q.status, }); } /** * GET /api/swarms/:id * Get a single swarm with entity info. */ @Get("swarms/:id") async get(@Param("id") id: string) { return this.swarm.get(id); } /** * GET /api/swarms/:id/dossier * Get the anonymized public dossier for a swarm. */ @Get("swarms/:id/dossier") async getDossier(@Param("id") id: string) { return this.swarm.getDossier(id); } /** * GET /api/swarms/:id/members * List members of a swarm. */ @Get("swarms/:id/members") async getMembers(@Param("id") id: string) { return this.swarm.getMembers(id); } /** * POST /api/missions/:missionId/swarm/opt-in * Opt a mission into a swarm with consent. */ @Post("missions/:missionId/swarm/opt-in") @HttpCode(HttpStatus.CREATED) async optIn( @Param("missionId") missionId: string, @Body() body: unknown, ) { const input = parseOrThrow(SwarmOptInInput, body); return this.swarm.optIn(missionId, input.swarmId, input); } /** * POST /api/admin/swarms/recluster * Trigger re-clustering of all active swarms (admin only). * TODO: emit swarm.recluster_requested event and implement worker function. */ @Post("admin/swarms/recluster") @HttpCode(HttpStatus.ACCEPTED) async recluster() { // TODO: emit swarm.recluster_requested event through WorkflowService // For now, return 501 Not Implemented to avoid fake acceptance. throw new Error("Re-clustering not yet implemented — use individual swarm opt-in."); } }