@@ -5,7 +5,11 @@ import {
5
5
isArrayElement ,
6
6
ObjectElement ,
7
7
StringElement ,
8
+ MemberElement ,
8
9
toValue ,
10
+ visit ,
11
+ isMemberElement ,
12
+ isStringElement ,
9
13
} from '@swagger-api/apidom-core' ;
10
14
import { isReferenceLikeElement , isDiscriminatorElement } from '@swagger-api/apidom-ns-openapi-3-0' ;
11
15
@@ -14,15 +18,21 @@ import OpenApi3_1Element from '../../elements/OpenApi3-1.ts';
14
18
import NormalizeStorage from './normalize-header-examples/NormalizeStorage.ts' ;
15
19
import { SchemaElement } from '../registration.ts' ;
16
20
import { isSchemaElement } from '../../predicates.ts' ;
21
+ import DiscriminatorElement from '../../elements/Discriminator.ts' ;
17
22
18
23
/**
19
24
* Normalization of Discriminator.mapping field.
20
25
*
21
26
* Discriminator.mapping fields are normalized by adding missing mappings from oneOf/anyOf items
22
27
* of the parent Schema Object and transforming existing mappings to Schema Objects.
23
28
*
29
+ * In case of allOf discriminator, the plugin will add missing mappings based on
30
+ * allOf items of other Schema Objects.
31
+ *
24
32
* The normalized mapping is stored in the Schema.discriminator field as `x-normalized-mapping`.
25
33
*
34
+ * This plugin is designed to be used on dereferenced OpenAPI 3.1 documents.
35
+ *
26
36
* NOTE: this plugin is idempotent
27
37
* @public
28
38
*/
@@ -191,6 +201,48 @@ const plugin =
191
201
192
202
if ( isNormalized ) {
193
203
schemaElement . discriminator . set ( 'x-normalized-mapping' , normalizedMapping ) ;
204
+
205
+ // dive in and eliminate cycles that might be created by normalization
206
+ visit (
207
+ schemaElement ,
208
+ { } ,
209
+ {
210
+ // @ts -ignore
211
+ detectCyclesCallback : < T extends Element > (
212
+ node : T ,
213
+ nodeKey : string | number ,
214
+ nodeParent : Element | undefined ,
215
+ ) => {
216
+ if (
217
+ ! nodeParent ||
218
+ ! isMemberElement ( node ) ||
219
+ ! isStringElement ( node . key ) ||
220
+ ! node . key . equals ( 'discriminator' ) ||
221
+ ! isDiscriminatorElement ( node . value )
222
+ ) {
223
+ return ;
224
+ }
225
+
226
+ const discriminator = cloneShallow ( node . value ) ;
227
+ const discriminatorCopy = new DiscriminatorElement ( ) ;
228
+
229
+ if ( discriminator . get ( 'mapping' ) ) {
230
+ discriminatorCopy . mapping = discriminator . get ( 'mapping' ) ;
231
+ }
232
+
233
+ if ( discriminator . get ( 'propertyName' ) ) {
234
+ discriminatorCopy . propertyName = discriminator . get ( 'propertyName' ) ;
235
+ }
236
+
237
+ // eslint-disable-next-line no-param-reassign
238
+ nodeParent [ nodeKey ] = new MemberElement (
239
+ new StringElement ( 'discriminator' ) ,
240
+ discriminatorCopy ,
241
+ ) ;
242
+ } ,
243
+ } ,
244
+ ) ;
245
+
194
246
storage ! . append ( schemaJSONPointer ) ;
195
247
}
196
248
} ,
0 commit comments