@@ -184,6 +184,67 @@ function createDiscriminatorEnum(
184
184
} ;
185
185
}
186
186
187
+ function patchDiscriminatorEnum (
188
+ schema : SchemaObject ,
189
+ ref : string ,
190
+ values : string [ ] ,
191
+ discriminator : DiscriminatorObject ,
192
+ discriminatorRef : string ,
193
+ options : OpenAPITSOptions ,
194
+ ) : boolean {
195
+ const resolvedSchema = resolveRef < SchemaObject > ( schema , ref , {
196
+ silent : options . silent ?? false ,
197
+ } ) ;
198
+
199
+ if ( resolvedSchema ?. allOf ) {
200
+ // if the schema is an allOf, we can append a new schema object to the allOf array
201
+ resolvedSchema . allOf . push ( {
202
+ type : "object" ,
203
+ // discriminator enum properties always need to be required
204
+ required : [ discriminator . propertyName ] ,
205
+ properties : {
206
+ [ discriminator . propertyName ] : createDiscriminatorEnum ( values ) ,
207
+ } ,
208
+ } ) ;
209
+
210
+ return true ;
211
+ } else if (
212
+ typeof resolvedSchema === "object" &&
213
+ "type" in resolvedSchema &&
214
+ resolvedSchema . type === "object"
215
+ ) {
216
+ // if the schema is an object, we can apply the discriminator enums to its properties
217
+ if ( ! resolvedSchema . properties ) {
218
+ resolvedSchema . properties = { } ;
219
+ }
220
+
221
+ // discriminator enum properties always need to be required
222
+ if ( ! resolvedSchema . required ) {
223
+ resolvedSchema . required = [ discriminator . propertyName ] ;
224
+ } else if ( ! resolvedSchema . required . includes ( discriminator . propertyName ) ) {
225
+ resolvedSchema . required . push ( discriminator . propertyName ) ;
226
+ }
227
+
228
+ // add/replace the discriminator enum property
229
+ resolvedSchema . properties [ discriminator . propertyName ] =
230
+ createDiscriminatorEnum (
231
+ values ,
232
+ resolvedSchema . properties [ discriminator . propertyName ] ,
233
+ ) ;
234
+
235
+ return true ;
236
+ }
237
+
238
+ warn (
239
+ `Discriminator mapping has an invalid schema (neither an object schema nor an allOf array): ${ ref } => ${ values . join (
240
+ ", " ,
241
+ ) } (Discriminator: ${ discriminatorRef } )`,
242
+ options . silent ,
243
+ ) ;
244
+
245
+ return false ;
246
+ }
247
+
187
248
type InternalDiscriminatorMapping = Record <
188
249
string ,
189
250
{ inferred ?: string ; defined ?: string [ ] }
@@ -267,57 +328,18 @@ export function scanDiscriminators(
267
328
// the inferred enum values from the schema might not represent the actual enum values of the discriminator,
268
329
// so if we have defined values, use them instead
269
330
const mappedValues = defined ?? [ inferred ! ] ;
270
- const resolvedSchema = resolveRef < SchemaObject > ( schema , mappedRef , {
271
- silent : options . silent ?? false ,
272
- } ) ;
273
-
274
- if ( resolvedSchema ?. allOf ) {
275
- // if the schema is an allOf, we can append a new schema object to the allOf array
276
- resolvedSchema . allOf . push ( {
277
- type : "object" ,
278
- // discriminator enum properties always need to be required
279
- required : [ discriminator . propertyName ] ,
280
- properties : {
281
- [ discriminator . propertyName ] : createDiscriminatorEnum ( mappedValues ) ,
282
- } ,
283
- } ) ;
284
331
285
- refsHandled . push ( mappedRef ) ;
286
- } else if (
287
- typeof resolvedSchema === "object" &&
288
- "type" in resolvedSchema &&
289
- resolvedSchema . type === "object"
332
+ if (
333
+ patchDiscriminatorEnum (
334
+ schema ,
335
+ mappedRef ,
336
+ mappedValues ,
337
+ discriminator ,
338
+ ref ,
339
+ options ,
340
+ )
290
341
) {
291
- // if the schema is an object, we can apply the discriminator enums to its properties
292
- if ( ! resolvedSchema . properties ) {
293
- resolvedSchema . properties = { } ;
294
- }
295
-
296
- // discriminator enum properties always need to be required
297
- if ( ! resolvedSchema . required ) {
298
- resolvedSchema . required = [ discriminator . propertyName ] ;
299
- } else if (
300
- ! resolvedSchema . required . includes ( discriminator . propertyName )
301
- ) {
302
- resolvedSchema . required . push ( discriminator . propertyName ) ;
303
- }
304
-
305
- // add/replace the discriminator enum property
306
- resolvedSchema . properties [ discriminator . propertyName ] =
307
- createDiscriminatorEnum (
308
- mappedValues ,
309
- resolvedSchema . properties [ discriminator . propertyName ] ,
310
- ) ;
311
-
312
342
refsHandled . push ( mappedRef ) ;
313
- } else {
314
- warn (
315
- `Discriminator mapping has an invalid schema (neither an object schema nor an allOf array): ${ mappedRef } => ${ mappedValues . join (
316
- ", " ,
317
- ) } (Discriminator: ${ ref } )`,
318
- options . silent ,
319
- ) ;
320
- continue ;
321
343
}
322
344
}
323
345
} ) ;
@@ -326,19 +348,48 @@ export function scanDiscriminators(
326
348
// (sometimes this mapping is implicit, so it can’t be done until we know
327
349
// about every discriminator in the document)
328
350
walk ( schema , ( obj , path ) => {
329
- for ( const key of [ "allOf" ] as const ) {
330
- if ( obj && Array . isArray ( obj [ key ] ) ) {
331
- for ( const item of ( obj as any ) [ key ] ) {
332
- if ( "$ref" in item ) {
333
- if ( objects [ item . $ref ] ) {
334
- objects [ createRef ( path ) ] = {
335
- ...objects [ item . $ref ] ,
336
- } ;
351
+ if ( ! obj || ! Array . isArray ( obj . allOf ) ) {
352
+ return ;
353
+ }
354
+
355
+ for ( const item of ( obj as any ) . allOf ) {
356
+ if ( "$ref" in item ) {
357
+ if ( ! objects [ item . $ref ] ) {
358
+ return ;
359
+ }
360
+
361
+ const ref = createRef ( path ) ;
362
+ const discriminator = objects [ item . $ref ] ;
363
+ const mappedValues : string [ ] = [ ] ;
364
+
365
+ if ( discriminator . mapping ) {
366
+ for ( const mappedValue in discriminator . mapping ) {
367
+ if ( discriminator . mapping [ mappedValue ] === ref ) {
368
+ mappedValues . push ( mappedValue ) ;
369
+ }
370
+ }
371
+
372
+ if ( mappedValues . length > 0 ) {
373
+ if (
374
+ patchDiscriminatorEnum (
375
+ schema ,
376
+ ref ,
377
+ mappedValues ,
378
+ discriminator ,
379
+ item . $ref ,
380
+ options ,
381
+ )
382
+ ) {
383
+ refsHandled . push ( ref ) ;
337
384
}
338
- } else if ( item . discriminator ?. propertyName ) {
339
- objects [ createRef ( path ) ] = { ...item . discriminator } ;
340
385
}
341
386
}
387
+
388
+ objects [ ref ] = {
389
+ ...objects [ item . $ref ] ,
390
+ } ;
391
+ } else if ( item . discriminator ?. propertyName ) {
392
+ objects [ createRef ( path ) ] = { ...item . discriminator } ;
342
393
}
343
394
}
344
395
} ) ;
0 commit comments