@@ -66,7 +66,7 @@ import {
6666  calculateHeaderName , 
6767  calculateHeaderPlace , 
6868  calculateParameterName , 
69-   nonEmptyString 
69+   nonEmptyString , 
7070}  from  '../deprecated-item-description' 
7171import  {  OPEN_API_DEPRECATION_RESOLVER  }  from  './openapi.deprecated' 
7272
@@ -84,13 +84,13 @@ const TO_EMPTY_OBJECT_MAPPING: ReplaceMapping = {
8484  mapping : new  Map ( [ [ EMPTY_MARKER ,  { 
8585    value : ( )  =>  ( { } ) , 
8686    reverseMatcher : deepEqualsMatcher ( { } ) , 
87-   } ] ] ) 
87+   } ] ] ) , 
8888} 
8989const  TO_EMPTY_ARRAY_MAPPING : ReplaceMapping  =  { 
9090  mapping : new  Map ( [ [ EMPTY_MARKER ,  { 
9191    value : ( )  =>  ( [ ] ) , 
9292    reverseMatcher : deepEqualsMatcher ( [ ] ) , 
93-   } ] ] ) 
93+   } ] ] ) , 
9494} 
9595
9696const  OPEN_API_30_JSON_SCHEMA_DEFAULTS : Record < string ,  JsonPrimitiveValue >  =  { 
@@ -206,16 +206,18 @@ const OPEN_API_COMPONENTS_REPLACES: Record<string, ReplaceMapping> = {
206206  [ OPEN_API_PROPERTY_EXAMPLES ] : TO_EMPTY_OBJECT_MAPPING , 
207207} 
208208
209- const  openApiExtensionRulesFunction : ( elseRules : NormalizationRules )  =>  NormalizationRules  =  ( elseRules )  =>  ( { 
210-   '/*' : ( {  key } )  =>  ( 
211-     typeof  key  ===  'string'  &&  key . startsWith ( 'x-' ) 
209+ const  openApiExtensionRulesFunction : ( elseRules : NormalizationRules  |  ( ( )  =>  NormalizationRules ) )  =>  NormalizationRules  =  ( elseRules )  =>  ( { 
210+   '/*' : ( ctx )  =>  { 
211+     const  {  key }  =  ctx 
212+     return  typeof  key  ===  'string'  &&  key . startsWith ( 'x-' ) 
212213      ? { 
214+         isExtension : true , 
213215        validate : checkType ( ...TYPE_JSON_ANY ) , 
214216        merge : resolvers . last , 
215217        '/**' : {  validate : checkType ( ...TYPE_JSON_ANY )  } , 
216-       }   as   NormalizationRules 
217-       : elseRules 
218-   ) , 
218+       } 
219+       : typeof   elseRules   ===   'function'  ?  elseRules ( )  :  elseRules 
220+   } , 
219221} ) 
220222
221223const  openApiExtensionRules : NormalizationRules  =  openApiExtensionRulesFunction ( {  validate : ( )  =>  false  } ) 
@@ -226,6 +228,7 @@ const openApiExternalDocsRules: NormalizationRules = {
226228    merge : resolvers . last , 
227229    '/description' : {  validate : checkType ( TYPE_STRING )  } , 
228230    '/url' : {  validate : checkType ( TYPE_STRING )  } , 
231+     ...openApiExtensionRules , 
229232  } , 
230233} 
231234
@@ -240,6 +243,11 @@ const openApiExamplesRules: NormalizationRules = {
240243  '/examples' : { 
241244    validate : checkType ( TYPE_OBJECT ) , 
242245    merge : resolvers . last , 
246+     '/*' : { 
247+       ...openApiExtensionRulesFunction ( { 
248+         validate : checkType ( ...TYPE_JSON_ANY ) , 
249+       } ) , 
250+     } , 
243251    '/**' : {  validate : checkType ( ...TYPE_JSON_ANY )  } , 
244252  } , 
245253} 
@@ -278,12 +286,12 @@ const openApiServersRules: NormalizationRules = {
278286const  openApiSecurityRules : NormalizationRules  =  { 
279287  '/security' : { 
280288    '/*' : { 
281-       ... openApiExtensionRulesFunction ( { 
289+       '/*' :  { 
282290        '/*' : { 
283291          validate : checkType ( TYPE_STRING ) , 
284292        } , 
285293        validate : checkType ( TYPE_ARRAY ) , 
286-       } ) , 
294+       } , 
287295      validate : checkType ( TYPE_OBJECT ) , 
288296    } , 
289297    validate : checkType ( TYPE_ARRAY ) , 
@@ -314,6 +322,7 @@ const openApiJsonSchemaExtensionRules = (): NormalizationRules => ({
314322  '/xml' : { 
315323    validate : checkType ( ...TYPE_JSON_ANY ) , 
316324    merge : resolvers . mergeObjects , 
325+     ...openApiExtensionRulesFunction ( {  validate : checkType ( ...TYPE_JSON_ANY )  } ) , 
317326    '/**' : {  validate : checkType ( ...TYPE_JSON_ANY )  } , 
318327  } , 
319328  '/discriminator' : { 
@@ -554,7 +563,7 @@ const openApiRequestRules = (version: OpenApiSpecVersion): NormalizationRules =>
554563} ) 
555564
556565const  openApiResponsesRules  =  ( version : OpenApiSpecVersion ) : NormalizationRules  =>  ( { 
557-   '/*' :  { 
566+   ... openApiExtensionRulesFunction ( { 
558567    '/description' : {  validate : checkType ( TYPE_STRING )  } , 
559568    '/headers' : openApiHeadersRules ( version ) , 
560569    '/content' : openApiMediaTypesRules ( version ) , 
@@ -568,11 +577,55 @@ const openApiResponsesRules = (version: OpenApiSpecVersion): NormalizationRules
568577    deprecation : { 
569578      inlineDescriptionSuffixCalculator : ctx  =>  `${ ctx . suffix }   '${ ctx . key . toString ( ) }  '` , 
570579    } , 
571-   } , 
580+   } ) , 
572581  deprecation : {  inlineDescriptionSuffixCalculator : ( )  =>  'in response'  } , 
573582  validate : checkType ( TYPE_OBJECT ) , 
574583} ) 
575584
585+ const  openApiPathItemRules  =  ( version : OpenApiSpecVersion ) : NormalizationRules  =>  ( { 
586+   deprecation : {  inlineDescriptionSuffixCalculator : ctx  =>  `${ ctx . key . toString ( ) }  `  } , 
587+   '/summary' : {  validate : checkType ( TYPE_STRING )  } , 
588+   '/description' : {  validate : checkType ( TYPE_STRING )  } , 
589+   '/servers' : { 
590+     '/*' : openApiServerRules , 
591+     validate : checkType ( TYPE_ARRAY ) , 
592+   } , 
593+   ...openApiExtensionRulesFunction ( { 
594+     deprecation : { 
595+       deprecationResolver : ( ctx )  =>  OPEN_API_DEPRECATION_RESOLVER ( ctx ) , 
596+       descriptionCalculator : ctx  =>  `[Deprecated] operation ${ ctx . key . toString ( ) . toUpperCase ( ) }   ${ ctx . suffix }  ` , 
597+     } , 
598+     '/tags' : { 
599+       '/*' : {  validate : checkType ( TYPE_STRING )  } , 
600+       validate : checkType ( TYPE_ARRAY ) , 
601+     } , 
602+     '/summary' : {  validate : checkType ( TYPE_STRING )  } , 
603+     '/description' : {  validate : checkType ( TYPE_STRING )  } , 
604+     ...openApiExternalDocsRules , 
605+     '/operationId' : {  validate : checkType ( TYPE_STRING )  } , 
606+     '/callbacks' : { 
607+       '/*' : { 
608+         ...openApiExtensionRulesFunction ( ( )  =>  openApiPathItemRules ( version ) ) , 
609+       } , 
610+     } , 
611+     '/deprecated' : {  validate : checkType ( TYPE_BOOLEAN )  } , 
612+     ...openApiSecurityRules , 
613+     ...openApiServersRules , 
614+     '/parameters' : openApiParametersRules ( version ) , 
615+     '/requestBody' : openApiRequestRules ( version ) , 
616+     '/responses' : openApiResponsesRules ( version ) , 
617+     ...openApiExtensionRules , 
618+     unify : [ 
619+       valueDefaults ( OPEN_API_OPERATION_DEFAULTS ) , 
620+       valueReplaces ( OPEN_API_OPERATION_REPLACES ) , 
621+     ] , 
622+     validate : checkType ( TYPE_OBJECT ) , 
623+   } ) , 
624+   '/parameters' : openApiParametersRules ( version ) , 
625+   validate : checkType ( TYPE_OBJECT ) , 
626+   unify : pathItemsUnification , 
627+ } ) 
628+ 
576629//TODO no 3.1 specific. Add it when need 
577630export  const  openApiRules  =  ( version : OpenApiSpecVersion ) : NormalizationRules  =>  ( { 
578631  '/openapi' : {  validate : checkType ( TYPE_STRING )  } , 
@@ -611,45 +664,7 @@ export const openApiRules = (version: OpenApiSpecVersion): NormalizationRules =>
611664    validate : checkType ( TYPE_ARRAY ) , 
612665  } , 
613666  '/paths' : { 
614-     '/*' : { 
615-       deprecation : {  inlineDescriptionSuffixCalculator : ctx  =>  `${ ctx . key . toString ( ) }  `  } , 
616-       '/summary' : {  validate : checkType ( TYPE_STRING )  } , 
617-       '/description' : {  validate : checkType ( TYPE_STRING )  } , 
618-       '/servers' : { 
619-         '/*' : openApiServerRules , 
620-         validate : checkType ( TYPE_ARRAY ) , 
621-       } , 
622-       '/*' : { 
623-         deprecation : { 
624-           deprecationResolver : ( ctx )  =>  OPEN_API_DEPRECATION_RESOLVER ( ctx ) , 
625-           descriptionCalculator : ctx  =>  `[Deprecated] operation ${ ctx . key . toString ( ) . toUpperCase ( ) }   ${ ctx . suffix }  ` 
626-         } , 
627-         '/tags' : { 
628-           '/*' : {  validate : checkType ( TYPE_STRING )  } , 
629-           validate : checkType ( TYPE_ARRAY ) , 
630-         } , 
631-         '/summary' : {  validate : checkType ( TYPE_STRING )  } , 
632-         '/description' : {  validate : checkType ( TYPE_STRING )  } , 
633-         ...openApiExternalDocsRules , 
634-         '/operationId' : {  validate : checkType ( TYPE_STRING )  } , 
635-         // '/callbacks': not supported 
636-         '/deprecated' : {  validate : checkType ( TYPE_BOOLEAN )  } , 
637-         ...openApiSecurityRules , 
638-         ...openApiServersRules , 
639-         '/parameters' : openApiParametersRules ( version ) , 
640-         '/requestBody' : openApiRequestRules ( version ) , 
641-         '/responses' : openApiResponsesRules ( version ) , 
642-         ...openApiExtensionRules , 
643-         unify : [ 
644-           valueDefaults ( OPEN_API_OPERATION_DEFAULTS ) , 
645-           valueReplaces ( OPEN_API_OPERATION_REPLACES ) , 
646-         ] , 
647-         validate : checkType ( TYPE_OBJECT ) , 
648-       } , 
649-       '/parameters' : openApiParametersRules ( version ) , 
650-       validate : checkType ( TYPE_OBJECT ) , 
651-       unify : pathItemsUnification , 
652-     } , 
667+     ...openApiExtensionRulesFunction ( openApiPathItemRules ( version ) ) , 
653668    validate : checkType ( TYPE_OBJECT ) , 
654669  } , 
655670  '/components' : { 
@@ -715,7 +730,11 @@ export const openApiRules = (version: OpenApiSpecVersion): NormalizationRules =>
715730      validate : checkType ( TYPE_OBJECT ) , 
716731    } , 
717732    '/headers' : openApiHeadersRules ( version ) , 
718-     // '/callbacks': not supported 
733+     '/callbacks' : { 
734+       '/*' : { 
735+         ...openApiExtensionRulesFunction ( ( )  =>  openApiPathItemRules ( version ) ) , 
736+       } , 
737+     } , 
719738    ...openApiExamplesRules , 
720739    ...openApiExtensionRules , 
721740    validate : checkType ( TYPE_OBJECT ) , 
@@ -724,6 +743,7 @@ export const openApiRules = (version: OpenApiSpecVersion): NormalizationRules =>
724743      valueReplaces ( OPEN_API_COMPONENTS_REPLACES ) , 
725744    ] , 
726745  } , 
746+   ...openApiExtensionRules , 
727747  unify : [ 
728748    valueDefaults ( OPEN_API_ROOT_DEFAULTS ) , 
729749    valueReplaces ( OPEN_API_ROOT_REPLACES ) , 
0 commit comments