Skip to content

Commit

Permalink
[RFC] Add Schema Definition to IDL.
Browse files Browse the repository at this point in the history
This implements the schema definition in the spec proposal in graphql/graphql-spec#90

Adjusts AST, parser, printer, visitor, but also changes the API of buildASTSchema to require a schema definition instead of passing the type names into the function.
  • Loading branch information
leebyron committed Mar 22, 2016
1 parent 176076c commit 8379e71
Show file tree
Hide file tree
Showing 12 changed files with 509 additions and 89 deletions.
5 changes: 5 additions & 0 deletions src/language/__tests__/schema-kitchen-sink.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.

schema {
query: QueryType
mutation: MutationType
}

type Foo implements Bar {
one: Type
two(argument: InputType!): Type
Expand Down
7 changes: 6 additions & 1 deletion src/language/__tests__/schema-printer.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,12 @@ describe('Printer', () => {

/* eslint-disable max-len */
expect(printed).to.equal(
`type Foo implements Bar {
`schema {
query: QueryType
mutation: MutationType
}
type Foo implements Bar {
one: Type
two(argument: InputType!): Type
three(argument: InputType, other: String): Int
Expand Down
28 changes: 23 additions & 5 deletions src/language/ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,14 @@ export type Node = Name
| NamedType
| ListType
| NonNullType
| SchemaDefinition
| OperationTypeDefinition
| ScalarTypeDefinition
| ObjectTypeDefinition
| FieldDefinition
| InputValueDefinition
| InterfaceTypeDefinition
| UnionTypeDefinition
| ScalarTypeDefinition
| EnumTypeDefinition
| EnumValueDefinition
| InputObjectTypeDefinition
Expand All @@ -77,19 +79,21 @@ export type Document = {

export type Definition = OperationDefinition
| FragmentDefinition
| TypeSystemDefinition
| TypeSystemDefinition // experimental non-spec addition.

export type OperationDefinition = {
kind: 'OperationDefinition';
loc?: ?Location;
// Note: subscription is an experimental non-spec addition.
operation: 'query' | 'mutation' | 'subscription';
operation: OperationType;
name?: ?Name;
variableDefinitions?: ?Array<VariableDefinition>;
directives?: ?Array<Directive>;
selectionSet: SelectionSet;
}

// Note: subscription is an experimental non-spec addition.
export type OperationType = 'query' | 'mutation' | 'subscription';

export type VariableDefinition = {
kind: 'VariableDefinition';
loc?: ?Location;
Expand Down Expand Up @@ -256,10 +260,24 @@ export type NonNullType = {

// Type System Definition

export type TypeSystemDefinition = TypeDefinition
export type TypeSystemDefinition = SchemaDefinition
| TypeDefinition
| TypeExtensionDefinition
| DirectiveDefinition

export type SchemaDefinition = {
kind: 'SchemaDefinition';
loc?: ?Location;
operationTypes: Array<OperationTypeDefinition>;
}

export type OperationTypeDefinition = {
kind: 'OperationTypeDefinition';
loc?: ?Location;
operation: OperationType;
type: NamedType;
}

export type TypeDefinition = ScalarTypeDefinition
| ObjectTypeDefinition
| InterfaceTypeDefinition
Expand Down
3 changes: 3 additions & 0 deletions src/language/kinds.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ export const NON_NULL_TYPE = 'NonNullType';

// Type System Definitions

export const SCHEMA_DEFINITION = 'SchemaDefinition';
export const OPERATION_TYPE_DEFINITION = 'OperationTypeDefinition';

// Type Definitions

export const SCALAR_TYPE_DEFINITION = 'ScalarTypeDefinition';
Expand Down
67 changes: 59 additions & 8 deletions src/language/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import type {
Document,
Definition,
OperationDefinition,
OperationType,
VariableDefinition,
SelectionSet,
Selection,
Expand All @@ -41,6 +42,9 @@ import type {

TypeSystemDefinition,

SchemaDefinition,
OperationTypeDefinition,

ScalarTypeDefinition,
ObjectTypeDefinition,
FieldDefinition,
Expand Down Expand Up @@ -86,6 +90,9 @@ import {
LIST_TYPE,
NON_NULL_TYPE,

SCHEMA_DEFINITION,
OPERATION_TYPE_DEFINITION,

SCALAR_TYPE_DEFINITION,
OBJECT_TYPE_DEFINITION,
FIELD_DEFINITION,
Expand Down Expand Up @@ -203,6 +210,7 @@ function parseDefinition(parser: Parser): Definition {
case 'fragment': return parseFragmentDefinition(parser);

// Note: the Type System IDL is an experimental non-spec addition.
case 'schema':
case 'scalar':
case 'type':
case 'interface':
Expand All @@ -224,8 +232,6 @@ function parseDefinition(parser: Parser): Definition {
* OperationDefinition :
* - SelectionSet
* - OperationType Name? VariableDefinitions? Directives? SelectionSet
*
* OperationType : one of query mutation
*/
function parseOperationDefinition(parser: Parser): OperationDefinition {
const start = parser.token.start;
Expand All @@ -240,12 +246,7 @@ function parseOperationDefinition(parser: Parser): OperationDefinition {
loc: loc(parser, start)
};
}
const operationToken = expect(parser, TokenKind.NAME);
const operation =
operationToken.value === 'mutation' ? 'mutation' :
operationToken.value === 'subscription' ? 'subscription' :
operationToken.value === 'query' ? 'query' :
(() => { throw unexpected(parser, operationToken); })();
const operation = parseOperationType(parser);
let name;
if (peek(parser, TokenKind.NAME)) {
name = parseName(parser);
Expand All @@ -261,6 +262,21 @@ function parseOperationDefinition(parser: Parser): OperationDefinition {
};
}

/**
* OperationType : one of query mutation subscription
*/
function parseOperationType(parser: Parser): OperationType {
const operationToken = expect(parser, TokenKind.NAME);
switch (operationToken.value) {
case 'query': return 'query';
case 'mutation': return 'mutation';
// Note: subscription is an experimental non-spec addition.
case 'subscription': return 'subscription';
}

throw unexpected(parser, operationToken);
}

/**
* VariableDefinitions : ( VariableDefinition+ )
*/
Expand Down Expand Up @@ -666,6 +682,7 @@ export function parseNamedType(parser: Parser): NamedType {
function parseTypeSystemDefinition(parser: Parser): TypeSystemDefinition {
if (peek(parser, TokenKind.NAME)) {
switch (parser.token.value) {
case 'schema': return parseSchemaDefinition(parser);
case 'scalar': return parseScalarTypeDefinition(parser);
case 'type': return parseObjectTypeDefinition(parser);
case 'interface': return parseInterfaceTypeDefinition(parser);
Expand All @@ -680,6 +697,40 @@ function parseTypeSystemDefinition(parser: Parser): TypeSystemDefinition {
throw unexpected(parser);
}

/**
* SchemaDefinition : schema { OperationTypeDefinition+ }
*
* OperationTypeDefinition : OperationType : NamedType
*/
function parseSchemaDefinition(parser: Parser): SchemaDefinition {
const start = parser.token.start;
expectKeyword(parser, 'schema');
const operationTypes = many(
parser,
TokenKind.BRACE_L,
parseOperationTypeDefinition,
TokenKind.BRACE_R
);
return {
kind: SCHEMA_DEFINITION,
operationTypes,
loc: loc(parser, start),
};
}

function parseOperationTypeDefinition(parser: Parser): OperationTypeDefinition {
const start = parser.token.start;
const operation = parseOperationType(parser);
expect(parser, TokenKind.COLON);
const type = parseNamedType(parser);
return {
kind: OPERATION_TYPE_DEFINITION,
operation,
type,
loc: loc(parser, start),
};
}

/**
* ScalarTypeDefinition : scalar Name
*/
Expand Down
6 changes: 6 additions & 0 deletions src/language/printer.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ const printDocASTReducer = {

// Type System Definitions

SchemaDefinition: ({ operationTypes }) =>
'schema ' + block(operationTypes),

OperationTypeDefinition: ({ operation, type }) =>
operation + ': ' + type,

ScalarTypeDefinition: ({ name }) =>
`scalar ${name}`,

Expand Down
7 changes: 6 additions & 1 deletion src/language/visitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,21 @@ export const QueryDocumentKeys = {
ListType: [ 'type' ],
NonNullType: [ 'type' ],

SchemaDefinition: [ 'operationTypes' ],
OperationTypeDefinition: [ 'type' ],

ScalarTypeDefinition: [ 'name' ],
ObjectTypeDefinition: [ 'name', 'interfaces', 'fields' ],
FieldDefinition: [ 'name', 'arguments', 'type' ],
InputValueDefinition: [ 'name', 'type', 'defaultValue' ],
InterfaceTypeDefinition: [ 'name', 'fields' ],
UnionTypeDefinition: [ 'name', 'types' ],
ScalarTypeDefinition: [ 'name' ],
EnumTypeDefinition: [ 'name', 'values' ],
EnumValueDefinition: [ 'name' ],
InputObjectTypeDefinition: [ 'name', 'fields' ],

TypeExtensionDefinition: [ 'definition' ],

DirectiveDefinition: [ 'name', 'arguments', 'locations' ],
};

Expand Down
Loading

0 comments on commit 8379e71

Please sign in to comment.