@@ -8,7 +8,14 @@ import mime from "mime-types";
8
8
import * as path from "path" ;
9
9
import { Synapse } from "../synapse" ;
10
10
11
- const IGNORE_PATTERNS = [ "node_modules" , "dist" , "build" , "coverage" , "logs" ] ;
11
+ const IGNORE_PATTERNS = [
12
+ "node_modules" ,
13
+ "dist" ,
14
+ "build" ,
15
+ "coverage" ,
16
+ "logs" ,
17
+ ".git" ,
18
+ ] ;
12
19
13
20
export type FileItem = {
14
21
name : string ;
@@ -61,6 +68,17 @@ export type ZipResult = {
61
68
} ;
62
69
} ;
63
70
71
+ export type FileListItem < WithContent extends boolean = false > =
72
+ WithContent extends true
73
+ ? { path : string ; content : string }
74
+ : { path : string } ;
75
+
76
+ export type FileListResult < WithContent extends boolean = false > = {
77
+ success : boolean ;
78
+ data ?: FileListItem < WithContent > [ ] ;
79
+ error ?: string ;
80
+ } ;
81
+
64
82
export class Filesystem {
65
83
private synapse : Synapse ;
66
84
private workDir : string ;
@@ -799,4 +817,108 @@ export class Filesystem {
799
817
} ;
800
818
}
801
819
}
820
+
821
+ /**
822
+ * Lists all files in a directory with optional content and recursive traversal
823
+ * @param dirPath - The directory path to list files from
824
+ * @param withContent - Whether to include file content in the results
825
+ * @param recursive - Whether to recursively traverse subdirectories
826
+ * @returns Promise<FileListResult> containing array of file objects
827
+ */
828
+ async listFilesInDir ( {
829
+ dirPath,
830
+ withContent,
831
+ recursive,
832
+ additionalIgnorePatterns,
833
+ } : {
834
+ dirPath : string ;
835
+ withContent ?: boolean ;
836
+ recursive ?: boolean ;
837
+ additionalIgnorePatterns ?: string [ ] ;
838
+ } ) : Promise < FileListResult < boolean > > {
839
+ if ( ! dirPath ) {
840
+ return { success : false , error : "path is required" } ;
841
+ }
842
+
843
+ try {
844
+ const fullPath = this . resolvePath ( dirPath ) ;
845
+ const workDir = path . resolve ( this . workDir ) ;
846
+ const results : Array < { path : string ; content ?: string } > = [ ] ;
847
+
848
+ // Read and parse .gitignore
849
+ let ig : ReturnType < typeof ignore > | null = null ;
850
+ try {
851
+ const gitignorePath = this . resolvePath ( ".gitignore" ) ;
852
+ const gitignoreContent = fsSync . existsSync ( gitignorePath )
853
+ ? fsSync . readFileSync ( gitignorePath , "utf-8" )
854
+ : "" ;
855
+ ig = ignore ( ) . add ( gitignoreContent ) ;
856
+ } catch {
857
+ ig = null ;
858
+ }
859
+
860
+ const walkDirectory = async ( dir : string ) => {
861
+ let entries : fsSync . Dirent [ ] ;
862
+ try {
863
+ entries = await fs . readdir ( dir , { withFileTypes : true } ) ;
864
+ } catch {
865
+ return ;
866
+ }
867
+
868
+ for ( const entry of entries ) {
869
+ const absPath = path . join ( dir , entry . name ) ;
870
+ const relPath = path . relative ( workDir , absPath ) . replace ( / \\ / g, "/" ) ;
871
+
872
+ // Skip if ignored by .gitignore or IGNORE_PATTERNS
873
+ if ( ig && ig . ignores ( relPath ) ) {
874
+ continue ;
875
+ }
876
+ if (
877
+ [ ...IGNORE_PATTERNS , ...( additionalIgnorePatterns || [ ] ) ] . some (
878
+ ( pattern ) => relPath . includes ( pattern ) ,
879
+ )
880
+ ) {
881
+ continue ;
882
+ }
883
+
884
+ if ( entry . isDirectory ( ) ) {
885
+ if ( recursive ) {
886
+ await walkDirectory ( absPath ) ;
887
+ }
888
+ } else if ( entry . isFile ( ) ) {
889
+ const fileObj : { path : string ; content ?: string } = {
890
+ path : relPath ,
891
+ } ;
892
+
893
+ if ( withContent ) {
894
+ try {
895
+ const content = await fs . readFile ( absPath , "utf-8" ) ;
896
+ fileObj . content = content ;
897
+ } catch {
898
+ // If we can't read the file, skip it or include it without content
899
+ continue ;
900
+ }
901
+ }
902
+
903
+ results . push ( fileObj ) ;
904
+ }
905
+ }
906
+ } ;
907
+
908
+ await walkDirectory ( fullPath ) ;
909
+
910
+ return {
911
+ success : true ,
912
+ data : results as FileListItem < boolean > [ ] ,
913
+ } ;
914
+ } catch ( error ) {
915
+ this . log (
916
+ `Error listing files in directory ${ dirPath } : ${ error instanceof Error ? error . message : String ( error ) } ` ,
917
+ ) ;
918
+ return {
919
+ success : false ,
920
+ error : error instanceof Error ? error . message : String ( error ) ,
921
+ } ;
922
+ }
923
+ }
802
924
}
0 commit comments