2026-07-23 05:11:16 +02:00
|
|
|
/**
|
2026-07-23 19:01:18 +02:00
|
|
|
* Plugin management hooks: list, install, activate, deactivate, uninstall, upload, install-url.
|
2026-07-23 05:11:16 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
|
|
|
import { apiGet, apiPost, apiDelete } from './client';
|
|
|
|
|
|
2026-07-24 14:23:28 +02:00
|
|
|
// ── Types matching backend schemas ──
|
|
|
|
|
|
2026-07-23 05:11:16 +02:00
|
|
|
export interface Plugin {
|
|
|
|
|
name: string;
|
2026-07-24 14:23:28 +02:00
|
|
|
display_name: string;
|
|
|
|
|
version: string;
|
2026-07-23 05:11:16 +02:00
|
|
|
status: 'discovered' | 'installed' | 'active' | 'inactive';
|
2026-07-24 14:23:28 +02:00
|
|
|
installed: boolean;
|
|
|
|
|
active: boolean;
|
|
|
|
|
description: string;
|
|
|
|
|
dependencies: string[];
|
|
|
|
|
events: string[];
|
|
|
|
|
migrations: string[];
|
|
|
|
|
permissions: string[];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface PluginListResponse {
|
|
|
|
|
plugins: Plugin[];
|
|
|
|
|
total: number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface PluginActionResponse {
|
|
|
|
|
name: string;
|
|
|
|
|
display_name: string;
|
|
|
|
|
version: string;
|
|
|
|
|
status: string;
|
|
|
|
|
installed: boolean;
|
|
|
|
|
active: boolean;
|
|
|
|
|
dropped_tables: string[];
|
|
|
|
|
message: string;
|
2026-07-23 05:11:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function usePlugins() {
|
|
|
|
|
return useQuery({
|
|
|
|
|
queryKey: ['plugins'],
|
|
|
|
|
queryFn: async () => {
|
2026-07-24 14:23:28 +02:00
|
|
|
const data = await apiGet<PluginListResponse>('/plugins');
|
|
|
|
|
return data.plugins;
|
2026-07-23 05:11:16 +02:00
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function useInstallPlugin() {
|
|
|
|
|
const queryClient = useQueryClient();
|
|
|
|
|
return useMutation({
|
2026-07-24 14:23:28 +02:00
|
|
|
mutationFn: (name: string) => apiPost<PluginActionResponse>(`/plugins/${name}/install`),
|
2026-07-23 05:11:16 +02:00
|
|
|
onSuccess: () => {
|
|
|
|
|
queryClient.invalidateQueries({ queryKey: ['plugins'] });
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function useActivatePlugin() {
|
|
|
|
|
const queryClient = useQueryClient();
|
|
|
|
|
return useMutation({
|
2026-07-24 14:23:28 +02:00
|
|
|
mutationFn: (name: string) => apiPost<PluginActionResponse>(`/plugins/${name}/activate`),
|
2026-07-23 05:11:16 +02:00
|
|
|
onSuccess: () => {
|
|
|
|
|
queryClient.invalidateQueries({ queryKey: ['plugins'] });
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function useDeactivatePlugin() {
|
|
|
|
|
const queryClient = useQueryClient();
|
|
|
|
|
return useMutation({
|
2026-07-24 14:23:28 +02:00
|
|
|
mutationFn: (name: string) => apiPost<PluginActionResponse>(`/plugins/${name}/deactivate`),
|
2026-07-23 05:11:16 +02:00
|
|
|
onSuccess: () => {
|
|
|
|
|
queryClient.invalidateQueries({ queryKey: ['plugins'] });
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function useUninstallPlugin() {
|
|
|
|
|
const queryClient = useQueryClient();
|
|
|
|
|
return useMutation({
|
|
|
|
|
mutationFn: ({ name, removeData }: { name: string; removeData: boolean }) =>
|
2026-07-24 14:23:28 +02:00
|
|
|
apiDelete<PluginActionResponse>(`/plugins/${name}?remove_data=${removeData}`),
|
2026-07-23 05:11:16 +02:00
|
|
|
onSuccess: () => {
|
|
|
|
|
queryClient.invalidateQueries({ queryKey: ['plugins'] });
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
2026-07-23 19:01:18 +02:00
|
|
|
|
|
|
|
|
export function useUploadPlugin() {
|
|
|
|
|
const queryClient = useQueryClient();
|
|
|
|
|
return useMutation({
|
|
|
|
|
mutationFn: async (file: File) => {
|
|
|
|
|
const formData = new FormData();
|
|
|
|
|
formData.append('file', file);
|
|
|
|
|
const { default: apiClient } = await import('./client');
|
2026-07-24 08:19:45 +02:00
|
|
|
const res = await apiClient.post('/plugins/upload', formData, {
|
2026-07-23 19:01:18 +02:00
|
|
|
headers: { 'Content-Type': 'multipart/form-data' },
|
|
|
|
|
});
|
2026-07-24 14:23:28 +02:00
|
|
|
return res.data as PluginActionResponse;
|
2026-07-23 19:01:18 +02:00
|
|
|
},
|
|
|
|
|
onSuccess: () => {
|
|
|
|
|
queryClient.invalidateQueries({ queryKey: ['plugins'] });
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function useInstallPluginFromUrl() {
|
|
|
|
|
const queryClient = useQueryClient();
|
|
|
|
|
return useMutation({
|
|
|
|
|
mutationFn: async (url: string) => {
|
|
|
|
|
const { default: apiClient } = await import('./client');
|
2026-07-24 08:19:45 +02:00
|
|
|
const res = await apiClient.post('/plugins/install-url', { url });
|
2026-07-24 14:23:28 +02:00
|
|
|
return res.data as PluginActionResponse;
|
2026-07-23 19:01:18 +02:00
|
|
|
},
|
|
|
|
|
onSuccess: () => {
|
|
|
|
|
queryClient.invalidateQueries({ queryKey: ['plugins'] });
|
|
|
|
|
},
|
|
|
|
|
});
|
2026-07-24 14:23:28 +02:00
|
|
|
}
|