Skip to content

Commit 637ee10

Browse files
committed
Merging #1173, fixes tests
1 parent f4047b7 commit 637ee10

11 files changed

+55
-39
lines changed

src/language/__tests__/schema-parser-test.js

-1
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,6 @@ type Hello {
712712
{
713713
kind: 'ScalarTypeDefinition',
714714
name: nameNode('Hello', { start: 7, end: 12 }),
715-
type: null,
716715
directives: [],
717716
loc: { start: 0, end: 12 },
718717
},

src/language/ast.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ export type ScalarTypeDefinitionNode = {
448448
+loc?: Location,
449449
+description?: StringValueNode,
450450
+name: NameNode,
451-
+type?: NamedTypeNode;
451+
+type?: NamedTypeNode,
452452
+directives?: $ReadOnlyArray<DirectiveNode>,
453453
};
454454

src/language/printer.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,12 @@ const printDocASTReducer = {
110110

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

113-
ScalarTypeDefinition: ({ description, name, directives }) =>
113+
ScalarTypeDefinition: ({ description, name, type, directives }) =>
114114
join(
115-
[description, join(['scalar', name, wrap(' as ', type), join(directives, ' ')], ' ')],
115+
[
116+
description,
117+
join(['scalar', name, wrap('as ', type), join(directives, ' ')], ' '),
118+
],
116119
'\n',
117120
),
118121

src/type/__tests__/introspection-test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1310,7 +1310,7 @@ describe('Introspection', () => {
13101310
description:
13111311
'Indicates this type is a scalar. ' +
13121312
'`ofType` may represent how this scalar is serialized.',
1313-
name: 'SCALAR'
1313+
name: 'SCALAR',
13141314
},
13151315
{
13161316
description:

src/type/definition.js

+5-14
Original file line numberDiff line numberDiff line change
@@ -461,18 +461,6 @@ export class GraphQLScalarType {
461461
this.astNode = config.astNode;
462462
this._scalarConfig = config;
463463
invariant(typeof config.name === 'string', 'Must provide name.');
464-
if (this.ofType) {
465-
const ofTypeName = this.ofType.name;
466-
invariant(
467-
ofTypeName === 'String' ||
468-
ofTypeName === 'Int' ||
469-
ofTypeName === 'Float' ||
470-
ofTypeName === 'Boolean' ||
471-
ofTypeName === 'ID',
472-
`${this.name} may only be described in terms of a built-in scalar ` +
473-
`type. However ${ofTypeName} is not a built-in scalar type.`
474-
);
475-
}
476464
invariant(
477465
typeof config.serialize === 'function',
478466
`${this.name} must provide "serialize" function. If this custom Scalar ` +
@@ -498,7 +486,8 @@ export class GraphQLScalarType {
498486

499487
// Parses an externally provided value to use as an input.
500488
parseValue(value: mixed): mixed {
501-
const parser = this._scalarConfig.parseValue || (this.ofType && this.ofType.parseValue);
489+
const parser =
490+
this._scalarConfig.parseValue || (this.ofType && this.ofType.parseValue);
502491
if (isInvalid(value)) {
503492
return undefined;
504493
}
@@ -507,7 +496,9 @@ export class GraphQLScalarType {
507496

508497
// Parses an externally provided literal value to use as an input.
509498
parseLiteral(valueNode: ValueNode, variables: ?ObjMap<mixed>): mixed {
510-
const parser = this._scalarConfig.parseLiteral || (this.ofType && this.ofType.parseLiteral);
499+
const parser =
500+
this._scalarConfig.parseLiteral ||
501+
(this.ofType && this.ofType.parseLiteral);
511502
return parser
512503
? parser(valueNode, variables)
513504
: valueFromASTUntyped(valueNode, variables);

src/type/introspection.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ export const __Type = new GraphQLObjectType({
207207
'The fundamental unit of any GraphQL Schema is the type. There are ' +
208208
'many kinds of types in GraphQL as represented by the `__TypeKind` enum.' +
209209
'\n\nDepending on the kind of a type, certain fields describe ' +
210-
'information about that type. Scalar types provide a name, description' +
210+
'information about that type. Scalar types provide a name, description ' +
211211
'and how they serialize, while Enum types provide their possible values. ' +
212212
'Object and Interface types provide the fields they describe. Abstract ' +
213213
'types, Union and Interface, provide the Object types possible ' +

src/type/validate.js

+21-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
*/
99

1010
import {
11+
isScalarType,
1112
isObjectType,
1213
isInterfaceType,
1314
isUnionType,
@@ -19,6 +20,7 @@ import {
1920
isOutputType,
2021
} from './definition';
2122
import type {
23+
GraphQLScalarType,
2224
GraphQLObjectType,
2325
GraphQLInterfaceType,
2426
GraphQLUnionType,
@@ -28,6 +30,7 @@ import type {
2830
import { isDirective } from './directives';
2931
import type { GraphQLDirective } from './directives';
3032
import { isIntrospectionType } from './introspection';
33+
import { isSpecifiedScalarType } from './scalars';
3134
import { isSchema } from './schema';
3235
import type { GraphQLSchema } from './schema';
3336
import find from '../jsutils/find';
@@ -239,7 +242,10 @@ function validateTypes(context: SchemaValidationContext): void {
239242
// Ensure they are named correctly.
240243
validateName(context, type);
241244

242-
if (isObjectType(type)) {
245+
if (isScalarType(type)) {
246+
// Ensure Scalars can serialize as expected.
247+
validateScalarSerialization(context, type);
248+
} else if (isObjectType(type)) {
243249
// Ensure fields are valid
244250
validateFields(context, type);
245251

@@ -261,6 +267,20 @@ function validateTypes(context: SchemaValidationContext): void {
261267
});
262268
}
263269

270+
function validateScalarSerialization(
271+
context: SchemaValidationContext,
272+
scalarType: GraphQLScalarType,
273+
): void {
274+
if (scalarType.ofType && !isSpecifiedScalarType(scalarType.ofType)) {
275+
context.reportError(
276+
`Scalar type ${scalarType.name} may only be described in terms of a ` +
277+
`spec-defined scalar type. However ${String(scalarType.ofType)} is ` +
278+
'not a built-in scalar type.',
279+
scalarType.astNode && scalarType.astNode.type,
280+
);
281+
}
282+
}
283+
264284
function validateFields(
265285
context: SchemaValidationContext,
266286
type: GraphQLObjectType | GraphQLInterfaceType,

src/utilities/__tests__/schemaPrinter-test.js

+10-8
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ describe('Type System Printer', () => {
503503
ofType: GraphQLInt,
504504
serialize(value) {
505505
return value % 2 === 1 ? value : null;
506-
}
506+
},
507507
});
508508

509509
const OddType = new GraphQLScalarType({
@@ -793,10 +793,10 @@ describe('Type System Printer', () => {
793793
types in GraphQL as represented by the \`__TypeKind\` enum.
794794
795795
Depending on the kind of a type, certain fields describe information about that
796-
type. Scalar types provide no information beyond a name and description, while
797-
Enum types provide their values. Object and Interface types provide the fields
798-
they describe. Abstract types, Union and Interface, provide the Object types
799-
possible at runtime. List and NonNull types compose other types.
796+
type. Scalar types provide a name, description and how they serialize, while
797+
Enum types provide their possible values. Object and Interface types provide the
798+
fields they describe. Abstract types, Union and Interface, provide the Object
799+
types possible at runtime. List and NonNull types compose other types.
800800
"""
801801
type __Type {
802802
kind: __TypeKind!
@@ -812,7 +812,9 @@ describe('Type System Printer', () => {
812812
813813
"""An enum describing what kind of type a given \`__Type\` is."""
814814
enum __TypeKind {
815-
"""Indicates this type is a scalar."""
815+
"""
816+
Indicates this type is a scalar. \`ofType\` may represent how this scalar is serialized.
817+
"""
816818
SCALAR
817819
818820
"""
@@ -1013,8 +1015,8 @@ describe('Type System Printer', () => {
10131015
# types in GraphQL as represented by the \`__TypeKind\` enum.
10141016
#
10151017
# Depending on the kind of a type, certain fields describe information about that
1016-
# type. Scalar types provide a name, descriptionand how they serialize, while Enum
1017-
# types provide their possible values. Object and Interface types provide the
1018+
# type. Scalar types provide a name, description and how they serialize, while
1019+
# Enum types provide their possible values. Object and Interface types provide the
10181020
# fields they describe. Abstract types, Union and Interface, provide the Object
10191021
# types possible at runtime. List and NonNull types compose other types.
10201022
type __Type {

src/utilities/buildASTSchema.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,10 @@ export class ASTDefinitionBuilder {
442442
return new GraphQLScalarType({
443443
name: def.name.value,
444444
description: getDescription(def, this._options),
445-
ofType: def.type && this.buildType(def.type),
445+
// Note: While this could make assertions to get the correctly typed
446+
// values below, that would throw immediately while type system
447+
// validation with validateSchema() will produce more actionable results.
448+
ofType: def.type && (this.buildType(def.type): any),
446449
astNode: def,
447450
serialize: value => value,
448451
});

src/utilities/buildClientSchema.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,9 @@ export function buildClientSchema(
208208
function buildScalarDef(
209209
scalarIntrospection: IntrospectionScalarType,
210210
): GraphQLScalarType {
211-
const ofType = scalarIntrospection.ofType ?
212-
getType(scalarIntrospection.ofType) :
213-
undefined;
211+
const ofType = scalarIntrospection.ofType
212+
? (getType(scalarIntrospection.ofType): any)
213+
: undefined;
214214
return new GraphQLScalarType({
215215
name: scalarIntrospection.name,
216216
description: scalarIntrospection.description,

src/utilities/findBreakingChanges.js

+4-6
Original file line numberDiff line numberDiff line change
@@ -161,18 +161,16 @@ export function findTypesThatChangedKind(
161161
`${typeName} changed from ` +
162162
`${typeKindName(oldType)} to ${typeKindName(newType)}.`,
163163
});
164-
} else if (
165-
oldType instanceof GraphQLScalarType &&
166-
newType instanceof GraphQLScalarType
167-
) {
164+
} else if (isScalarType(oldType) && isScalarType(newType)) {
168165
const oldOfType = oldType.ofType;
169166
const newOfType = newType.ofType;
170167
if (oldOfType && newOfType && oldOfType !== newOfType) {
171168
breakingChanges.push({
172169
type: BreakingChangeType.TYPE_CHANGED_KIND,
173-
description: `${typeName} changed from ` +
170+
description:
171+
`${typeName} changed from ` +
174172
`${typeKindName(oldType)} serialized as ${oldOfType.name} ` +
175-
`to ${typeKindName(newType)} serialized as ${newOfType.name}.`
173+
`to ${typeKindName(newType)} serialized as ${newOfType.name}.`,
176174
});
177175
}
178176
}

0 commit comments

Comments
 (0)