import { json } from '@sveltejs/kit'; import type { RequestHandler } from './$types'; import { getEnvironment, updateEnvironment, deleteEnvironment, getEnvironmentPublicIps, setEnvironmentPublicIp, deleteEnvironmentPublicIp, deleteEnvUpdateCheckSettings, getGitStacksForEnvironmentOnly, deleteGitStack } from '$lib/server/db'; import { clearDockerClientCache } from '$lib/server/docker'; import { deleteGitStackFiles } from '$lib/server/git'; import { authorize } from '$lib/server/authorize'; import { refreshSubprocessEnvironments } from '$lib/server/subprocess-manager'; import { serializeLabels, parseLabels, MAX_LABELS } from '$lib/utils/label-colors'; import { unregisterSchedule } from '$lib/server/scheduler'; import { closeEdgeConnection } from '$lib/server/hawser'; export const GET: RequestHandler = async ({ params, cookies }) => { const auth = await authorize(cookies); if (auth.authEnabled && !await auth.can('environments', 'view')) { return json({ error: 'Permission denied' }, { status: 403 }); } try { const id = parseInt(params.id); const env = await getEnvironment(id); if (!env) { return json({ error: 'Environment not found' }, { status: 404 }); } // Get public IP for this environment const publicIps = await getEnvironmentPublicIps(); const publicIp = publicIps[id.toString()] || null; // Parse labels from JSON string to array return json({ ...env, labels: parseLabels(env.labels as string | null), publicIp }); } catch (error) { console.error('Failed to get environment:', error); return json({ error: 'Failed to get environment' }, { status: 500 }); } }; export const PUT: RequestHandler = async ({ params, request, cookies }) => { const auth = await authorize(cookies); if (auth.authEnabled && !await auth.can('environments', 'edit')) { return json({ error: 'Permission denied' }, { status: 403 }); } try { const id = parseInt(params.id); const data = await request.json(); // Clear cached Docker client before updating clearDockerClientCache(id); // Handle labels - only update if provided in the request const labels = data.labels !== undefined ? serializeLabels(Array.isArray(data.labels) ? data.labels.slice(0, MAX_LABELS) : []) : undefined; const env = await updateEnvironment(id, { name: data.name, host: data.host, port: data.port, protocol: data.protocol, tlsCa: data.tlsCa, tlsCert: data.tlsCert, tlsKey: data.tlsKey, icon: data.icon, socketPath: data.socketPath, collectActivity: data.collectActivity, collectMetrics: data.collectMetrics, highlightChanges: data.highlightChanges, labels: labels, connectionType: data.connectionType, hawserToken: data.hawserToken }); if (!env) { return json({ error: 'Environment not found' }, { status: 404 }); } // Notify subprocesses if collectActivity or collectMetrics setting changed if (data.collectActivity !== undefined || data.collectMetrics !== undefined) { refreshSubprocessEnvironments(); } // Handle public IP - update if provided in request if (data.publicIp !== undefined) { await setEnvironmentPublicIp(id, data.publicIp || null); } // Get current public IP for response const publicIps = await getEnvironmentPublicIps(); const publicIp = publicIps[id.toString()] || null; // Parse labels from JSON string to array return json({ ...env, labels: parseLabels(env.labels as string | null), publicIp }); } catch (error) { console.error('Failed to update environment:', error); return json({ error: 'Failed to update environment' }, { status: 500 }); } }; export const DELETE: RequestHandler = async ({ params, cookies }) => { const auth = await authorize(cookies); if (auth.authEnabled && !await auth.can('environments', 'delete')) { return json({ error: 'Permission denied' }, { status: 403 }); } try { const id = parseInt(params.id); // Close Edge connection if this is a Hawser Edge environment // This rejects any pending requests and closes the WebSocket closeEdgeConnection(id); // Clear cached Docker client before deleting clearDockerClientCache(id); // Clean up git stacks for this environment const gitStacks = await getGitStacksForEnvironmentOnly(id); for (const stack of gitStacks) { // Unregister schedule if auto-update was enabled if (stack.autoUpdate) { unregisterSchedule(stack.id, 'git_stack_sync'); } // Delete git stack files from filesystem deleteGitStackFiles(stack.id); // Delete git stack from database await deleteGitStack(stack.id); } const success = await deleteEnvironment(id); if (!success) { return json({ error: 'Cannot delete this environment' }, { status: 400 }); } // Clean up public IP entry for this environment await deleteEnvironmentPublicIp(id); // Clean up update check settings and unregister schedule await deleteEnvUpdateCheckSettings(id); unregisterSchedule(id, 'env_update_check'); // Notify subprocesses to stop collecting from deleted environment refreshSubprocessEnvironments(); return json({ success: true }); } catch (error) { console.error('Failed to delete environment:', error); return json({ error: 'Failed to delete environment' }, { status: 500 }); } };