@@ -52,7 +52,7 @@ function resolveRef (context, location, ref) {
52
52
hashIndex = ref . length
53
53
}
54
54
55
- const schemaId = ref . slice ( 0 , hashIndex ) || location . getOriginSchemaId ( )
55
+ const schemaId = ref . slice ( 0 , hashIndex ) || location . schemaId
56
56
const jsonPointer = ref . slice ( hashIndex ) || '#'
57
57
58
58
const schema = context . refResolver . getSchema ( schemaId , jsonPointer )
@@ -407,107 +407,137 @@ function buildInnerObject (context, location) {
407
407
return code
408
408
}
409
409
410
- function mergeAllOfSchema ( context , location , schema , mergedSchema ) {
411
- const allOfLocation = location . getPropertyLocation ( 'allOf' )
410
+ function mergeAllOfSchema ( context , location ) {
411
+ const schema = location . schema
412
+ const schemaWithoutAllOf = clone ( schema )
413
+ const clonedAllOfSchemas = schemaWithoutAllOf . allOf
412
414
413
- for ( let i = 0 ; i < schema . allOf . length ; i ++ ) {
414
- let allOfSchema = schema . allOf [ i ]
415
+ delete schemaWithoutAllOf . allOf
415
416
416
- if ( allOfSchema . $ref ) {
417
- const allOfSchemaLocation = allOfLocation . getPropertyLocation ( i )
418
- allOfSchema = resolveRef ( context , allOfSchemaLocation , allOfSchema . $ref ) . schema
419
- }
417
+ const allOfSchemasLocation = location . getPropertyLocation ( 'allOf' )
418
+ allOfSchemasLocation . schema = clonedAllOfSchemas
420
419
421
- let allOfSchemaType = allOfSchema . type
422
- if ( allOfSchemaType === undefined ) {
423
- allOfSchemaType = inferTypeByKeyword ( allOfSchema )
424
- }
420
+ const locations = [
421
+ new Location (
422
+ schemaWithoutAllOf ,
423
+ location . schemaId ,
424
+ location . jsonPointer
425
+ )
426
+ ]
425
427
426
- if ( allOfSchemaType !== undefined ) {
427
- if (
428
- mergedSchema . type !== undefined &&
429
- mergedSchema . type !== allOfSchemaType
430
- ) {
431
- throw new Error ( 'allOf schemas have different type values' )
432
- }
433
- mergedSchema . type = allOfSchemaType
434
- }
428
+ for ( let i = 0 ; i < clonedAllOfSchemas . length ; i ++ ) {
429
+ const allOfSchemaLocation = allOfSchemasLocation . getPropertyLocation ( i )
430
+ locations . push ( allOfSchemaLocation )
431
+ }
435
432
436
- if ( allOfSchema . format !== undefined ) {
437
- if (
438
- mergedSchema . format !== undefined &&
439
- mergedSchema . format !== allOfSchema . format
440
- ) {
441
- throw new Error ( 'allOf schemas have different format values' )
442
- }
443
- mergedSchema . format = allOfSchema . format
444
- }
433
+ const mergedLocation = mergeSchemas ( context , locations )
434
+ return mergedLocation
435
+ }
445
436
446
- if ( allOfSchema . nullable !== undefined ) {
447
- if (
448
- mergedSchema . nullable !== undefined &&
449
- mergedSchema . nullable !== allOfSchema . nullable
450
- ) {
451
- throw new Error ( 'allOf schemas have different nullable values' )
452
- }
453
- mergedSchema . nullable = allOfSchema . nullable
454
- }
437
+ function mergeSchemas ( context , locations ) {
438
+ const mergedSchema = { }
455
439
456
- if ( allOfSchema . properties !== undefined ) {
457
- if ( mergedSchema . properties === undefined ) {
458
- mergedSchema . properties = { }
459
- }
460
- Object . assign ( mergedSchema . properties , allOfSchema . properties )
461
- }
440
+ for ( let location of locations ) {
441
+ let schema = location . schema
442
+ resolveRelativeRefs ( schema , location . schemaId )
462
443
463
- if ( allOfSchema . additionalProperties !== undefined ) {
464
- if ( mergedSchema . additionalProperties === undefined ) {
465
- mergedSchema . additionalProperties = { }
466
- }
467
- Object . assign ( mergedSchema . additionalProperties , allOfSchema . additionalProperties )
468
- }
444
+ if ( schema . $ref ) {
445
+ const { $ref, ...schemaWithoutRef } = schema
446
+ const refSchemaLocation = resolveRef ( context , location , $ref )
447
+ refSchemaLocation . schema = clone ( refSchemaLocation . schema )
469
448
470
- if ( allOfSchema . patternProperties !== undefined ) {
471
- if ( mergedSchema . patternProperties === undefined ) {
472
- mergedSchema . patternProperties = { }
473
- }
474
- Object . assign ( mergedSchema . patternProperties , allOfSchema . patternProperties )
475
- }
449
+ const newSchemaLocation = new Location (
450
+ schemaWithoutRef ,
451
+ location . schemaId ,
452
+ location . jsonPointer
453
+ )
476
454
477
- if ( allOfSchema . required !== undefined ) {
478
- if ( mergedSchema . required === undefined ) {
479
- mergedSchema . required = [ ]
480
- }
481
- mergedSchema . required . push ( ... allOfSchema . required )
455
+ location = mergeSchemas (
456
+ context ,
457
+ [ refSchemaLocation , newSchemaLocation ]
458
+ )
459
+ schema = location . schema
482
460
}
483
461
484
- if ( allOfSchema . oneOf !== undefined ) {
485
- if ( mergedSchema . oneOf === undefined ) {
486
- mergedSchema . oneOf = [ ]
487
- }
488
- mergedSchema . oneOf . push ( ...allOfSchema . oneOf )
489
- }
462
+ for ( const key in schema ) {
463
+ const value = schema [ key ]
490
464
491
- if ( allOfSchema . anyOf !== undefined ) {
492
- if ( mergedSchema . anyOf === undefined ) {
493
- mergedSchema . anyOf = [ ]
465
+ if ( key === '$id' ) continue
466
+ if ( key === 'allOf' ) {
467
+ if ( mergedSchema . allOf === undefined ) {
468
+ mergedSchema . allOf = [ ]
469
+ }
470
+ mergedSchema . allOf . push ( ...value )
471
+ } else if ( key === 'anyOf' ) {
472
+ if ( mergedSchema . anyOf === undefined ) {
473
+ mergedSchema . anyOf = [ ]
474
+ }
475
+ mergedSchema . anyOf . push ( ...value )
476
+ } else if ( key === 'oneOf' ) {
477
+ if ( mergedSchema . oneOf === undefined ) {
478
+ mergedSchema . oneOf = [ ]
479
+ }
480
+ mergedSchema . oneOf . push ( ...value )
481
+ } else if ( key === 'required' ) {
482
+ if ( mergedSchema . required === undefined ) {
483
+ mergedSchema . required = [ ]
484
+ }
485
+ mergedSchema . required . push ( ...value )
486
+ } else if ( key === 'properties' ) {
487
+ if ( mergedSchema . properties === undefined ) {
488
+ mergedSchema . properties = { }
489
+ }
490
+ Object . assign ( mergedSchema . properties , value )
491
+ } else if ( key === 'patternProperties' ) {
492
+ if ( mergedSchema . patternProperties === undefined ) {
493
+ mergedSchema . patternProperties = { }
494
+ }
495
+ Object . assign ( mergedSchema . patternProperties , value )
496
+ } else if ( key === 'additionalProperties' ) {
497
+ if ( mergedSchema . additionalProperties === undefined ) {
498
+ mergedSchema . additionalProperties = { }
499
+ }
500
+ Object . assign ( mergedSchema . additionalProperties , value )
501
+ } else if ( key === 'type' ) {
502
+ if ( mergedSchema . type !== undefined && mergedSchema . type !== value ) {
503
+ throw new Error ( 'allOf schemas have different type values' )
504
+ }
505
+ mergedSchema . type = value
506
+ } else if ( key === 'format' ) {
507
+ if ( mergedSchema . format !== undefined && mergedSchema . format !== value ) {
508
+ throw new Error ( 'allOf schemas have different format values' )
509
+ }
510
+ mergedSchema . format = value
511
+ } else if ( key === 'nullable' ) {
512
+ if ( mergedSchema . nullable !== undefined && mergedSchema . nullable !== value ) {
513
+ throw new Error ( 'allOf schemas have different nullable values' )
514
+ }
515
+ mergedSchema . nullable = value
494
516
}
495
- mergedSchema . anyOf . push ( ...allOfSchema . anyOf )
496
517
}
518
+ }
519
+ const mergedSchemaId = `__fjs_merged_${ schemaIdCounter ++ } `
520
+ const mergedSchemaLocation = new Location ( mergedSchema , mergedSchemaId )
521
+ context . refResolver . addSchema ( mergedSchema , mergedSchemaId )
522
+ return mergedSchemaLocation
523
+ }
497
524
498
- if ( allOfSchema . allOf !== undefined ) {
499
- mergeAllOfSchema ( context , location , allOfSchema , mergedSchema )
525
+ function resolveRelativeRefs ( schema , schemaId ) {
526
+ if ( schema . $ref ?. charAt ( 0 ) === '#' ) {
527
+ schema . $ref = schemaId + schema . $ref
528
+ }
529
+ for ( const subSchema of Object . values ( schema ) ) {
530
+ if (
531
+ typeof subSchema === 'object' &&
532
+ subSchema . $id === undefined
533
+ ) {
534
+ resolveRelativeRefs ( subSchema , schemaId )
500
535
}
501
536
}
502
- delete mergedSchema . allOf
503
-
504
- mergedSchema . $id = `__fjs_merged_${ schemaIdCounter ++ } `
505
- context . refResolver . addSchema ( mergedSchema )
506
- location . addMergedSchema ( mergedSchema , mergedSchema . $id )
507
537
}
508
538
509
539
function addIfThenElse ( context , location , input ) {
510
- context . validatorSchemasIds . add ( location . getSchemaId ( ) )
540
+ context . validatorSchemasIds . add ( location . schemaId )
511
541
512
542
const schema = merge ( { } , location . schema )
513
543
const thenSchema = schema . then
@@ -872,16 +902,16 @@ function buildValue (context, location, input) {
872
902
}
873
903
874
904
if ( schema . allOf ) {
875
- mergeAllOfSchema ( context , location , schema , clone ( schema ) )
876
- schema = location . schema
905
+ const mergedSchemaLocation = mergeAllOfSchema ( context , location )
906
+ return buildValue ( context , mergedSchemaLocation , input )
877
907
}
878
908
879
909
const type = schema . type
880
910
881
911
let code = ''
882
912
883
913
if ( ( type === undefined || type === 'object' ) && ( schema . anyOf || schema . oneOf ) ) {
884
- context . validatorSchemasIds . add ( location . getSchemaId ( ) )
914
+ context . validatorSchemasIds . add ( location . schemaId )
885
915
886
916
if ( schema . type === 'object' ) {
887
917
context . wrapObjects = false
0 commit comments