From ac4f915494f289d1c97ffdfe3af59efd94734f8c Mon Sep 17 00:00:00 2001 From: Mohamed Zenadi Date: Fri, 27 Mar 2020 12:09:51 +0100 Subject: [PATCH] fix: sort discriminator entries by mapping order (#1216) * sort discriminator entries by mapping order * fix string compare --- src/services/models/Schema.ts | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/services/models/Schema.ts b/src/services/models/Schema.ts index b6401c9add..722c2bb78d 100644 --- a/src/services/models/Schema.ts +++ b/src/services/models/Schema.ts @@ -263,7 +263,7 @@ export class SchemaModel { const inversedMapping = isLimitedToMapping ? { ...explicitInversedMapping } : { ...implicitInversedMapping, ...explicitInversedMapping }; - const refs: Array<{ $ref; name }> = []; + let refs: Array<{ $ref; name }> = []; for (const $ref of Object.keys(inversedMapping)) { const names = inversedMapping[$ref]; @@ -276,6 +276,35 @@ export class SchemaModel { } } + // Make the listing respects the mapping + // in case a mapping is defined, the user usually wants to have the order shown + // as it was defined in the yaml. This will sort the names given the provided + // mapping (if provided). + // The logic is: + // - If a name is among the mapping, promote it to first + // - Names among the mapping are sorted by their order in the mapping + // - Names outside the mapping are sorted alphabetically + const names = Object.keys(mapping); + if (names.length !== 0) { + refs = refs.sort((left, right) => { + const indexLeft = names.indexOf(left.name); + const indexRight = names.indexOf(right.name); + + if (indexLeft < 0 && indexRight < 0) { + // out of mapping, order by name + return left.name.localCompare(right.name); + } else if (indexLeft < 0) { + // the right is found, so mapping wins + return 1; + } else if (indexRight < 0) { + // left wins as it's in mapping + return -1; + } else { + return indexLeft - indexRight; + } + }); + } + this.oneOf = refs.map(({ $ref, name }) => { const innerSchema = new SchemaModel(parser, parser.byRef($ref)!, $ref, this.options, true); innerSchema.title = name;