A deployable markdown editor that connects with your self hosted files and lets you edit in a beautiful interface
at main 106 lines 3.8 kB view raw
1import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; 2import { reposApi } from '../api'; 3 4export function useRepositories(sortBy: 'updated' | 'created' | 'name' = 'updated') { 5 return useQuery({ 6 queryKey: ['repositories', sortBy], 7 queryFn: () => reposApi.listRepositories(sortBy), 8 }); 9} 10 11export function useFiles( 12 owner: string, 13 repo: string, 14 path: string = '', 15 branch: string = '', 16 extensions: string[] = ['md', 'mdx'] 17) { 18 return useQuery({ 19 queryKey: ['files', owner, repo, path, branch, extensions], 20 queryFn: () => reposApi.listFiles(owner, repo, path, branch, extensions), 21 enabled: !!owner && !!repo, 22 // Extended cache configuration for performance 23 staleTime: 5 * 60 * 1000, // 5 min - aligns with backend cache 24 gcTime: 10 * 60 * 1000, // 10 min - keep in cache longer 25 refetchOnMount: false, // Don't refetch if data is fresh 26 refetchOnReconnect: false, // Don't refetch on reconnect 27 }); 28} 29 30export function useFileContent( 31 owner: string, 32 repo: string, 33 path: string, 34 branch: string = '' 35) { 36 return useQuery({ 37 queryKey: ['file-content', owner, repo, path, branch], 38 queryFn: () => reposApi.getFileContent(owner, repo, path, branch), 39 enabled: !!owner && !!repo && !!path, 40 }); 41} 42 43export function useCreateFile(owner: string, repo: string) { 44 const queryClient = useQueryClient(); 45 46 return useMutation({ 47 mutationFn: ({ path, content, message }: { path: string; content?: string; message?: string }) => 48 reposApi.createFile(owner, repo, path, content, message), 49 onSuccess: () => { 50 // Invalidate and refetch files query and pending changes 51 queryClient.invalidateQueries({ queryKey: ['files', owner, repo] }); 52 queryClient.invalidateQueries({ queryKey: ['pending-changes', owner, repo] }); 53 }, 54 }); 55} 56 57export function useCreateFolder(owner: string, repo: string) { 58 const queryClient = useQueryClient(); 59 60 return useMutation({ 61 mutationFn: ({ path, message }: { path: string; message?: string }) => 62 reposApi.createFolder(owner, repo, path, message), 63 onSuccess: () => { 64 // Invalidate and refetch files query and pending changes 65 queryClient.invalidateQueries({ queryKey: ['files', owner, repo] }); 66 queryClient.invalidateQueries({ queryKey: ['pending-changes', owner, repo] }); 67 }, 68 }); 69} 70 71export function useRenameItem(owner: string, repo: string) { 72 const queryClient = useQueryClient(); 73 74 return useMutation({ 75 mutationFn: ({ oldPath, newPath, message }: { oldPath: string; newPath: string; message?: string }) => 76 reposApi.renameItem(owner, repo, oldPath, newPath, message), 77 onSuccess: () => { 78 // Invalidate and refetch files query and pending changes 79 queryClient.invalidateQueries({ queryKey: ['files', owner, repo] }); 80 queryClient.invalidateQueries({ queryKey: ['pending-changes', owner, repo] }); 81 }, 82 }); 83} 84 85export function usePendingChanges(owner: string, repo: string) { 86 return useQuery({ 87 queryKey: ['pending-changes', owner, repo], 88 queryFn: () => reposApi.getPendingChanges(owner, repo), 89 enabled: !!owner && !!repo, 90 refetchInterval: 5000, // Refetch every 5 seconds to keep in sync 91 }); 92} 93 94export function useDiscardChanges(owner: string, repo: string) { 95 const queryClient = useQueryClient(); 96 97 return useMutation({ 98 mutationFn: () => reposApi.discardChanges(owner, repo), 99 onSuccess: () => { 100 // Invalidate and refetch all related queries 101 queryClient.invalidateQueries({ queryKey: ['pending-changes', owner, repo] }); 102 queryClient.invalidateQueries({ queryKey: ['files', owner, repo] }); 103 queryClient.invalidateQueries({ queryKey: ['branchStatus', owner, repo] }); 104 }, 105 }); 106}