@@ -97,52 +97,76 @@ export function parseMethodParameters({ method, parameters, path }: PathMethod,
9797export function parseMethodMetadata ( { method, path, responses, options : meta } : PathMethod ) {
9898 const { configRead, interfaces } = inject ( )
9999 const metaAny = meta as { consumes ?: string [ ] }
100+
101+ // 1. 结构化注释生成
100102 const comments = [
101103 meta . summary && `@summary ${ meta . summary } ` ,
102104 meta . description && `@description ${ meta . description } ` ,
103105 `@method ${ method } ` ,
104- meta . tags ?. length ? `@tags ${ meta . tags . join ( ' | ' ) || '-' } ` : undefined ,
105- metaAny . consumes ?. length ? `@consumes ${ metaAny . consumes . join ( '; ' ) || '-' } ` : undefined ,
106- ] . filter ( ( c ) : c is string => typeof c === 'string' )
106+ meta . tags ?. length && `@tags ${ meta . tags . join ( ' | ' ) } ` ,
107+ metaAny . consumes ?. length && `@consumes ${ metaAny . consumes . join ( '; ' ) } ` ,
108+ ] . filter ( ( c ) : c is string => ! ! c )
107109
110+ // 2. 路径处理
108111 let name = camelCase ( `${ method } /${ path } ` )
109-
110- const url = `${ path . replace ( / ( \{ ) / g, '${paths.' ) } `
111- function hasContent ( r : unknown ) : r is { content ?: Record < string , { schema ?: unknown } > } {
112- return r != null && typeof r === 'object' && 'content' in r
112+ const url = path . replace ( / \{ / g, '${paths.' )
113+
114+ // 3. 响应 Schema 提取逻辑 (解耦与简化)
115+ const getResponseSchema = ( ) => {
116+ const res200 = responses [ '200' ]
117+ const resDefault = responses . default
118+
119+ // 优先尝试从 content/application/json 获取 (OpenAPI 3.0)
120+ const getContentSchema = ( res : any ) => res ?. content ?. [ 'application/json' ] ?. schema
121+ const schemaFromContent = getContentSchema ( res200 ) ?? getContentSchema ( resDefault )
122+ if ( schemaFromContent )
123+ return schemaFromContent
124+
125+ // 兜底从根节点获取 (Swagger 2.0)
126+ if ( res200 && 'schema' in res200 )
127+ return ( res200 as any ) . schema
128+ return null
113129 }
114- const resDefault = responses . default && hasContent ( responses . default ) ? responses . default : null
115- const res200 = responses [ '200' ] && typeof responses [ '200' ] === 'object' ? responses [ '200' ] : null
116- const contentDefault = resDefault ?. content ?. [ 'application/json' ]
117- const content200 = res200 && hasContent ( res200 ) ? res200 . content ?. [ 'application/json' ] : null
118- const schemaFromContent = ( contentDefault && typeof contentDefault === 'object' && 'schema' in contentDefault ? ( contentDefault as { schema : unknown } ) . schema : null )
119- ?? ( content200 && typeof content200 === 'object' && 'schema' in content200 ? ( content200 as { schema : unknown } ) . schema : null )
120- const schemaFromRes200 = res200 && typeof res200 === 'object' && 'schema' in res200 && ! ( 'content' in res200 ) ? ( res200 as { schema : unknown } ) . schema : null
121- const responseSchema = schemaFromContent ?? schemaFromRes200
122- let responseType = responseSchema && typeof responseSchema === 'object' ? parseSchemaType ( responseSchema as Parameters < typeof parseSchemaType > [ 0 ] ) : 'void'
123-
124- if ( configRead . config . responseRequired )
125- deepSignRequired ( interfaces . find ( v => v . name === responseType ) ?. properties || [ ] )
126-
127- function deepSignRequired ( properties : StatementField [ ] ) {
128- for ( const property of properties ) {
129- property . required = true
130-
131- for ( const { properties } of interfaces . filter ( v => v . name === property . type ) )
132- deepSignRequired ( properties || [ ] )
130+
131+ const responseSchema = getResponseSchema ( )
132+ let responseType = responseSchema ? parseSchemaType ( responseSchema as any ) : 'void'
133+
134+ // 4. 强制必填标记逻辑 (递归优化)
135+ if ( configRead . config . responseRequired && responseType !== 'void' ) {
136+ const processedTypes = new Set < string > ( ) // 防止循环引用导致死循环
137+ const markRequiredRecursive = ( typeName : string ) => {
138+ if ( processedTypes . has ( typeName ) )
139+ return
140+ processedTypes . add ( typeName )
141+ const targetInterface = interfaces . find ( v => v . name === typeName )
142+ targetInterface ?. properties ?. forEach ( ( prop ) => {
143+ prop . required = true
144+ if ( prop . type )
145+ markRequiredRecursive ( prop . type )
146+ } )
133147 }
148+ markRequiredRecursive ( responseType )
134149 }
135150
151+ // 5. 转换与注入
136152 const config = inject ( `${ method } /${ path } ` )
137- ; ( { name , responseType } = transformOperation ( {
153+ const transformed = transformOperation ( {
138154 configRead,
139155 name,
140156 parameters : config ?. parameters ,
141157 responseType,
142- } ) )
143- // Inject function return type into named context (function name)
144- // Referenced at:
145- // - packages/pipeline/src/compiler/request.ts:172 (inject(item.name) gets returnType)
146- provide ( name , { returnType : responseType } )
147- return { description : comments , name, url, responseType, body : [ ] as string [ ] }
158+ } )
159+
160+ name = transformed . name
161+ responseType = transformed . responseType
162+
163+ provide ( name , { responseType } )
164+
165+ return {
166+ description : comments ,
167+ name,
168+ url,
169+ responseType,
170+ body : [ ] as string [ ] ,
171+ }
148172}
0 commit comments