import { json } from '@sveltejs/kit'; import { z } from 'zod'; import type { RequestHandler } from './$types'; import { requireAdmin } from '$lib/server/middleware/authorize.js'; import { discoverAll, type DiscoveryConfig } from '$lib/server/services/discoveryService.js'; import { success, error } from '$lib/server/utils/response.js'; const discoverConfigSchema = z.object({ dockerSocketPath: z.string().regex(/^[\w/.:-]+$/).optional(), traefikApiUrl: z.string().url().optional() }); /** * POST /api/admin/discover — Scan Docker and Traefik for services. Admin only. * * Body: { dockerSocketPath?: string, traefikApiUrl?: string } */ export const POST: RequestHandler = async (event) => { requireAdmin(event); let rawBody: unknown; try { rawBody = await event.request.json(); } catch { return json(error('Invalid JSON body'), { status: 400 }); } const parsed = discoverConfigSchema.safeParse(rawBody); if (!parsed.success) { return json(error(`Validation failed: ${parsed.error.issues.map((i) => i.message).join(', ')}`), { status: 400 }); } const config: DiscoveryConfig = { dockerSocketPath: parsed.data.dockerSocketPath || undefined, traefikApiUrl: parsed.data.traefikApiUrl || undefined }; if (!config.dockerSocketPath && !config.traefikApiUrl) { return json( error('At least one discovery source must be configured (dockerSocketPath or traefikApiUrl)'), { status: 400 } ); } try { const result = await discoverAll(config); return json(success(result)); } catch (err) { const message = err instanceof Error ? err.message : 'Discovery scan failed'; return json(error(message), { status: 500 }); } };