Skip to content

Commit d430324

Browse files
committed
add fix for mixture of default and custom root type names
1 parent 4fb0d80 commit d430324

File tree

2 files changed

+58
-51
lines changed

2 files changed

+58
-51
lines changed

src/utilities/buildASTSchema.ts

Lines changed: 2 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import type { ParseOptions } from '../language/parser.js';
33
import { parse } from '../language/parser.js';
44
import type { Source } from '../language/source.js';
55

6-
import { specifiedDirectives } from '../type/directives.js';
76
import type { GraphQLSchemaValidationOptions } from '../type/schema.js';
87
import { GraphQLSchema } from '../type/schema.js';
98

@@ -38,49 +37,9 @@ export function buildASTSchema(
3837
assertValidSDL(documentAST);
3938
}
4039

41-
const emptySchemaConfig = {
42-
description: undefined,
43-
types: [],
44-
directives: [],
45-
extensions: Object.create(null),
46-
extensionASTNodes: [],
47-
assumeValid: false,
48-
};
49-
const config = extendSchemaImpl(emptySchemaConfig, documentAST, options);
40+
const config = extendSchemaImpl(documentAST, undefined, options);
5041

51-
if (config.astNode == null) {
52-
for (const type of config.types) {
53-
switch (type.name) {
54-
// Note: While this could make early assertions to get the correctly
55-
// typed values below, that would throw immediately while type system
56-
// validation with validateSchema() will produce more actionable results.
57-
case 'Query':
58-
// @ts-expect-error validated in `validateSchema`
59-
config.query = type;
60-
break;
61-
case 'Mutation':
62-
// @ts-expect-error validated in `validateSchema`
63-
config.mutation = type;
64-
break;
65-
case 'Subscription':
66-
// @ts-expect-error validated in `validateSchema`
67-
config.subscription = type;
68-
break;
69-
}
70-
}
71-
}
72-
73-
const directives = [
74-
...config.directives,
75-
// If specified directives were not explicitly declared, add them.
76-
...specifiedDirectives.filter((stdDirective) =>
77-
config.directives.every(
78-
(directive) => directive.name !== stdDirective.name,
79-
),
80-
),
81-
];
82-
83-
return new GraphQLSchema({ ...config, directives });
42+
return new GraphQLSchema(config);
8443
}
8544

8645
/**

src/utilities/extendSchema.ts

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ import {
6464
GraphQLOneOfDirective,
6565
GraphQLSpecifiedByDirective,
6666
isSpecifiedDirective,
67+
specifiedDirectives,
6768
} from '../type/directives.js';
6869
import {
6970
introspectionTypes,
@@ -116,7 +117,7 @@ export function extendSchema(
116117
}
117118

118119
const schemaConfig = schema.toConfig();
119-
const extendedConfig = extendSchemaImpl(schemaConfig, documentAST, options);
120+
const extendedConfig = extendSchemaImpl(documentAST, schemaConfig, options);
120121
return schemaConfig === extendedConfig
121122
? schema
122123
: new GraphQLSchema(extendedConfig);
@@ -126,10 +127,19 @@ export function extendSchema(
126127
* @internal
127128
*/
128129
export function extendSchemaImpl(
129-
schemaConfig: GraphQLSchemaNormalizedConfig,
130130
documentAST: DocumentNode,
131+
originalSchemaConfig: GraphQLSchemaNormalizedConfig | undefined,
131132
options?: Options,
132133
): GraphQLSchemaNormalizedConfig {
134+
const schemaConfig: GraphQLSchemaNormalizedConfig = originalSchemaConfig ?? {
135+
description: undefined,
136+
types: [],
137+
directives: [...specifiedDirectives],
138+
extensions: Object.create(null),
139+
extensionASTNodes: [],
140+
assumeValid: false,
141+
};
142+
133143
// Collect the type definitions and extensions found in the document.
134144
const typeDefs: Array<TypeDefinitionNode> = [];
135145

@@ -211,7 +221,12 @@ export function extendSchemaImpl(
211221
// If this document contains no new types, extensions, or directives then
212222
// return the same unmodified GraphQLSchema instance.
213223
if (!isSchemaChanged) {
214-
return schemaConfig;
224+
return originalSchemaConfig
225+
? originalSchemaConfig
226+
: {
227+
...schemaConfig,
228+
directives: [...specifiedDirectives],
229+
};
215230
}
216231

217232
const typeMap = new Map<string, GraphQLNamedType>(
@@ -230,19 +245,31 @@ export function extendSchemaImpl(
230245
subscription:
231246
schemaConfig.subscription && replaceNamedType(schemaConfig.subscription),
232247
// Then, incorporate schema definition and all schema extensions.
233-
...(schemaDef && getOperationTypes([schemaDef])),
248+
...(schemaDef
249+
? getOperationTypes([schemaDef])
250+
: !originalSchemaConfig && getDefaultOperationTypes()),
234251
...getOperationTypes(schemaExtensions),
235252
};
236253

254+
const newDirectives = directiveDefs.map(buildDirective);
255+
const directives = originalSchemaConfig
256+
? [...schemaConfig.directives.map(replaceDirective), ...newDirectives]
257+
: [
258+
...newDirectives,
259+
// If specified directives were not explicitly declared, add them.
260+
...specifiedDirectives.filter((stdDirective) =>
261+
newDirectives.every(
262+
(directive) => directive.name !== stdDirective.name,
263+
),
264+
),
265+
];
266+
237267
// Then produce and return a Schema config with these types.
238268
return {
239269
description: schemaDef?.description?.value ?? schemaConfig.description,
240270
...operationTypes,
241271
types: Array.from(typeMap.values()),
242-
directives: [
243-
...schemaConfig.directives.map(replaceDirective),
244-
...directiveDefs.map(buildDirective),
245-
],
272+
directives,
246273
extensions: schemaConfig.extensions,
247274
astNode: schemaDef ?? schemaConfig.astNode,
248275
extensionASTNodes: schemaConfig.extensionASTNodes.concat(schemaExtensions),
@@ -431,6 +458,27 @@ export function extendSchemaImpl(
431458
};
432459
}
433460

461+
function getDefaultOperationTypes(): {
462+
query?: Maybe<GraphQLObjectType>;
463+
mutation?: Maybe<GraphQLObjectType>;
464+
subscription?: Maybe<GraphQLObjectType>;
465+
} {
466+
const opTypes = {};
467+
for (const typeName of ['Query', 'Mutation', 'Subscription']) {
468+
const operationType = typeMap.get(typeName);
469+
470+
if (operationType) {
471+
// Note: While this could make early assertions to get the correctly
472+
// typed values below, that would throw immediately while type system
473+
// validation with validateSchema() will produce more actionable results.
474+
// @ts-expect-error
475+
opTypes[typeName.toLowerCase()] = operationType;
476+
}
477+
}
478+
479+
return opTypes;
480+
}
481+
434482
function getOperationTypes(
435483
nodes: ReadonlyArray<SchemaDefinitionNode | SchemaExtensionNode>,
436484
): {

0 commit comments

Comments
 (0)