@@ -13,96 +13,107 @@ const readFile = promisify(fs.readFile);
1313export class Project {
1414 private readonly knownImports : Record < string , Record < string , KnownCodec > > ;
1515
16- private files : Record < string , SourceFile > ;
16+ private processedFiles : Record < string , SourceFile > ;
17+ private pendingFiles : Set < string > ;
1718 private types : Record < string , string > ;
19+ private visitedPackages : Set < string > ;
1820
1921 constructor ( files : Record < string , SourceFile > = { } , knownImports = KNOWN_IMPORTS ) {
20- this . files = files ;
22+ this . processedFiles = files ;
23+ this . pendingFiles = new Set ( ) ;
2124 this . knownImports = knownImports ;
2225 this . types = { } ;
26+ this . visitedPackages = new Set ( ) ;
2327 }
2428
2529 add ( path : string , sourceFile : SourceFile ) : void {
26- this . files [ path ] = sourceFile ;
30+ this . processedFiles [ path ] = sourceFile ;
31+ this . pendingFiles . delete ( path ) ;
32+
33+ // Update types mapping
34+ for ( const exp of sourceFile . symbols . exports ) {
35+ this . types [ exp . exportedName ] = path ;
36+ }
2737 }
2838
2939 get ( path : string ) : SourceFile | undefined {
30- return this . files [ path ] ;
40+ return this . processedFiles [ path ] ;
3141 }
3242
3343 has ( path : string ) : boolean {
34- return this . files . hasOwnProperty ( path ) ;
44+ return this . processedFiles . hasOwnProperty ( path ) ;
3545 }
3646
3747 async parseEntryPoint ( entryPoint : string ) : Promise < E . Either < string , Project > > {
3848 const queue : string [ ] = [ entryPoint ] ;
3949 let path : string | undefined ;
40- const visitedPackages = new Set < string > ( ) ;
50+
4151 while ( ( ( path = queue . pop ( ) ) , path !== undefined ) ) {
4252 if ( ! [ '.ts' , '.js' ] . includes ( p . extname ( path ) ) ) {
4353 continue ;
4454 }
4555
46- const src = await this . readFile ( path ) ;
47- const sourceFile = await parseSource ( path , src ) ;
48-
49- if ( sourceFile === undefined ) continue ;
56+ try {
57+ const src = await this . readFile ( path ) ;
58+ const sourceFile = await parseSource ( path , src ) ;
5059
51- // map types to their file path
52- for ( const exp of sourceFile . symbols . exports ) {
53- this . types [ exp . exportedName ] = path ;
54- }
55-
56- this . add ( path , sourceFile ) ;
60+ if ( ! sourceFile ) {
61+ console . error ( `Error parsing source file: ${ path } ` ) ;
62+ continue ;
63+ }
5764
58- for ( const sym of Object . values ( sourceFile . symbols . imports ) ) {
59- if ( ! sym . from . startsWith ( '.' ) ) {
60- // If we are not resolving a relative path, we need to resolve the entry point
61- const baseDir = p . dirname ( sourceFile . path ) ;
62- let entryPoint = this . resolveEntryPoint ( baseDir , sym . from ) ;
65+ // map types to their file path
66+ for ( const exp of sourceFile . symbols . exports ) {
67+ this . types [ exp . exportedName ] = path ;
68+ }
6369
64- if ( ! visitedPackages . has ( sym . from ) ) {
65- // This is a step that checks if this import has custom codecs, and loads them into known imports
66- const codecs = await this . getCustomCodecs ( baseDir , sym . from ) ;
67- if ( E . isLeft ( codecs ) ) {
68- return codecs ;
70+ this . add ( path , sourceFile ) ;
71+
72+ // Process imports
73+ const baseDir = p . dirname ( path ) ;
74+ for ( const sym of Object . values ( sourceFile . symbols . imports ) ) {
75+ if ( ! sym . from . startsWith ( '.' ) ) {
76+ if ( ! this . visitedPackages . has ( sym . from ) ) {
77+ const codecs = await this . getCustomCodecs ( baseDir , sym . from ) ;
78+ if ( E . isLeft ( codecs ) ) {
79+ return codecs ;
80+ }
81+
82+ if ( Object . keys ( codecs . right ) . length > 0 ) {
83+ this . knownImports [ sym . from ] = {
84+ ...codecs . right ,
85+ ...this . knownImports [ sym . from ] ,
86+ } ;
87+ logInfo ( `Loaded custom codecs for ${ sym . from } ` ) ;
88+ }
89+
90+ this . visitedPackages . add ( sym . from ) ;
6991 }
7092
71- if ( Object . keys ( codecs . right ) . length > 0 ) {
72- this . knownImports [ sym . from ] = {
73- ...codecs . right ,
74- ...this . knownImports [ sym . from ] ,
75- } ;
76-
77- logInfo ( `Loaded custom codecs for ${ sym . from } ` ) ;
93+ const entryPoint = this . resolveEntryPoint ( baseDir , sym . from ) ;
94+ if ( E . isRight ( entryPoint ) && ! this . has ( entryPoint . right ) ) {
95+ queue . push ( entryPoint . right ) ;
96+ }
97+ } else {
98+ const absImportPathE = this . resolve ( baseDir , sym . from ) ;
99+ if ( E . isRight ( absImportPathE ) && ! this . has ( absImportPathE . right ) ) {
100+ queue . push ( absImportPathE . right ) ;
78101 }
79102 }
103+ }
80104
81- visitedPackages . add ( sym . from ) ;
82-
83- if ( E . isLeft ( entryPoint ) ) {
84- continue ;
85- } else if ( ! this . has ( entryPoint . right ) ) {
86- queue . push ( entryPoint . right ) ;
87- }
88- } else {
89- const filePath = p . dirname ( path ) ;
90- const absImportPathE = this . resolve ( filePath , sym . from ) ;
91- if ( E . isLeft ( absImportPathE ) ) {
92- return absImportPathE ;
93- } else if ( ! this . has ( absImportPathE . right ) ) {
105+ // Process star exports
106+ for ( const starExport of sourceFile . symbols . exportStarFiles ) {
107+ const absImportPathE = this . resolve ( baseDir , starExport ) ;
108+ if ( E . isRight ( absImportPathE ) && ! this . has ( absImportPathE . right ) ) {
94109 queue . push ( absImportPathE . right ) ;
95110 }
96111 }
97- }
98- for ( const starExport of sourceFile . symbols . exportStarFiles ) {
99- const filePath = p . dirname ( path ) ;
100- const absImportPathE = this . resolve ( filePath , starExport ) ;
101- if ( E . isLeft ( absImportPathE ) ) {
102- return absImportPathE ;
103- } else if ( ! this . has ( absImportPathE . right ) ) {
104- queue . push ( absImportPathE . right ) ;
112+ } catch ( err ) {
113+ if ( err instanceof Error ) {
114+ return E . left ( err . message ) ;
105115 }
116+ return E . left ( 'Unknown error occurred while processing files' ) ;
106117 }
107118 }
108119
0 commit comments