Skip to content

Commit 3e4c728

Browse files
committed
simplify lexicographicSortSchema with mapSchemaConfig
1 parent 6a9976b commit 3e4c728

File tree

1 file changed

+39
-150
lines changed

1 file changed

+39
-150
lines changed

src/utilities/lexicographicSortSchema.ts

Lines changed: 39 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -1,173 +1,62 @@
1-
import { inspect } from '../jsutils/inspect.js';
2-
import { invariant } from '../jsutils/invariant.js';
3-
import type { Maybe } from '../jsutils/Maybe.js';
41
import { naturalCompare } from '../jsutils/naturalCompare.js';
52
import type { ObjMap } from '../jsutils/ObjMap.js';
63

7-
import type {
8-
GraphQLFieldConfigArgumentMap,
9-
GraphQLFieldConfigMap,
10-
GraphQLInputFieldConfigMap,
11-
GraphQLNamedType,
12-
GraphQLType,
13-
} from '../type/definition.js';
14-
import {
15-
GraphQLEnumType,
16-
GraphQLInputObjectType,
17-
GraphQLInterfaceType,
18-
GraphQLList,
19-
GraphQLNonNull,
20-
GraphQLObjectType,
21-
GraphQLUnionType,
22-
isEnumType,
23-
isInputObjectType,
24-
isInterfaceType,
25-
isListType,
26-
isNonNullType,
27-
isObjectType,
28-
isScalarType,
29-
isUnionType,
30-
} from '../type/definition.js';
31-
import { GraphQLDirective } from '../type/directives.js';
32-
import { isIntrospectionType } from '../type/introspection.js';
334
import { GraphQLSchema } from '../type/schema.js';
345

