Skip to content

Commit

Permalink
Add @stream directive to specified directives
Browse files Browse the repository at this point in the history
  • Loading branch information
robrichard committed Oct 22, 2020
1 parent 43efcb5 commit 293a89f
Show file tree
Hide file tree
Showing 14 changed files with 123 additions and 15 deletions.
1 change: 1 addition & 0 deletions src/__tests__/starWarsIntrospection-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ describe('Star Wars Introspection Tests', () => {
{ name: 'Droid' },
{ name: 'Query' },
{ name: 'Boolean' },
{ name: 'Int' },
{ name: '__Schema' },
{ name: '__Type' },
{ name: '__TypeKind' },
Expand Down
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export {
GraphQLIncludeDirective,
GraphQLSkipDirective,
GraphQLDeferDirective,
GraphQLStreamDirective,
GraphQLDeprecatedDirective,
GraphQLSpecifiedByDirective,
// "Enum" of Type Kinds
Expand Down
48 changes: 48 additions & 0 deletions src/type/__tests__/introspection-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ describe('Introspection', () => {
enumValues: null,
possibleTypes: null,
},
{
kind: 'SCALAR',
name: 'Int',
specifiedByUrl: null,
fields: null,
inputFields: null,
interfaces: null,
enumValues: null,
possibleTypes: null,
},
{
kind: 'OBJECT',
name: '__Schema',
Expand Down Expand Up @@ -961,6 +971,44 @@ describe('Introspection', () => {
},
],
},
{
name: 'stream',
isRepeatable: false,
locations: ['FIELD'],
args: [
{
defaultValue: null,
name: 'if',
type: {
kind: 'SCALAR',
name: 'Boolean',
ofType: null,
},
},
{
defaultValue: null,
name: 'label',
type: {
kind: 'SCALAR',
name: 'String',
ofType: null,
},
},
{
defaultValue: null,
name: 'initialCount',
type: {
kind: 'NON_NULL',
name: null,
ofType: {
kind: 'SCALAR',
name: 'Int',
ofType: null,
},
},
},
],
},
{
name: 'deprecated',
isRepeatable: false,
Expand Down
1 change: 1 addition & 0 deletions src/type/__tests__/schema-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ describe('Type System: Schema', () => {
'ASub',
'Boolean',
'String',
'Int',
'__Schema',
'__Type',
'__TypeKind',
Expand Down
5 changes: 5 additions & 0 deletions src/type/directives.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ export const GraphQLSkipDirective: GraphQLDirective;
*/
export const GraphQLDeferDirective: GraphQLDirective;

/**
* Used to conditionally stream list fields.
*/
export const GraphQLStreamDirective: GraphQLDirective;

/**
* Used to provide a URL for specifying the behavior of custom scalar definitions.
*/
Expand Down
27 changes: 26 additions & 1 deletion src/type/directives.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import type {
GraphQLArgument,
GraphQLFieldConfigArgumentMap,
} from './definition';
import { GraphQLString, GraphQLBoolean } from './scalars';
import { GraphQLString, GraphQLBoolean, GraphQLInt } from './scalars';
import { argsToArgsConfig, GraphQLNonNull } from './definition';

/**
Expand Down Expand Up @@ -191,6 +191,30 @@ export const GraphQLDeferDirective = new GraphQLDirective({
},
});

/**
* Used to conditionally stream list fields.
*/
export const GraphQLStreamDirective = new GraphQLDirective({
name: 'stream',
description:
'Directs the executor to stream plural fields when the `if` argument is true or undefined.',
locations: [DirectiveLocation.FIELD],
args: {
if: {
type: GraphQLBoolean,
description: 'Stream when true or undefined.',
},
label: {
type: GraphQLString,
description: 'Unique name',
},
initialCount: {
type: new GraphQLNonNull(GraphQLInt),
description: 'Number of items to return immediately',
},
},
});

/**
* Constant string used for default reason for a deprecation.
*/
Expand Down Expand Up @@ -240,6 +264,7 @@ export const specifiedDirectives = Object.freeze([
GraphQLIncludeDirective,
GraphQLSkipDirective,
GraphQLDeferDirective,
GraphQLStreamDirective,
GraphQLDeprecatedDirective,
GraphQLSpecifiedByDirective,
]);
Expand Down
1 change: 1 addition & 0 deletions src/type/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ export {
GraphQLIncludeDirective,
GraphQLSkipDirective,
GraphQLDeferDirective,
GraphQLStreamDirective,
GraphQLDeprecatedDirective,
GraphQLSpecifiedByDirective,
// Constant Deprecation Reason
Expand Down
1 change: 1 addition & 0 deletions src/type/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export {
GraphQLIncludeDirective,
GraphQLSkipDirective,
GraphQLDeferDirective,
GraphQLStreamDirective,
GraphQLDeprecatedDirective,
GraphQLSpecifiedByDirective,
// Constant Deprecation Reason
Expand Down
14 changes: 9 additions & 5 deletions src/utilities/__tests__/buildASTSchema-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
GraphQLDeprecatedDirective,
GraphQLSpecifiedByDirective,
GraphQLDeferDirective,
GraphQLStreamDirective,
} from '../../type/directives';
import {
GraphQLID,
Expand Down Expand Up @@ -162,8 +163,7 @@ describe('Schema Builder', () => {
it('include standard type only if it is used', () => {
const schema = buildSchema('type Query');

// String and Boolean are always included through introspection types
expect(schema.getType('Int')).to.equal(undefined);
// String, Boolean, and Int are always included through introspection types
expect(schema.getType('Float')).to.equal(undefined);
expect(schema.getType('ID')).to.equal(undefined);
});
Expand Down Expand Up @@ -255,10 +255,11 @@ describe('Schema Builder', () => {
it('Maintains specified directives', () => {
const schema = buildSchema('type Query');

expect(schema.getDirectives()).to.have.lengthOf(5);
expect(schema.getDirectives()).to.have.lengthOf(6);
expect(schema.getDirective('skip')).to.equal(GraphQLSkipDirective);
expect(schema.getDirective('include')).to.equal(GraphQLIncludeDirective);
expect(schema.getDirective('defer')).to.equal(GraphQLDeferDirective);
expect(schema.getDirective('stream')).to.equal(GraphQLStreamDirective);
expect(schema.getDirective('deprecated')).to.equal(
GraphQLDeprecatedDirective,
);
Expand All @@ -274,9 +275,10 @@ describe('Schema Builder', () => {
directive @deprecated on FIELD_DEFINITION
directive @specifiedBy on FIELD_DEFINITION
directive @defer on FRAGMENT_SPREAD
directive @stream on FIELD
`);

expect(schema.getDirectives()).to.have.lengthOf(5);
expect(schema.getDirectives()).to.have.lengthOf(6);
expect(schema.getDirective('skip')).to.not.equal(GraphQLSkipDirective);
expect(schema.getDirective('include')).to.not.equal(
GraphQLIncludeDirective,
Expand All @@ -288,17 +290,19 @@ describe('Schema Builder', () => {
GraphQLSpecifiedByDirective,
);
expect(schema.getDirective('defer')).to.not.equal(GraphQLDeferDirective);
expect(schema.getDirective('stream')).to.not.equal(GraphQLStreamDirective);
});

it('Adding directives maintains specified directives', () => {
const schema = buildSchema(`
directive @foo(arg: Int) on FIELD
`);

expect(schema.getDirectives()).to.have.lengthOf(6);
expect(schema.getDirectives()).to.have.lengthOf(7);
expect(schema.getDirective('skip')).to.not.equal(undefined);
expect(schema.getDirective('include')).to.not.equal(undefined);
expect(schema.getDirective('defer')).to.not.equal(undefined);
expect(schema.getDirective('stream')).to.not.equal(undefined);
expect(schema.getDirective('deprecated')).to.not.equal(undefined);
expect(schema.getDirective('specifiedBy')).to.not.equal(undefined);
});
Expand Down
1 change: 0 additions & 1 deletion src/utilities/__tests__/buildClientSchema-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ describe('Type System: build schema from introspection', () => {
const introspection = introspectionFromSchema(schema);
const clientSchema = buildClientSchema(introspection);

expect(clientSchema.getType('Int')).to.equal(undefined);
expect(clientSchema.getType('Float')).to.equal(undefined);
expect(clientSchema.getType('ID')).to.equal(undefined);
});
Expand Down
4 changes: 1 addition & 3 deletions src/utilities/__tests__/extendSchema-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,7 @@ describe('extendSchema', () => {
it('extends objects with standard type fields', () => {
const schema = buildSchema('type Query');

// String and Boolean are always included through introspection types
expect(schema.getType('Int')).to.equal(undefined);
// String, Boolean, and Int are always included through introspection types
expect(schema.getType('Float')).to.equal(undefined);
expect(schema.getType('String')).to.equal(GraphQLString);
expect(schema.getType('Boolean')).to.equal(GraphQLBoolean);
Expand All @@ -214,7 +213,6 @@ describe('extendSchema', () => {
const extendedSchema = extendSchema(schema, extendAST);

expect(validateSchema(extendedSchema)).to.deep.equal([]);
expect(extendedSchema.getType('Int')).to.equal(undefined);
expect(extendedSchema.getType('Float')).to.equal(undefined);
expect(extendedSchema.getType('String')).to.equal(GraphQLString);
expect(extendedSchema.getType('Boolean')).to.equal(GraphQLBoolean);
Expand Down
2 changes: 2 additions & 0 deletions src/utilities/__tests__/findBreakingChanges-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { GraphQLSchema } from '../../type/schema';
import {
GraphQLSkipDirective,
GraphQLDeferDirective,
GraphQLStreamDirective,
GraphQLIncludeDirective,
GraphQLSpecifiedByDirective,
GraphQLDeprecatedDirective,
Expand Down Expand Up @@ -804,6 +805,7 @@ describe('findBreakingChanges', () => {
GraphQLIncludeDirective,
GraphQLSpecifiedByDirective,
GraphQLDeferDirective,
GraphQLStreamDirective,
],
});

Expand Down
26 changes: 26 additions & 0 deletions src/utilities/__tests__/printSchema-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,20 @@ describe('Type System Printer', () => {
label: String
) on FRAGMENT_SPREAD | INLINE_FRAGMENT
"""
Directs the executor to stream plural fields when the \`if\` argument is true or undefined.
"""
directive @stream(
"""Stream when true or undefined."""
if: Boolean
"""Unique name"""
label: String
"""Number of items to return immediately"""
initialCount: Int!
) on FIELD
"""Marks an element of a GraphQL schema as no longer supported."""
directive @deprecated(
"""
Expand Down Expand Up @@ -872,6 +886,18 @@ describe('Type System Printer', () => {
label: String
) on FRAGMENT_SPREAD | INLINE_FRAGMENT
# Directs the executor to stream plural fields when the \`if\` argument is true or undefined.
directive @stream(
# Stream when true or undefined.
if: Boolean
# Unique name
label: String
# Number of items to return immediately
initialCount: Int!
) on FIELD
# Marks an element of a GraphQL schema as no longer supported.
directive @deprecated(
# Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted using the Markdown syntax, as specified by [CommonMark](https://commonmark.org/).
Expand Down
6 changes: 1 addition & 5 deletions src/validation/__tests__/KnownTypeNamesRule-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ describe('Validate: Known type names', () => {
it('references to standard scalars that are missing in schema', () => {
const schema = buildSchema('type Query { foo: String }');
const query = `
query ($id: ID, $float: Float, $int: Int) {
query ($id: ID, $float: Float) {
__typename
}
`;
Expand All @@ -94,10 +94,6 @@ describe('Validate: Known type names', () => {
message: 'Unknown type "Float".',
locations: [{ line: 2, column: 31 }],
},
{
message: 'Unknown type "Int".',
locations: [{ line: 2, column: 44 }],
},
]);
});

Expand Down

0 comments on commit 293a89f

Please sign in to comment.