11import { OpenAPIV3 } from 'openapi-types' ;
22import { traverse } from './utils/OpenApiTraverser' ;
3- import { resolveRef } from './utils/helper' ;
3+ import { resolveRef , deleteMatchingKeys } from './utils/helper' ;
44import Logger from './utils/logger' ;
55
66/**
@@ -10,6 +10,7 @@ import Logger from './utils/logger';
1010export class VendorExtensionProcessor {
1111 private static readonly PROTOBUF_EXCLUDED_EXTENSION = 'x-protobuf-excluded' ;
1212 private static readonly PROTOBUF_TYPE_EXTENSION = 'x-protobuf-type' ;
13+ private static readonly PROTOBUF_NAME_EXTENSION = 'x-protobuf-name' ;
1314
1415 private static readonly PROTOBUF_TYPE_MAPPING : Record < string , { type : string ; format ?: string } > = {
1516 'int32' : { type : 'integer' , format : 'int32' } ,
@@ -30,23 +31,26 @@ export class VendorExtensionProcessor {
3031
3132 /**
3233 * Process the spec by pruning anything marked with x-protobuf-excluded
33- * Direct path-level handling + traverse for schemas only
34+ * and applying vendor extensions (x-protobuf-name, x-protobuf-type)
3435 */
3536 public process ( ) : OpenAPIV3 . Document {
37+ deleteMatchingKeys ( this . root , ( item : any ) => this . hasProtobufExcluded ( item ) ) ;
3638
37- this . removeProtobufExcludedFromPaths ( ) ;
3839 traverse ( this . root , {
40+ onParameter : ( param : any , name : string ) => {
41+ this . applyNameOverrideToParameter ( param ) ;
42+ } ,
3943 onSchema : ( schema : any , name : string ) => {
40- this . removeProtobufExcludedProperties ( schema ) ;
4144 this . applyTypeOverride ( schema ) ;
45+ this . applyNameOverride ( schema ) ;
4246 } ,
4347 onResponseSchema : ( schema : any , name : string ) => {
44- this . removeProtobufExcludedProperties ( schema ) ;
4548 this . applyTypeOverride ( schema ) ;
49+ this . applyNameOverride ( schema ) ;
4650 } ,
4751 onRequestSchema : ( schema : any , name : string ) => {
48- this . removeProtobufExcludedProperties ( schema ) ;
4952 this . applyTypeOverride ( schema ) ;
53+ this . applyNameOverride ( schema ) ;
5054 } ,
5155 onSchemaProperty : ( schema : any , name : string ) => {
5256 this . applyTypeOverride ( schema ) ;
@@ -73,55 +77,61 @@ export class VendorExtensionProcessor {
7377 }
7478
7579 /**
76- * Remove x-protobuf-excluded items from path-level elements directly
80+ * Apply name override to a parameter if it has x-protobuf-name
7781 */
78- private removeProtobufExcludedFromPaths ( ) : void {
79- if ( ! this . root . paths ) return ;
80-
81- for ( const pathKey in this . root . paths ) {
82- const pathItem = this . root . paths [ pathKey ] ;
83- if ( ! pathItem || typeof pathItem !== 'object' || '$ref' in pathItem ) continue ;
84-
85- // Handle operations
86- for ( const method in pathItem ) {
87- if ( method === 'parameters' || method === '$ref' || method === 'summary' ||
88- method === 'description' || method === 'servers' ) continue ;
89-
90- const operation = ( pathItem as any ) [ method ] ;
91- if ( ! operation || typeof operation !== 'object' ) continue ;
92-
93- // Remove parameters with x-protobuf-excluded
94- if ( Array . isArray ( operation . parameters ) ) {
95- const originalLength = operation . parameters . length ;
96- operation . parameters = operation . parameters . filter ( ( p : any ) => ! this . hasProtobufExcluded ( p ) ) ;
97- const removedCount = originalLength - operation . parameters . length ;
98- if ( removedCount > 0 ) {
99- this . logger . info ( `Removed ${ removedCount } parameter(s) from ${ method . toUpperCase ( ) } ${ pathKey } (${ VendorExtensionProcessor . PROTOBUF_EXCLUDED_EXTENSION } )` ) ;
100- }
101- }
82+ private applyNameOverrideToParameter ( param : OpenAPIV3 . ParameterObject ) : void {
83+ if ( ! param || typeof param !== 'object' || ! ( VendorExtensionProcessor . PROTOBUF_NAME_EXTENSION in param ) ) return ;
84+
85+ const newName = param [ VendorExtensionProcessor . PROTOBUF_NAME_EXTENSION ] ;
86+ if ( typeof newName === 'string' && param . name && newName !== param . name ) {
87+ const oldName = param . name ;
88+ param . name = newName ;
89+ delete param [ VendorExtensionProcessor . PROTOBUF_NAME_EXTENSION ] ;
90+ this . logger . info ( `Renamed parameter '${ oldName } ' -> '${ newName } ' (${ VendorExtensionProcessor . PROTOBUF_NAME_EXTENSION } )` ) ;
91+ }
92+ }
93+
10294
103- // Remove responses with x-protobuf-excluded
104- if ( operation . responses ) {
105- for ( const status in operation . responses ) {
106- if ( this . hasProtobufExcluded ( operation . responses [ status ] ) ) {
107- delete operation . responses [ status ] ;
108- this . logger . info ( `Removed response ${ status } from ${ method . toUpperCase ( ) } ${ pathKey } (${ VendorExtensionProcessor . PROTOBUF_EXCLUDED_EXTENSION } )` ) ;
109- }
95+ /**
96+ * Apply name override to schema properties and composed schemas (oneOf, anyOf, allOf)
97+ * - For properties: renames property keys
98+ * - For composed schemas: sets title field for sub-schemas
99+ */
100+ private applyNameOverride ( schema : any ) : void {
101+ if ( ! schema || typeof schema !== 'object' ) return ;
102+
103+ // Rename properties within schema.properties collection
104+ if ( schema ?. properties ) {
105+ for ( const prop in schema . properties ) {
106+ const propSchema = schema . properties [ prop ] ;
107+ if ( propSchema && typeof propSchema === 'object' && VendorExtensionProcessor . PROTOBUF_NAME_EXTENSION in propSchema ) {
108+ const newName = propSchema [ VendorExtensionProcessor . PROTOBUF_NAME_EXTENSION ] ;
109+ if ( typeof newName === 'string' && newName !== prop ) {
110+ schema . properties [ newName ] = schema . properties [ prop ] ;
111+ delete schema . properties [ prop ] ;
112+ delete schema . properties [ newName ] [ VendorExtensionProcessor . PROTOBUF_NAME_EXTENSION ] ;
113+
114+ this . logger . info ( `Renamed property '${ prop } ' -> '${ newName } ' (${ VendorExtensionProcessor . PROTOBUF_NAME_EXTENSION } )` ) ;
110115 }
111116 }
112117 }
113118 }
114- }
115119
116- private removeProtobufExcludedProperties ( schema : OpenAPIV3 . SchemaObject ) : void {
117- if ( ! schema ?. properties ) return ;
118-
119- for ( const prop in schema . properties ) {
120- const propSchema = schema . properties [ prop ] ;
121- if ( propSchema && typeof propSchema === 'object' ) {
122- if ( this . hasProtobufExcluded ( propSchema ) ) {
123- delete schema . properties [ prop ] ;
124- this . logger . info ( `Removed schema property ${ prop } (${ VendorExtensionProcessor . PROTOBUF_EXCLUDED_EXTENSION } )` ) ;
120+ // Set title for composed schemas (oneOf, anyOf, allOf)
121+ const composedKeys = [ 'allOf' , 'anyOf' , 'oneOf' ] as const ;
122+ for ( const key of composedKeys ) {
123+ const subschemas = schema [ key ] ;
124+ if ( ! Array . isArray ( subschemas ) ) continue ;
125+
126+ for ( const subschema of subschemas ) {
127+ if ( subschema && typeof subschema === 'object' && VendorExtensionProcessor . PROTOBUF_NAME_EXTENSION in subschema ) {
128+ const titleValue = subschema [ VendorExtensionProcessor . PROTOBUF_NAME_EXTENSION ] ;
129+ if ( typeof titleValue === 'string' ) {
130+ const oldTitle = subschema . title ;
131+ subschema . title = titleValue ;
132+ delete subschema [ VendorExtensionProcessor . PROTOBUF_NAME_EXTENSION ] ;
133+ this . logger . info ( `Set title for ${ key } sub-schema: '${ oldTitle } ' -> '${ titleValue } ' (${ VendorExtensionProcessor . PROTOBUF_NAME_EXTENSION } )` ) ;
134+ }
125135 }
126136 }
127137 }
@@ -170,4 +180,5 @@ export class VendorExtensionProcessor {
170180 this . logger . info ( `Applied ${ VendorExtensionProcessor . PROTOBUF_TYPE_EXTENSION } : ${ protoType } -> type: ${ schema . type } ${ schema . format ? `, format: ${ schema . format } ` : '' } ` ) ;
171181 }
172182 }
183+
173184}
0 commit comments