1
1
import {
2
- cloneDeep ,
2
+ ArrayElement ,
3
+ cloneShallow ,
3
4
Element ,
4
5
isArrayElement ,
6
+ ObjectElement ,
5
7
StringElement ,
6
8
toValue ,
7
9
} from '@swagger-api/apidom-core' ;
@@ -41,12 +43,15 @@ const plugin =
41
43
( toolbox : Toolbox ) => {
42
44
const { ancestorLineageToJSONPointer } = toolbox ;
43
45
let storage : NormalizeStorage | undefined ;
46
+ let allOfDiscriminatorMapping : ObjectElement ;
44
47
45
48
return {
46
49
visitor : {
47
50
OpenApi3_1Element : {
48
51
enter ( element : OpenApi3_1Element ) {
49
52
storage = new NormalizeStorage ( element , storageField , 'discriminator-mapping' ) ;
53
+ allOfDiscriminatorMapping =
54
+ element . getMetaProperty ( 'allOfDiscriminatorMapping' ) ?? new ObjectElement ( ) ;
50
55
} ,
51
56
leave ( ) {
52
57
storage = undefined ;
@@ -82,19 +87,33 @@ const plugin =
82
87
return ;
83
88
}
84
89
85
- // skip if neither oneOf nor anyOf is present
86
- if ( ! isArrayElement ( schemaElement . oneOf ) && ! isArrayElement ( schemaElement . anyOf ) ) {
90
+ const parentElement = ancestors [ ancestors . length - 1 ] ;
91
+ const schemaName = schemaElement . getMetaProperty ( 'schemaName' ) ;
92
+ const allOfMapping = allOfDiscriminatorMapping . getMember ( toValue ( schemaName ) ) ;
93
+ const hasAllOfMapping =
94
+ // @ts -ignore
95
+ allOfMapping && ! parentElement ?. classes ?. contains ( 'json-schema-allOf' ) ;
96
+
97
+ // skip if neither oneOf, anyOf nor allOf is present
98
+ if (
99
+ ! isArrayElement ( schemaElement . oneOf ) &&
100
+ ! isArrayElement ( schemaElement . anyOf ) &&
101
+ ! hasAllOfMapping
102
+ ) {
87
103
return ;
88
104
}
89
105
90
106
const mapping =
91
107
schemaElement . discriminator . get ( 'mapping' ) ?? new DiscriminatorMappingElement ( ) ;
92
- const normalizedMapping : DiscriminatorMappingElement = cloneDeep ( mapping ) ;
108
+ const normalizedMapping : DiscriminatorMappingElement =
109
+ new DiscriminatorMappingElement ( ) ;
93
110
let isNormalized = true ;
94
111
95
112
const items = isArrayElement ( schemaElement . oneOf )
96
113
? schemaElement . oneOf
97
- : schemaElement . anyOf ;
114
+ : isArrayElement ( schemaElement . anyOf )
115
+ ? schemaElement . anyOf
116
+ : ( allOfMapping . value as ArrayElement ) ;
98
117
99
118
items ! . forEach ( ( item ) => {
100
119
if ( ! isSchemaElement ( item ) ) {
@@ -114,7 +133,10 @@ const plugin =
114
133
* handle external references and internal references
115
134
* that don't point to components/schemas/<SchemaName>
116
135
*/
117
- if ( metaRefOrigin !== baseURI || ( ! metaSchemaName && metaRefFields ) ) {
136
+ if (
137
+ ! hasAllOfMapping &&
138
+ ( metaRefOrigin !== baseURI || ( ! metaSchemaName && metaRefFields ) )
139
+ ) {
118
140
let hasMatchingMapping = false ;
119
141
120
142
mapping . forEach ( ( mappingValue : StringElement , mappingKey : StringElement ) => {
@@ -124,7 +146,7 @@ const plugin =
124
146
?. get ( '$refBaseURI' ) ;
125
147
126
148
if ( mappingValueSchemaRefBaseURI ?. equals ( metaRefFields ?. $refBaseURI ) ) {
127
- normalizedMapping . set ( toValue ( mappingKey ) , cloneDeep ( item ) ) ;
149
+ normalizedMapping . set ( toValue ( mappingKey ) , cloneShallow ( item ) ) ;
128
150
hasMatchingMapping = true ;
129
151
}
130
152
} ) ;
@@ -148,25 +170,29 @@ const plugin =
148
170
149
171
if (
150
172
mappingValueSchemaName ?. equals ( metaSchemaName ) &&
151
- mappingValueSchemaRefBaseURI ?. equals ( metaRefFields ?. $refBaseURI )
173
+ ( ! hasAllOfMapping ||
174
+ mappingValueSchemaRefBaseURI ?. equals ( metaRefFields ?. $refBaseURI ) )
152
175
) {
153
- normalizedMapping . set ( toValue ( mappingKey ) , cloneDeep ( item ) ) ;
176
+ normalizedMapping . set ( toValue ( mappingKey ) , cloneShallow ( item ) ) ;
154
177
hasMatchingMapping = true ;
155
178
}
156
179
} ) ;
157
180
158
181
// add a new mapping if no matching mapping was found
159
182
if ( ! hasMatchingMapping ) {
160
- normalizedMapping . set ( metaSchemaName , cloneDeep ( item ) ) ;
183
+ normalizedMapping . set ( metaSchemaName , cloneShallow ( item ) ) ;
161
184
}
162
185
}
163
186
} ) ;
164
187
165
- // check if any mapping is not a Schema Object
188
+ // check if any mapping is not a Schema Object or if any mapping was not normalized
189
+ const mappingKeys = mapping . keys ( ) ;
190
+ const normalizedMappingKeys = normalizedMapping . keys ( ) ;
166
191
isNormalized =
167
192
isNormalized &&
168
193
normalizedMapping . filter ( ( mappingValue : Element ) => ! isSchemaElement ( mappingValue ) )
169
- . length === 0 ;
194
+ . length === 0 &&
195
+ mappingKeys . every ( ( mappingKey : string ) => normalizedMappingKeys . includes ( mappingKey ) ) ;
170
196
171
197
if ( isNormalized ) {
172
198
schemaElement . discriminator . set ( 'x-normalized-mapping' , normalizedMapping ) ;
0 commit comments