Skip to content

Commit 40efdac

Browse files
committed
Allows to add schema definition missing in the original schema
Split out from graphql#1438
1 parent 732c90f commit 40efdac

File tree

2 files changed

+45
-9
lines changed

2 files changed

+45
-9
lines changed

src/utilities/__tests__/extendSchema-test.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1271,7 +1271,7 @@ describe('extendSchema', () => {
12711271
expect(schema.getMutationType()).to.equal(null);
12721272
});
12731273

1274-
it('does not allow new schema within an extension', () => {
1274+
it('does not allow overriding schema within an extension', () => {
12751275
const sdl = `
12761276
schema {
12771277
mutation: Mutation
@@ -1286,6 +1286,31 @@ describe('extendSchema', () => {
12861286
);
12871287
});
12881288

1289+
it('adds schema definition missing in the original schema', () => {
1290+
let schema = new GraphQLSchema({
1291+
directives: [
1292+
new GraphQLDirective({
1293+
name: 'onSchema',
1294+
locations: ['SCHEMA'],
1295+
}),
1296+
],
1297+
});
1298+
expect(schema.getQueryType()).to.equal(undefined);
1299+
1300+
const ast = parse(`
1301+
schema @onSchema {
1302+
query: Foo
1303+
}
1304+
1305+
type Foo {
1306+
bar: String
1307+
}
1308+
`);
1309+
schema = extendSchema(schema, ast);
1310+
const queryType = schema.getQueryType();
1311+
expect(queryType).to.have.property('name', 'Foo');
1312+
});
1313+
12891314
it('adds new root types via schema extension', () => {
12901315
const schema = extendTestSchema(`
12911316
extend schema {

src/utilities/extendSchema.js

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import type {
5353
DocumentNode,
5454
DirectiveDefinitionNode,
5555
SchemaExtensionNode,
56+
SchemaDefinitionNode,
5657
} from '../language/ast';
5758

5859
type Options = {|
@@ -106,18 +107,28 @@ export function extendSchema(
106107
// have the same name. For example, a type named "skip".
107108
const directiveDefinitions: Array<DirectiveDefinitionNode> = [];
108109

110+
let schemaDef: ?SchemaDefinitionNode;
109111
// Schema extensions are collected which may add additional operation types.
110112
const schemaExtensions: Array<SchemaExtensionNode> = [];
111113

112114
for (let i = 0; i < documentAST.definitions.length; i++) {
113115
const def = documentAST.definitions[i];
114116
switch (def.kind) {
115117
case Kind.SCHEMA_DEFINITION:
116-
// Sanity check that a schema extension is not defining a new schema
117-
throw new GraphQLError(
118-
'Cannot define a new schema within a schema extension.',
119-
[def],
120-
);
118+
// Sanity check that a schema extension is not overriding the schema
119+
if (
120+
schema.astNode ||
121+
schema.getQueryType() ||
122+
schema.getMutationType() ||
123+
schema.getSubscriptionType()
124+
) {
125+
throw new GraphQLError(
126+
'Cannot define a new schema within a schema extension.',
127+
[def],
128+
);
129+
}
130+
schemaDef = def;
131+
break;
121132
case Kind.SCHEMA_EXTENSION:
122133
schemaExtensions.push(def);
123134
break;
@@ -216,9 +227,9 @@ export function extendSchema(
216227
subscription: extendMaybeNamedType(schema.getSubscriptionType()),
217228
};
218229

219-
// Then, incorporate all schema extensions.
220-
for (const schemaExtension of schemaExtensions) {
221-
if (schemaExtension.operationTypes) {
230+
// Then, incorporate schema definition and all schema extensions.
231+
for (const schemaExtension of [schemaDef, ...schemaExtensions]) {
232+
if (schemaExtension && schemaExtension.operationTypes) {
222233
for (const operationType of schemaExtension.operationTypes) {
223234
const operation = operationType.operation;
224235
if (operationTypes[operation]) {

0 commit comments

Comments
 (0)