Files
cameleer-server/ui/src/api/queries/admin/environments.ts
hsiegeln 7e47f1628d
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m23s
CI / docker (push) Successful in 1m9s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 40s
feat: JAR retention policy with nightly cleanup job
Per-environment "keep last N versions" setting (default 5, null for
unlimited). Nightly scheduled job at 03:00 deletes old versions from
both database and disk, skipping any version that is currently deployed.

Full stack:
- V6 migration: adds jar_retention_count column to environments
- Environment record, repository, service, admin controller endpoint
- JarRetentionJob: @Scheduled nightly, iterates environments and apps
- UI: retention policy editor on admin Environments page with
  toggle between limited/unlimited and version count input
- AppVersionRepository.delete() for version cleanup

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 19:06:28 +02:00

90 lines
2.6 KiB
TypeScript

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { adminFetch } from './admin-api';
export interface Environment {
id: string;
slug: string;
displayName: string;
production: boolean;
enabled: boolean;
defaultContainerConfig: Record<string, unknown>;
jarRetentionCount: number | null;
createdAt: string;
}
export interface CreateEnvironmentRequest {
slug: string;
displayName: string;
production: boolean;
}
export interface UpdateEnvironmentRequest {
displayName: string;
production: boolean;
enabled: boolean;
}
export function useEnvironments() {
return useQuery({
queryKey: ['admin', 'environments'],
queryFn: () => adminFetch<Environment[]>('/environments'),
});
}
export function useCreateEnvironment() {
const qc = useQueryClient();
return useMutation({
mutationFn: (req: CreateEnvironmentRequest) =>
adminFetch<Environment>('/environments', {
method: 'POST',
body: JSON.stringify(req),
}),
onSuccess: () => qc.invalidateQueries({ queryKey: ['admin', 'environments'] }),
});
}
export function useUpdateEnvironment() {
const qc = useQueryClient();
return useMutation({
mutationFn: ({ id, ...req }: UpdateEnvironmentRequest & { id: string }) =>
adminFetch<Environment>(`/environments/${id}`, {
method: 'PUT',
body: JSON.stringify(req),
}),
onSuccess: () => qc.invalidateQueries({ queryKey: ['admin', 'environments'] }),
});
}
export function useUpdateDefaultContainerConfig() {
const qc = useQueryClient();
return useMutation({
mutationFn: ({ id, config }: { id: string; config: Record<string, unknown> }) =>
adminFetch<Environment>(`/environments/${id}/default-container-config`, {
method: 'PUT',
body: JSON.stringify(config),
}),
onSuccess: () => qc.invalidateQueries({ queryKey: ['admin', 'environments'] }),
});
}
export function useUpdateJarRetention() {
const qc = useQueryClient();
return useMutation({
mutationFn: ({ id, jarRetentionCount }: { id: string; jarRetentionCount: number | null }) =>
adminFetch<Environment>(`/environments/${id}/jar-retention`, {
method: 'PUT',
body: JSON.stringify({ jarRetentionCount }),
}),
onSuccess: () => qc.invalidateQueries({ queryKey: ['admin', 'environments'] }),
});
}
export function useDeleteEnvironment() {
const qc = useQueryClient();
return useMutation({
mutationFn: (id: string) =>
adminFetch<void>(`/environments/${id}`, { method: 'DELETE' }),
onSuccess: () => qc.invalidateQueries({ queryKey: ['admin', 'environments'] }),
});
}