1
+ import { useState } from 'react' ;
2
+ import axios from 'axios' ;
3
+
4
+ interface RepoFile {
5
+ url : string ;
6
+ name : string ;
7
+ file_type : string ;
8
+ download_url : string ;
9
+ sha : string ;
10
+ size : string ;
11
+ path : string ;
12
+ type ?: string ;
13
+ }
14
+
15
+ const useGitHubFolderTree = ( folderUrl : string , apiKey ?: string ) => {
16
+ const [ repoFiles , setRepoFiles ] = useState < RepoFile [ ] > ( [ ] ) ;
17
+ const [ error , setError ] = useState < string > ( '' ) ;
18
+ const [ log , setLog ] = useState < string > ( '' ) ;
19
+
20
+ const fetchFolderData = async ( folderUrl : string ) : Promise < any > => {
21
+ const contentIndex = folderUrl . indexOf ( "contents/" ) + "contents/" . length ;
22
+ const decodedUrl = decodeURIComponent ( contentIndex > 0 ? folderUrl . substring ( contentIndex ) : folderUrl ) ;
23
+ setLog ( `Fetching data from ${ decodedUrl } ` ) ;
24
+ const options : any = { } ;
25
+ if ( apiKey ) {
26
+ options . headers = {
27
+ Authorization : `Bearer ${ apiKey } ` ,
28
+ } ;
29
+ }
30
+ const { data : response } = await axios . get ( folderUrl , options ) ;
31
+ setLog ( `Data fetched from ${ decodedUrl } ` ) ;
32
+ return response ;
33
+ } ;
34
+
35
+ const processFolderContents = async ( folder : RepoFile [ ] ) : Promise < ( RepoFile | null ) [ ] > => {
36
+ const filePromises = folder . map ( async ( item : RepoFile ) => {
37
+ if ( item . type === 'file' ) {
38
+ setLog ( `Processing ${ item . name } ` ) ;
39
+ const extension = item . name . split ( '.' ) . pop ( ) || 'unknown' ;
40
+ const sizeInKB = Math . round ( parseInt ( item . size ) / 1024 ) ;
41
+ let size ;
42
+ if ( sizeInKB >= 1024 ) {
43
+ const sizeInMB = ( sizeInKB / 1024 ) . toFixed ( 2 ) ;
44
+ size = sizeInMB + ' MB' ;
45
+ } else {
46
+ size = sizeInKB + ' KB' ;
47
+ }
48
+
49
+ return {
50
+ name : item . name ,
51
+ file_type : extension ,
52
+ download_url : item . download_url ,
53
+ sha : item . sha ,
54
+ size : size ,
55
+ path : item . path ,
56
+ } ;
57
+ } else if ( item . type === 'dir' ) {
58
+ setLog ( `Processing ${ item . name } ` ) ;
59
+ const subFolder = await fetchFolderData ( item . url ) ;
60
+ setLog ( `Subfolder data fetched from ${ item . url } ` ) ;
61
+ const subFolderFiles = await processFolderContents ( subFolder ) ;
62
+ setLog ( `Processed ${ item . name } ` ) ;
63
+ return subFolderFiles ;
64
+ }
65
+
66
+ return null ;
67
+ } ) ;
68
+
69
+ const files = await Promise . all ( filePromises ) ;
70
+ const flattenedFiles = files . flat ( ) ;
71
+
72
+ setLog ( 'Processing complete' ) ;
73
+ return flattenedFiles . filter ( Boolean ) as ( RepoFile | null ) [ ] ;
74
+ } ;
75
+
76
+ const fetchRepositoryContents = async ( ) => {
77
+ try {
78
+ const urlRegex = / h t t p s : \/ \/ g i t h u b .c o m \/ ( [ ^ \/ ] + ) \/ ( [ ^ \/ ] + ) \/ t r e e \/ ( [ ^ \/ ] + ) \/ ? ( .* ) / ;
79
+ if ( ! folderUrl ) {
80
+ setError ( 'Please enter a GitHub folder URL' ) ;
81
+ return ;
82
+ }
83
+
84
+ const matches = folderUrl . match ( urlRegex ) ;
85
+
86
+ if ( ! matches ) {
87
+ setError ( 'Invalid GitHub folder URL' ) ;
88
+ return ;
89
+ }
90
+
91
+ const user = matches [ 1 ] ;
92
+ const repo = matches [ 2 ] ;
93
+ const branch = matches [ 3 ] ;
94
+ const dir = matches [ 4 ] ;
95
+ console . log ( user , repo , branch , dir ) ;
96
+ setLog ( `Extracted user: ${ user } , repo: ${ repo } , branch: ${ branch } , dir: ${ dir } ` ) ;
97
+
98
+ const apiUrl = `https://api.github.com/repos/${ user } /${ repo } /contents/${ dir } ?ref=${ branch } ` ;
99
+ setLog ( `Fetching repository contents from ${ apiUrl } ` ) ;
100
+ const folderData = await fetchFolderData ( apiUrl ) ;
101
+ setLog ( 'Folder data fetched' ) ;
102
+
103
+ const processedFiles = await processFolderContents ( folderData ) ;
104
+ setRepoFiles ( ( prevFiles ) => [ ...prevFiles , ...processedFiles ] . filter ( Boolean ) as RepoFile [ ] ) ;
105
+ } catch ( error : any ) {
106
+ setError ( error . response ?. data ?. message || 'An error occurred' ) ;
107
+ console . error ( `Error: ${ error } ` ) ;
108
+ }
109
+ } ;
110
+
111
+ return {
112
+ repoFiles,
113
+ error,
114
+ log,
115
+ fetchRepositoryContents,
116
+ } ;
117
+ } ;
118
+
119
+ export default useGitHubFolderTree ;
0 commit comments