Skip to content

Commit 2e9ca2e

Browse files
committed
Add @specified directive
This in an implementation for a spec proposal: * Spec proposal: [[RFC] Custom Scalar Specification URIs](graphql/graphql-spec#649) * Original issue: [[RFC] Custom Scalar Specification URIs](graphql/graphql-spec#635) Please let me know if I forgot something.
1 parent 61a07b1 commit 2e9ca2e

7 files changed

+83
-6
lines changed

src/type/__tests__/introspection-test.js

+19
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,25 @@ describe('Introspection', () => {
847847
},
848848
],
849849
},
850+
{
851+
name: 'specified',
852+
locations: ['FIELD_DEFINITION'],
853+
args: [
854+
{
855+
defaultValue: null,
856+
name: 'by',
857+
type: {
858+
kind: 'NON_NULL',
859+
name: null,
860+
ofType: {
861+
kind: 'SCALAR',
862+
name: 'String',
863+
ofType: null,
864+
},
865+
},
866+
},
867+
],
868+
},
850869
{
851870
name: 'deprecated',
852871
locations: ['FIELD_DEFINITION', 'ENUM_VALUE'],

src/type/directives.d.ts

+6
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ export const GraphQLIncludeDirective: GraphQLDirective;
5454
*/
5555
export const GraphQLSkipDirective: GraphQLDirective;
5656

57+
/**
58+
* Used to provide an RFC3986-compliant URI for specifying the behaviour of
59+
* custom scalar definitions.
60+
*/
61+
export const GraphQLSpecifiedDirective: GraphQLDirective;
62+
5763
/**
5864
* Constant string used for default reason for a deprecation.
5965
*/

src/type/directives.js

+19
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,24 @@ export const GraphQLSkipDirective = new GraphQLDirective({
167167
},
168168
});
169169

