deleting a stack shows which folders will be removed, with a choice to keep/delete folders

This commit is contained in:
jarek committed 2026-08-09 10:31:28 +02:00
1 parent 4375f42415
commit 3859888da6
6 files changed
+274 -27

No files matched your search

+5 -2
View File
@@ -10,6 +10,9 @@ export const DELETE: RequestHandler = async (event) => {
const force = url.searchParams.get('force') === 'true';
const volumes = url.searchParams.get('volumes') === 'true';
// files defaults to true (backward-compatible: old callers with no param still delete
// files). The delete modal passes files=false for "Remove stack" (keep files on disk).
const files = url.searchParams.get('files') !== 'false';
const envId = url.searchParams.get('env');
const envIdNum = envId ? parseInt(envId) : undefined;
@@ -25,10 +28,10 @@ export const DELETE: RequestHandler = async (event) => {
try {
const stackName = decodeURIComponent(params.name);
const result = await removeStack(stackName, envIdNum, force, volumes);
const result = await removeStack(stackName, envIdNum, force, volumes, files);
// Audit log
await auditStack(event, 'delete', stackName, envIdNum, { force, volumes });
await auditStack(event, 'delete', stackName, envIdNum, { force, volumes, files });
if (!result.success) {
return json({ success: false, error: result.error }, { status: 400 });
@@ -0,0 +1,31 @@
import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
import { computeStackDeletionPaths } from '$lib/server/stacks';
import { authorize } from '$lib/server/authorize';
// GET /api/stacks/[name]/delete-preview?env=N
// Returns the on-disk directories a delete-with-files would remove, so the confirm modal
// shows the user EXACTLY what the backend will delete (same source of truth — no drift).
export const GET: RequestHandler = async ({ params, url, cookies }) => {
const auth = await authorize(cookies);
const envId = url.searchParams.get('env');
const envIdNum = envId ? parseInt(envId) : undefined;
if (auth.authEnabled && !(await auth.can('stacks', 'remove', envIdNum))) {
return json({ error: 'Permission denied' }, { status: 403 });
}
const { name } = params;
try {
const { stackDir, gitDir, sourceType, namedVolumes } = await computeStackDeletionPaths(name, envIdNum);
return json({
stackName: name,
sourceType, // internal | git | external | null
stackDir, // absolute path, or null if Dockhand won't delete files
gitDir, // absolute path of the cloned git repo dir, or null
namedVolumes, // compose-managed named volumes removed by "also delete volumes"
canDeleteFiles: !!(stackDir || gitDir),
});
} catch (error: any) {
return json({ error: error.message || 'Failed to compute deletion preview' }, { status: 500 });
}
};