@@ -73,6 +73,53 @@ interface OpenAPIGeneratorOptions {
7373 * ! be careful that the folder will be removed after the process ends
7474 */
7575 tmpRoot ?: string
76+
77+ /**
78+ * disable log
79+ * @default false
80+ */
81+ silent ?: boolean
82+ }
83+
84+ function extractRootObjects ( code : string ) {
85+ const results = [ ]
86+ let i = 0
87+
88+ while ( i < code . length ) {
89+ // find the next colon
90+ const colonIdx = code . indexOf ( ':' , i )
91+ if ( colonIdx === - 1 ) break
92+
93+ // backtrack to find the key (simple word characters)
94+ let keyEnd = colonIdx - 1
95+ while ( keyEnd >= 0 && / \s / . test ( code [ keyEnd ] ) ) keyEnd --
96+ let keyStart = keyEnd
97+ while ( keyStart >= 0 && / \w / . test ( code [ keyStart ] ) ) keyStart --
98+
99+ // find the opening brace after colon
100+ const braceIdx = code . indexOf ( '{' , colonIdx )
101+ if ( braceIdx === - 1 ) break
102+
103+ // scan braces
104+ let depth = 0
105+ let end = braceIdx
106+ for ( ; end < code . length ; end ++ ) {
107+ if ( code [ end ] === '{' ) depth ++
108+ else if ( code [ end ] === '}' ) {
109+ depth --
110+ if ( depth === 0 ) {
111+ end ++ // move past closing brace
112+ break
113+ }
114+ }
115+ }
116+
117+ results . push ( `{${ code . slice ( keyStart + 1 , end ) } ;}` )
118+
119+ i = end
120+ }
121+
122+ return results
76123}
77124
78125/**
@@ -97,7 +144,8 @@ export const fromTypes =
97144 overrideOutputPath,
98145 debug = false ,
99146 compilerOptions,
100- tmpRoot = join ( tmpdir ( ) , '.ElysiaAutoOpenAPI' )
147+ tmpRoot = join ( tmpdir ( ) , '.ElysiaAutoOpenAPI' ) ,
148+ silent = false
101149 } : OpenAPIGeneratorOptions = { }
102150 ) =>
103151 ( ) => {
@@ -177,7 +225,7 @@ export const fromTypes =
177225 spawnSync ( `tsc` , {
178226 shell : true ,
179227 cwd : tmpRoot ,
180- stdio : debug ? 'inherit' : undefined
228+ stdio : silent ? undefined : 'inherit'
181229 } )
182230
183231 const fileName = targetFilePath
@@ -235,7 +283,7 @@ export const fromTypes =
235283 console . warn ( tempFiles )
236284 }
237285 } else {
238- console . log (
286+ console . warn (
239287 "reason: root folder doesn't exists" ,
240288 join ( tmpRoot , 'dist' )
241289 )
@@ -247,8 +295,10 @@ export const fromTypes =
247295
248296 const declaration = readFileSync ( targetFile , 'utf8' )
249297
298+ // console.log(declaration, targetFile)
299+
250300 // Check just in case of race-condition
251- if ( existsSync ( tmpRoot ) )
301+ if ( ! debug && existsSync ( tmpRoot ) )
252302 rmSync ( tmpRoot , { recursive : true , force : true } )
253303
254304 let instance = declaration . match (
@@ -282,11 +332,8 @@ export const fromTypes =
282332 const routes : AdditionalReference = { }
283333
284334 // Treaty is a collection of { ... } & { ... } & { ... }
285- // Each route will be intersected with each other
286- // instead of being nested in a route object
287- for ( const route of routesString . slice ( 1 ) . split ( '} & {' ) ) {
288- // as ' } & {' is removed, we need to add it back
289- let schema = TypeBox ( `{${ route } }` )
335+ for ( const route of extractRootObjects ( routesString ) ) {
336+ let schema = TypeBox ( route )
290337 if ( schema . type !== 'object' ) continue
291338
292339 const paths = [ ]
@@ -302,6 +349,9 @@ export const fromTypes =
302349 }
303350
304351 const method = paths . pop ( ) !
352+ // For whatever reason, if failed to infer route correctly
353+ if ( ! method ) continue
354+
305355 const path = '/' + paths . join ( '/' )
306356 schema = schema . properties
307357
0 commit comments