import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import type { CursorPage, DownloaderInstance, DownloaderInstanceCreate, DownloaderInstanceUpdate, InstanceTestResult, LibraryRoot, LibraryRootCreate, LibraryRootUpdate, MediaServerInstance, MediaServerInstanceCreate, MediaServerInstanceUpdate, PathMapping, PathMappingCreate, PathMappingUpdate, Site, SiteAccount, SiteAccountUpdate, SiteCreate, SiteCredentialsPut, SiteCredentialsResult, SiteUpdate, StorageInstance, StorageInstanceCreate, StorageInstanceUpdate, StorageTestResult, } from "@umt/contracts"; import { apiData } from "~/lib/api.ts"; import { type QueryArea, qk } from "~/lib/query-keys.ts"; import { fetchAllCursorPages } from "./parse.ts"; /** 实例类资源的标准 CRUD 钩子(列表按游标取齐配置) */ function crudHooks(area: QueryArea, base: string) { return { useList: () => useQuery({ queryKey: qk.list(area), queryFn: ({ signal }) => fetchAllCursorPages((cursor) => apiData>(base, { params: { limit: 200, cursor }, signal })), }), useCreate: () => { const qc = useQueryClient(); return useMutation({ mutationFn: (body: Create) => apiData(base, { method: "POST", body }), onSuccess: () => qc.invalidateQueries({ queryKey: qk.all(area) }), }); }, useUpdate: () => { const qc = useQueryClient(); return useMutation({ mutationFn: ({ id, body }: { id: string; body: Update }) => apiData(`${base}/{id}`, { method: "PATCH", pathParams: { id }, body }), onSuccess: () => qc.invalidateQueries({ queryKey: qk.all(area) }), }); }, useRemove: () => { const qc = useQueryClient(); return useMutation({ mutationFn: (id: string) => apiData(`${base}/{id}`, { method: "DELETE", pathParams: { id } }), onSuccess: () => qc.invalidateQueries({ queryKey: qk.all(area) }), }); }, }; } /** 连接测试 / 校验类动作(结果写回 health,完成后刷新列表) */ function actionHook(area: QueryArea, path: string) { return () => { const qc = useQueryClient(); return useMutation({ mutationFn: (id: string) => apiData(path, { method: "POST", pathParams: { id }, body: {} }), onSettled: () => qc.invalidateQueries({ queryKey: qk.all(area) }), }); }; } /** Alist / OpenList 存储实例 */ export const storages = { ...crudHooks( "storage-instances", "/storage-instances", ), useTest: actionHook("storage-instances", "/storage-instances/{id}/test"), }; export const downloaders = { ...crudHooks( "downloader-instances", "/downloader-instances", ), useTest: actionHook("downloader-instances", "/downloader-instances/{id}/test"), }; export const mediaServers = { ...crudHooks( "media-server-instances", "/media-server-instances", ), useTest: actionHook("media-server-instances", "/media-server-instances/{id}/test"), }; export const libraryRoots = { ...crudHooks("library-roots", "/library-roots"), useTest: actionHook("library-roots", "/library-roots/{id}/test"), }; export const pathMappings = { ...crudHooks("path-mappings", "/path-mappings"), useVerify: actionHook("path-mappings", "/path-mappings/{id}/verify"), }; // ─── 站点账号凭证(设置页录入;站点本身由站点工作台管理) ─── export function useSiteOptions() { return useQuery({ queryKey: qk.list("sites", { limit: 200 }), queryFn: ({ signal }) => fetchAllCursorPages((cursor) => apiData>("/sites", { params: { limit: 200, cursor }, signal })), }); } export function useSiteAccounts() { return useQuery({ queryKey: qk.list("site-accounts"), queryFn: ({ signal }) => fetchAllCursorPages((cursor) => apiData>("/site-accounts", { params: { limit: 200, cursor }, signal }), ), }); } export function usePutSiteCredentials() { const qc = useQueryClient(); return useMutation({ mutationFn: ({ siteId, body }: { siteId: string; body: SiteCredentialsPut }) => apiData("/sites/{id}/credentials", { method: "PUT", pathParams: { id: siteId }, body }), onSuccess: () => { qc.invalidateQueries({ queryKey: qk.all("site-accounts") }); qc.invalidateQueries({ queryKey: qk.all("sites") }); }, }); } // ─── 站点登记与参数(设置"站点与账号";浏览在站点工作台) ─── function useInvalidateSites() { const qc = useQueryClient(); return () => { // sites.ts 用 ["sites", …],这里的列表用 qk.list("sites"),两者同前缀 qc.invalidateQueries({ queryKey: qk.all("sites") }); qc.invalidateQueries({ queryKey: qk.all("site-accounts") }); }; } export function useCreateSite() { const inv = useInvalidateSites(); return useMutation({ mutationFn: (body: SiteCreate) => apiData("/sites", { method: "POST", body }), onSuccess: inv, }); } export function useUpdateSite() { const inv = useInvalidateSites(); return useMutation({ mutationFn: ({ id, body }: { id: string; body: SiteUpdate }) => apiData("/sites/{id}", { method: "PATCH", pathParams: { id }, body }), onSuccess: inv, }); } export function useUpdateSiteAccount() { const inv = useInvalidateSites(); return useMutation({ mutationFn: ({ id, body }: { id: string; body: SiteAccountUpdate }) => apiData("/site-accounts/{id}", { method: "PATCH", pathParams: { id }, body }), onSuccess: inv, }); } export function useRemoveSiteAccount() { const inv = useInvalidateSites(); return useMutation({ mutationFn: (id: string) => apiData("/site-accounts/{id}", { method: "DELETE", pathParams: { id } }), onSuccess: inv, }); }