From 408f48e67f1c38e1506a71c6566ca5b046cff809 Mon Sep 17 00:00:00 2001 From: Yaacov Rydzinski Date: Tue, 26 Nov 2024 11:30:48 +0200 Subject: [PATCH] simplify lexicographicSortSchema with mapSchemaConfig --- src/utilities/lexicographicSortSchema.ts | 189 +++++------------------ 1 file changed, 39 insertions(+), 150 deletions(-) diff --git a/src/utilities/lexicographicSortSchema.ts b/src/utilities/lexicographicSortSchema.ts index e3f25e1c4a..639aa6e01e 100644 --- a/src/utilities/lexicographicSortSchema.ts +++ b/src/utilities/lexicographicSortSchema.ts @@ -1,173 +1,62 @@ -import { inspect } from '../jsutils/inspect.js'; -import { invariant } from '../jsutils/invariant.js'; -import type { Maybe } from '../jsutils/Maybe.js'; import { naturalCompare } from '../jsutils/naturalCompare.js'; import type { ObjMap } from '../jsutils/ObjMap.js'; -import type { - GraphQLFieldConfigArgumentMap, - GraphQLFieldConfigMap, - GraphQLInputFieldConfigMap, - GraphQLNamedType, - GraphQLType, -} from '../type/definition.js'; -import { - GraphQLEnumType, - GraphQLInputObjectType, - GraphQLInterfaceType, - GraphQLList, - GraphQLNonNull, - GraphQLObjectType, - GraphQLUnionType, - isEnumType, - isInputObjectType, - isInterfaceType, - isListType, - isNonNullType, - isObjectType, - isScalarType, - isUnionType, -} from '../type/definition.js'; -import { GraphQLDirective } from '../type/directives.js'; -import { isIntrospectionType } from '../type/introspection.js'; import { GraphQLSchema } from '../type/schema.js'; +import { mapSchemaConfig, SchemaElementKind } from './mapSchemaConfig.js'; + /** * Sort GraphQLSchema. * * This function returns a sorted copy of the given GraphQLSchema. */ export function lexicographicSortSchema(schema: GraphQLSchema): GraphQLSchema { - const schemaConfig = schema.toConfig(); - const typeMap = new Map( - sortByName(schemaConfig.types).map((type) => [ - type.name, - sortNamedType(type), - ]), - ); - - return new GraphQLSchema({ - ...schemaConfig, - types: Array.from(typeMap.values()), - directives: sortByName(schemaConfig.directives).map(sortDirective), - query: replaceMaybeType(schemaConfig.query), - mutation: replaceMaybeType(schemaConfig.mutation), - subscription: replaceMaybeType(schemaConfig.subscription), - }); - - function replaceType(type: T): T { - if (isListType(type)) { - // @ts-expect-error - return new GraphQLList(replaceType(type.ofType)); - } else if (isNonNullType(type)) { - // @ts-expect-error - return new GraphQLNonNull(replaceType(type.ofType)); - } - // @ts-expect-error FIXME: TS Conversion - return replaceNamedType(type); - } - - function replaceNamedType(type: T): T { - return typeMap.get(type.name) as T; - } - - function replaceMaybeType( - maybeType: Maybe, - ): Maybe { - return maybeType && replaceNamedType(maybeType); - } - - function sortDirective(directive: GraphQLDirective) { - const config = directive.toConfig(); - return new GraphQLDirective({ - ...config, - locations: sortBy(config.locations, (x) => x), - args: sortArgs(config.args), - }); - } - - function sortArgs(args: GraphQLFieldConfigArgumentMap) { - return sortObjMap(args, (arg) => ({ - ...arg, - type: replaceType(arg.type), - })); - } - - function sortFields(fieldsMap: GraphQLFieldConfigMap) { - return sortObjMap(fieldsMap, (field) => ({ - ...field, - type: replaceType(field.type), - args: field.args && sortArgs(field.args), - })); - } - - function sortInputFields(fieldsMap: GraphQLInputFieldConfigMap) { - return sortObjMap(fieldsMap, (field) => ({ - ...field, - type: replaceType(field.type), - })); - } - - function sortTypes( - array: ReadonlyArray, - ): Array { - return sortByName(array).map(replaceNamedType); - } - - function sortNamedType(type: GraphQLNamedType): GraphQLNamedType { - if (isScalarType(type) || isIntrospectionType(type)) { - return type; - } - if (isObjectType(type)) { - const config = type.toConfig(); - return new GraphQLObjectType({ + return new GraphQLSchema( + mapSchemaConfig(schema.toConfig(), () => ({ + [SchemaElementKind.OBJECT]: (config) => ({ ...config, - interfaces: () => sortTypes(config.interfaces), - fields: () => sortFields(config.fields), - }); - } - if (isInterfaceType(type)) { - const config = type.toConfig(); - return new GraphQLInterfaceType({ + interfaces: () => sortByName(config.interfaces()), + fields: () => sortObjMap(config.fields()), + }), + [SchemaElementKind.FIELD]: (config) => ({ ...config, - interfaces: () => sortTypes(config.interfaces), - fields: () => sortFields(config.fields), - }); - } - if (isUnionType(type)) { - const config = type.toConfig(); - return new GraphQLUnionType({ + args: sortObjMap(config.args), + }), + [SchemaElementKind.INTERFACE]: (config) => ({ ...config, - types: () => sortTypes(config.types), - }); - } - if (isEnumType(type)) { - const config = type.toConfig(); - return new GraphQLEnumType({ + interfaces: () => sortByName(config.interfaces()), + fields: () => sortObjMap(config.fields()), + }), + [SchemaElementKind.UNION]: (config) => ({ ...config, - values: sortObjMap(config.values, (value) => value), - }); - } - if (isInputObjectType(type)) { - const config = type.toConfig(); - return new GraphQLInputObjectType({ + types: () => sortByName(config.types()), + }), + [SchemaElementKind.ENUM]: (config) => ({ ...config, - fields: () => sortInputFields(config.fields), - }); - } - /* c8 ignore next 3 */ - // Not reachable, all possible types have been considered. - invariant(false, 'Unexpected type: ' + inspect(type)); - } + values: () => sortObjMap(config.values()), + }), + [SchemaElementKind.INPUT_OBJECT]: (config) => ({ + ...config, + fields: () => sortObjMap(config.fields()), + }), + [SchemaElementKind.DIRECTIVE]: (config) => ({ + ...config, + locations: sortBy(config.locations, (x) => x), + args: sortObjMap(config.args), + }), + [SchemaElementKind.SCHEMA]: (config) => ({ + ...config, + types: sortByName(config.types), + directives: sortByName(config.directives), + }), + })), + ); } -function sortObjMap( - map: ObjMap, - sortValueFn: (value: T) => R, -): ObjMap { +function sortObjMap(map: ObjMap): ObjMap { const sortedMap = Object.create(null); for (const key of Object.keys(map).sort(naturalCompare)) { - sortedMap[key] = sortValueFn(map[key]); + sortedMap[key] = map[key]; } return sortedMap; }