6+
import { mapSchemaConfig, SchemaElementKind } from './mapSchemaConfig.js';
7+
358
/**
369
* Sort GraphQLSchema.
3710
*
3811
* This function returns a sorted copy of the given GraphQLSchema.
3912
*/
4013
export function lexicographicSortSchema(schema: GraphQLSchema): GraphQLSchema {
41-
const schemaConfig = schema.toConfig();
42-
const typeMap = new Map<string, GraphQLNamedType>(
43-
sortByName(schemaConfig.types).map((type) => [
44-
type.name,
45-
sortNamedType(type),
46-
]),
47-
);
48-
49-
return new GraphQLSchema({
50-
...schemaConfig,
51-
types: Array.from(typeMap.values()),
52-
directives: sortByName(schemaConfig.directives).map(sortDirective),
53-
query: replaceMaybeType(schemaConfig.query),
54-
mutation: replaceMaybeType(schemaConfig.mutation),
55-
subscription: replaceMaybeType(schemaConfig.subscription),
56-
});
57-
58-
function replaceType<T extends GraphQLType>(type: T): T {
59-
if (isListType(type)) {
60-
// @ts-expect-error
61-
return new GraphQLList(replaceType(type.ofType));
62-
} else if (isNonNullType(type)) {
63-
// @ts-expect-error
64-
return new GraphQLNonNull(replaceType(type.ofType));
65-
}
66-
// @ts-expect-error FIXME: TS Conversion
67-
return replaceNamedType<GraphQLNamedType>(type);
68-
}
69-
70-
function replaceNamedType<T extends GraphQLNamedType>(type: T): T {
71-
return typeMap.get(type.name) as T;
72-
}
73-
74-
function replaceMaybeType<T extends GraphQLNamedType>(
75-
maybeType: Maybe<T>,
76-
): Maybe<T> {
77-
return maybeType && replaceNamedType(maybeType);
78-
}
79-
80-
function sortDirective(directive: GraphQLDirective) {
81-
const config = directive.toConfig();
82-
return new GraphQLDirective({
83-
...config,
84-
locations: sortBy(config.locations, (x) => x),
85-
args: sortArgs(config.args),
86-
});
87-
}
88-
89-
function sortArgs(args: GraphQLFieldConfigArgumentMap) {
90-
return sortObjMap(args, (arg) => ({
91-
...arg,
92-
type: replaceType(arg.type),
93-
}));
94-
}
95-
96-
function sortFields(fieldsMap: GraphQLFieldConfigMap<unknown, unknown>) {
97-
return sortObjMap(fieldsMap, (field) => ({
98-
...field,
99-
type: replaceType(field.type),
100-
args: field.args && sortArgs(field.args),
101-
}));
102-
}
103-
104-
function sortInputFields(fieldsMap: GraphQLInputFieldConfigMap) {
105-
return sortObjMap(fieldsMap, (field) => ({
106-
...field,
107-
type: replaceType(field.type),
108-
}));
109-
}
110-
111-
function sortTypes<T extends GraphQLNamedType>(
112-
array: ReadonlyArray<T>,
113-
): Array<T> {
114-
return sortByName(array).map(replaceNamedType);
115-
}
116-
117-
function sortNamedType(type: GraphQLNamedType): GraphQLNamedType {
118-
if (isScalarType(type) || isIntrospectionType(type)) {
119-
return type;
120-
}
121-
if (isObjectType(type)) {
122-
const config = type.toConfig();
123-
return new GraphQLObjectType({
14+
return new GraphQLSchema(
15+
mapSchemaConfig(schema.toConfig(), () => ({
16+
[SchemaElementKind.OBJECT]: (config) => ({
12417
...config,
125-
interfaces: () => sortTypes(config.interfaces),
126-
fields: () => sortFields(config.fields),
127-
});
128-
}
129-
if (isInterfaceType(type)) {
130-
const config = type.toConfig();
131-
return new GraphQLInterfaceType({
18+
interfaces: () => sortByName(config.interfaces()),
19+
fields: () => sortObjMap(config.fields()),
20+
}),
21+
[SchemaElementKind.FIELD]: (config) => ({
13222
...config,
133-
interfaces: () => sortTypes(config.interfaces),
134-
fields: () => sortFields(config.fields),
135-
});
136-
}
137-
if (isUnionType(type)) {
138-
const config = type.toConfig();
139-
return new GraphQLUnionType({
23+
args: sortObjMap(config.args),
24+
}),
25+
[SchemaElementKind.INTERFACE]: (config) => ({
14026
...config,
141-
types: () => sortTypes(config.types),
142-
});
143-
}
144-
if (isEnumType(type)) {
145-
const config = type.toConfig();
146-
return new GraphQLEnumType({
27+
interfaces: () => sortByName(config.interfaces()),
28+
fields: () => sortObjMap(config.fields()),
29+
}),
30+
[SchemaElementKind.UNION]: (config) => ({
14731
...config,
148-
values: sortObjMap(config.values, (value) => value),
149-
});
150-
}
151-
if (isInputObjectType(type)) {
152-
const config = type.toConfig();
153-
return new GraphQLInputObjectType({
32+
types: () => sortByName(config.types()),
33+
}),
34+
[SchemaElementKind.ENUM]: (config) => ({
15435
...config,
155-
fields: () => sortInputFields(config.fields),
156-
});
157-
}
158-
/* c8 ignore next 3 */
159-
// Not reachable, all possible types have been considered.
160-
invariant(false, 'Unexpected type: ' + inspect(type));
161-
}
36+
values: () => sortObjMap(config.values()),
37+
}),
38+
[SchemaElementKind.INPUT_OBJECT]: (config) => ({
39+
...config,
40+
fields: () => sortObjMap(config.fields()),
41+
}),
42+
[SchemaElementKind.DIRECTIVE]: (config) => ({
43+
...config,
44+
locations: sortBy(config.locations, (x) => x),
45+
args: sortObjMap(config.args),
46+
}),
47+
[SchemaElementKind.SCHEMA]: (config) => ({
48+
...config,
49+
types: sortByName(config.types),
50+
directives: sortByName(config.directives),
51+
}),
52+
})),
53+
);
16254
}
16355

164-
function sortObjMap<T, R>(
165-
map: ObjMap<T>,
166-
sortValueFn: (value: T) => R,
167-
): ObjMap<R> {
56+
function sortObjMap<T, R>(map: ObjMap<T>): ObjMap<R> {
16857
const sortedMap = Object.create(null);
16958
for (const key of Object.keys(map).sort(naturalCompare)) {
170-
sortedMap[key] = sortValueFn(map[key]);
59+
sortedMap[key] = map[key];
17160
}
17261
return sortedMap;
17362
}

0 commit comments

Comments
 (0)