170+
/**
171+
* Used to provide an RFC3986-compliant URI for specifying the behaviour of
172+
* custom scalar definitions.
173+
*/
174+
export const GraphQLSpecifiedDirective = new GraphQLDirective({
175+
name: 'specified',
176+
description:
177+
'Exposes a RFC3986-compliant URI that specifies the behaviour of this scalar.',
178+
locations: [DirectiveLocation.FIELD_DEFINITION],
179+
args: {
180+
by: {
181+
type: GraphQLNonNull(GraphQLString),
182+
description:
183+
'The RFC3986-compliant URI that specifies the behaviour of this scalar.',
184+
},
185+
},
186+
});
187+
170188
/**
171189
* Constant string used for default reason for a deprecation.
172190
*/
@@ -195,6 +213,7 @@ export const GraphQLDeprecatedDirective = new GraphQLDirective({
195213
export const specifiedDirectives = Object.freeze([
196214
GraphQLIncludeDirective,
197215
GraphQLSkipDirective,
216+
GraphQLSpecifiedDirective,
198217
GraphQLDeprecatedDirective,
199218
]);
200219

src/utilities/__tests__/buildASTSchema-test.js

+14-5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
assertDirective,
1616
GraphQLSkipDirective,
1717
GraphQLIncludeDirective,
18+
GraphQLSpecifiedDirective,
1819
GraphQLDeprecatedDirective,
1920
} from '../../type/directives';
2021
import {
@@ -182,12 +183,15 @@ describe('Schema Builder', () => {
182183
expect(cycleSDL(sdl, { commentDescriptions: true })).to.equal(sdl);
183184
});
184185

185-
it('Maintains @skip & @include', () => {
186+
it('Maintains @include, @skip & @specified', () => {
186187
const schema = buildSchema('type Query');
187188

188-
expect(schema.getDirectives()).to.have.lengthOf(3);
189+
expect(schema.getDirectives()).to.have.lengthOf(4);
189190
expect(schema.getDirective('skip')).to.equal(GraphQLSkipDirective);
190191
expect(schema.getDirective('include')).to.equal(GraphQLIncludeDirective);
192+
expect(schema.getDirective('specified')).to.equal(
193+
GraphQLSpecifiedDirective,
194+
);
191195
expect(schema.getDirective('deprecated')).to.equal(
192196
GraphQLDeprecatedDirective,
193197
);
@@ -197,27 +201,32 @@ describe('Schema Builder', () => {
197201
const schema = buildSchema(`
198202
directive @skip on FIELD
199203
directive @include on FIELD
204+
directive @specified on FIELD_DEFINITION
200205
directive @deprecated on FIELD_DEFINITION
201206
`);
202207

203-
expect(schema.getDirectives()).to.have.lengthOf(3);
208+
expect(schema.getDirectives()).to.have.lengthOf(4);
204209
expect(schema.getDirective('skip')).to.not.equal(GraphQLSkipDirective);
205210
expect(schema.getDirective('include')).to.not.equal(
206211
GraphQLIncludeDirective,
207212
);
213+
expect(schema.getDirective('specified')).to.not.equal(
214+
GraphQLSpecifiedDirective,
215+
);
208216
expect(schema.getDirective('deprecated')).to.not.equal(
209217
GraphQLDeprecatedDirective,
210218
);
211219
});
212220

213-
it('Adding directives maintains @skip & @include', () => {
221+
it('Adding directives maintains @include, @skip & @specified', () => {
214222
const schema = buildSchema(`
215223
directive @foo(arg: Int) on FIELD
216224
`);
217225

218-
expect(schema.getDirectives()).to.have.lengthOf(4);
226+
expect(schema.getDirectives()).to.have.lengthOf(5);
219227
expect(schema.getDirective('skip')).to.not.equal(undefined);
220228
expect(schema.getDirective('include')).to.not.equal(undefined);
229+
expect(schema.getDirective('specified')).to.not.equal(undefined);
221230
expect(schema.getDirective('deprecated')).to.not.equal(undefined);
222231
});
223232

src/utilities/__tests__/findBreakingChanges-test.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { GraphQLSchema } from '../../type/schema';
77
import {
88
GraphQLSkipDirective,
99
GraphQLIncludeDirective,
10+
GraphQLSpecifiedDirective,
1011
GraphQLDeprecatedDirective,
1112
} from '../../type/directives';
1213

@@ -790,7 +791,11 @@ describe('findBreakingChanges', () => {
790791
const oldSchema = new GraphQLSchema({});
791792

792793
const newSchema = new GraphQLSchema({
793-
directives: [GraphQLSkipDirective, GraphQLIncludeDirective],
794+
directives: [
795+
GraphQLSkipDirective,
796+
GraphQLIncludeDirective,
797+
GraphQLSpecifiedDirective,
798+
],
794799
});
795800

796801
expect(findBreakingChanges(oldSchema, newSchema)).to.deep.equal([

src/utilities/__tests__/schemaPrinter-test.js

+14
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,14 @@ describe('Type System Printer', () => {
590590
if: Boolean!
591591
) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
592592
593+
"""
594+
Exposes a RFC3986-compliant URI that specifies the behaviour of this scalar.
595+
"""
596+
directive @specified(
597+
"""The RFC3986-compliant URI that specifies the behaviour of this scalar."""
598+
by: String!
599+
) on FIELD_DEFINITION
600+
593601
"""Marks an element of a GraphQL schema as no longer supported."""
594602
directive @deprecated(
595603
"""
@@ -803,6 +811,12 @@ describe('Type System Printer', () => {
803811
if: Boolean!
804812
) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
805813
814+
# Exposes a RFC3986-compliant URI that specifies the behaviour of this scalar.
815+
directive @specified(
816+
# The RFC3986-compliant URI that specifies the behaviour of this scalar.
817+
by: String!
818+
) on FIELD_DEFINITION
819+
806820
# Marks an element of a GraphQL schema as no longer supported.
807821
directive @deprecated(
808822
# 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/).

src/utilities/buildASTSchema.js

+5
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ import {
5555
GraphQLSkipDirective,
5656
GraphQLIncludeDirective,
5757
GraphQLDeprecatedDirective,
58+
GraphQLSpecifiedDirective,
5859
} from '../type/directives';
5960
import {
6061
type GraphQLType,
@@ -170,6 +171,10 @@ export function buildASTSchema(
170171
directives.push(GraphQLIncludeDirective);
171172
}
172173

174+
if (!directives.some(directive => directive.name === 'specified')) {
175+
directives.push(GraphQLSpecifiedDirective);
176+
}
177+
173178
if (!directives.some(directive => directive.name === 'deprecated')) {
174179
directives.push(GraphQLDeprecatedDirective);
175180
}

0 commit comments

Comments
 (0)