A deployable markdown editor that connects with your self hosted files and lets you edit in a beautiful interface
1import { apiClient } from './client';
2import type { Repository, FileNode, FileContent } from '../types/api';
3
4export const reposApi = {
5 listRepositories: async (sortBy: 'updated' | 'created' | 'name' = 'updated'): Promise<Repository[]> => {
6 const { data } = await apiClient.get<{ repositories: Repository[] }>('/api/repos', {
7 params: { sort: sortBy },
8 });
9 return data.repositories;
10 },
11
12 listFiles: async (
13 owner: string,
14 repo: string,
15 path: string = '',
16 branch: string = '',
17 extensions: string[] = []
18 ): Promise<{ files: FileNode[]; current_branch: string }> => {
19 const { data } = await apiClient.get<{ files: FileNode[]; current_branch: string }>(
20 `/api/repos/${owner}/${repo}/files`,
21 {
22 params: {
23 path,
24 branch,
25 extensions: extensions.length > 0 ? extensions.join(',') : undefined,
26 },
27 }
28 );
29 return data;
30 },
31
32 getFileContent: async (
33 owner: string,
34 repo: string,
35 path: string,
36 branch: string = ''
37 ): Promise<FileContent> => {
38 const { data } = await apiClient.get<FileContent>(`/api/repos/${owner}/${repo}/files/${path}`, {
39 params: { branch },
40 });
41 return data;
42 },
43
44 invalidateCache: async (owner: string, repo: string): Promise<{ invalidated_count: number }> => {
45 const { data } = await apiClient.delete<{ invalidated_count: number }>(`/api/repos/${owner}/${repo}/cache`);
46 return data;
47 },
48
49 createFile: async (
50 owner: string,
51 repo: string,
52 path: string,
53 content: string = '',
54 message?: string
55 ): Promise<{ success: boolean; path: string }> => {
56 const { data } = await apiClient.post<{ success: boolean; path: string }>(
57 `/api/repos/${owner}/${repo}/create-file`,
58 { path, content, message }
59 );
60 return data;
61 },
62
63 createFolder: async (
64 owner: string,
65 repo: string,
66 path: string,
67 message?: string
68 ): Promise<{ success: boolean; path: string }> => {
69 const { data } = await apiClient.post<{ success: boolean; path: string }>(
70 `/api/repos/${owner}/${repo}/create-folder`,
71 { path, message }
72 );
73 return data;
74 },
75
76 renameItem: async (
77 owner: string,
78 repo: string,
79 oldPath: string,
80 newPath: string,
81 message?: string
82 ): Promise<{ success: boolean; old_path: string; new_path: string }> => {
83 const { data } = await apiClient.post<{ success: boolean; old_path: string; new_path: string }>(
84 `/api/repos/${owner}/${repo}/rename`,
85 { old_path: oldPath, new_path: newPath, message }
86 );
87 return data;
88 },
89
90 getPendingChanges: async (
91 owner: string,
92 repo: string
93 ): Promise<{ pending_changes: any[]; count: number }> => {
94 const { data } = await apiClient.get<{ pending_changes: any[]; count: number }>(
95 `/api/repos/${owner}/${repo}/pending-changes`
96 );
97 return data;
98 },
99
100 discardChanges: async (
101 owner: string,
102 repo: string
103 ): Promise<{ success: boolean; message: string }> => {
104 const { data } = await apiClient.delete<{ success: boolean; message: string }>(
105 `/api/repos/${owner}/${repo}/pending-changes`
106 );
107 return data;
108 },
109};