Skip to content

Commit 96a4e74

Browse files
committed
buildSchema: optimise perfomance by extracting 'extendSchemaImpl'
1 parent 3948aa2 commit 96a4e74

File tree

3 files changed

+52
-24
lines changed

3 files changed

+52
-24
lines changed

src/type/schema.js

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -270,14 +270,7 @@ export class GraphQLSchema {
270270
return find(this.getDirectives(), directive => directive.name === name);
271271
}
272272

273-
toConfig(): {|
274-
...GraphQLSchemaConfig,
275-
types: Array<GraphQLNamedType>,
276-
directives: Array<GraphQLDirective>,
277-
extensions: ?ReadOnlyObjMap<mixed>,
278-
extensionASTNodes: ?$ReadOnlyArray<SchemaExtensionNode>,
279-
assumeValid: boolean,
280-
|} {
273+
toConfig(): GraphQLSchemaNormalizedConfig {
281274
return {
282275
query: this.getQueryType(),
283276
mutation: this.getMutationType(),
@@ -325,6 +318,18 @@ export type GraphQLSchemaConfig = {|
325318
...GraphQLSchemaValidationOptions,
326319
|};
327320

321+
/**
322+
* @internal
323+
*/
324+
export type GraphQLSchemaNormalizedConfig = {|
325+
...GraphQLSchemaConfig,
326+
types: Array<GraphQLNamedType>,
327+
directives: Array<GraphQLDirective>,
328+
extensions: ?ReadOnlyObjMap<mixed>,
329+
extensionASTNodes: ?$ReadOnlyArray<SchemaExtensionNode>,
330+
assumeValid: boolean,
331+
|};
332+
328333
function collectImplementations(
329334
types: $ReadOnlyArray<GraphQLNamedType>,
330335
): ObjMap<InterfaceImplementations> {

src/utilities/buildASTSchema.js

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
GraphQLDeprecatedDirective,
2020
} from '../type/directives';
2121

22-
import { extendSchema } from './extendSchema';
22+
import { extendSchemaImpl } from './extendSchema';
2323

2424
export type BuildSchemaOptions = {|
2525
...GraphQLSchemaValidationOptions,
@@ -71,20 +71,28 @@ export function buildASTSchema(
7171
assertValidSDL(documentAST);
7272
}
7373

74-
const emptySchema = new GraphQLSchema({ directives: [] });
75-
const extendedSchema = extendSchema(emptySchema, documentAST, {
74+
const config = extendSchemaImpl(emptySchemaConfig, documentAST, {
7675
...options,
7776
assumeValidSDL: true,
7877
});
7978

80-
const config = extendedSchema.toConfig();
81-
if (extendedSchema.astNode == null) {
82-
// Note: While this could make early assertions to get the correctly
83-
// typed values below, that would throw immediately while type system
84-
// validation with validateSchema() will produce more actionable results.
85-
config.query = (extendedSchema.getType('Query'): any);
86-
config.mutation = (extendedSchema.getType('Mutation'): any);
87-
config.subscription = (extendedSchema.getType('Subscription'): any);
79+
if (config.astNode == null) {
80+
for (const type of config.types) {
81+
switch (type.name) {
82+
// Note: While this could make early assertions to get the correctly
83+
// typed values below, that would throw immediately while type system
84+
// validation with validateSchema() will produce more actionable results.
85+
case 'Query':
86+
config.query = (type: any);
87+
break;
88+
case 'Mutation':
89+
config.mutation = (type: any);
90+
break;
91+
case 'Subscription':
92+
config.subscription = (type: any);
93+
break;
94+
}
95+
}
8896
}
8997

9098
const { directives } = config;
@@ -101,10 +109,11 @@ export function buildASTSchema(
101109
directives.push(GraphQLDeprecatedDirective);
102110
}
103111

104-
config.assumeValid = (options && options.assumeValid) || false;
105112
return new GraphQLSchema(config);
106113
}
107114

115+
const emptySchemaConfig = new GraphQLSchema({ directives: [] }).toConfig();
116+
108117
/**
109118
* A helper function to build a GraphQLSchema directly from a source
110119
* document.

src/utilities/extendSchema.js

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import {
5757
type GraphQLSchemaValidationOptions,
5858
assertSchema,
5959
GraphQLSchema,
60+
type GraphQLSchemaNormalizedConfig,
6061
} from '../type/schema';
6162
import {
6263
type GraphQLType,
@@ -140,6 +141,18 @@ export function extendSchema(
140141
assertValidSDLExtension(documentAST, schema);
141142
}
142143

144+
const schemaConfig = schema.toConfig();
145+
const extendedConfig = extendSchemaImpl(schemaConfig, documentAST, options);
146+
return schemaConfig === extendedConfig
147+
? schema
148+
: new GraphQLSchema(extendedConfig);
149+
}
150+
151+
export function extendSchemaImpl(
152+
schemaConfig: GraphQLSchemaNormalizedConfig,
153+
documentAST: DocumentNode,
154+
options?: Options,
155+
): GraphQLSchemaNormalizedConfig {
143156
// Collect the type definitions and extensions found in the document.
144157
const typeDefs = [];
145158
const typeExtensionsMap = Object.create(null);
@@ -179,7 +192,7 @@ export function extendSchema(
179192
schemaExtensions.length === 0 &&
180193
!schemaDef
181194
) {
182-
return schema;
195+
return schemaConfig;
183196
}
184197

185198
const astBuilder = new ASTDefinitionBuilder(options, typeName => {
@@ -191,7 +204,6 @@ export function extendSchema(
191204
});
192205

193206
const typeMap = astBuilder.buildTypeMap(typeDefs, typeExtensionsMap);
194-
const schemaConfig = schema.toConfig();
195207
for (const existingType of schemaConfig.types) {
196208
typeMap[existingType.name] = extendNamedType(existingType);
197209
}
@@ -208,19 +220,21 @@ export function extendSchema(
208220
};
209221

210222
// Then produce and return a Schema with these types.
211-
return new GraphQLSchema({
223+
return {
212224
...operationTypes,
213225
types: objectValues(typeMap),
214226
directives: [
215227
...schemaConfig.directives.map(replaceDirective),
216228
...astBuilder.buildDirectives(directiveDefs),
217229
],
230+
extensions: Object.create(null),
218231
astNode: schemaDef || schemaConfig.astNode,
219232
extensionASTNodes: concatMaybeArrays(
220233
schemaConfig.extensionASTNodes,
221234
schemaExtensions,
222235
),
223-
});
236+
assumeValid: (options && options.assumeValid) || false,
237+
};
224238

225239
// Below are functions used for producing this schema that have closed over
226240
// this scope and have access to the schema, cache, and newly defined types.

0 commit comments

Comments
 (0)