8
8
*/
9
9
10
10
import inspect from '../jsutils/inspect' ;
11
+ import isFinite from '../jsutils/isFinite' ;
11
12
import isInteger from '../jsutils/isInteger' ;
12
13
import { GraphQLScalarType , isNamedType } from './definition' ;
13
14
import { Kind } from '../language/kinds' ;
@@ -20,38 +21,46 @@ import { Kind } from '../language/kinds';
20
21
const MAX_INT = 2147483647 ;
21
22
const MIN_INT = - 2147483648 ;
22
23
23
- function coerceInt ( value : mixed ) : number {
24
+ function serializeInt ( value : mixed ) : number {
24
25
if ( Array . isArray ( value ) ) {
25
26
throw new TypeError (
26
- `Int cannot represent an array value: [ ${ String ( value ) } ] ` ,
27
+ `Int cannot represent an array value: ${ inspect ( value ) } ` ,
27
28
) ;
28
29
}
29
- if ( value === '' ) {
30
+ const num = Number ( value ) ;
31
+ if ( value === '' || ! isInteger ( num ) ) {
30
32
throw new TypeError (
31
- ' Int cannot represent non-integer value: (empty string)' ,
33
+ ` Int cannot represent non-integer value: ${ inspect ( value ) } ` ,
32
34
) ;
33
35
}
34
- const num = Number ( value ) ;
35
- if ( ! isInteger ( num ) ) {
36
+ if ( num > MAX_INT || num < MIN_INT ) {
36
37
throw new TypeError (
37
- ' Int cannot represent non- integer value: ' + inspect ( value ) ,
38
+ ` Int cannot represent non 32-bit signed integer value: ${ inspect ( value ) } ` ,
38
39
) ;
39
40
}
41
+ return num ;
42
+ }
40
43
41
- if ( num > MAX_INT || num < MIN_INT ) {
44
+ function coerceInt ( value : mixed ) : number {
45
+ if ( ! isInteger ( value ) ) {
42
46
throw new TypeError (
43
- ' Int cannot represent non 32-bit signed integer value: ' + inspect ( value ) ,
47
+ ` Int cannot represent non- integer value: ${ inspect ( value ) } ` ,
44
48
) ;
45
49
}
46
- return num ;
50
+ if ( value > MAX_INT || value < MIN_INT ) {
51
+ throw new TypeError (
52
+ `Int cannot represent non 32-bit signed integer value: ${ inspect ( value ) } ` ,
53
+ ) ;
54
+ }
55
+ return value ;
47
56
}
48
57
49
58
export const GraphQLInt = new GraphQLScalarType ( {
50
59
name : 'Int' ,
51
60
description :
52
61
'The `Int` scalar type represents non-fractional signed whole numeric ' +
53
62
'values. Int can represent values between -(2^31) and 2^31 - 1. ' ,
54
- serialize : coerceInt ,
63
+ serialize : serializeInt ,
55
64
parseValue : coerceInt ,
56
65
parseLiteral ( ast ) {
57
66
if ( ast . kind === Kind . INT ) {
@@ -64,24 +73,28 @@ export const GraphQLInt = new GraphQLScalarType({
64
73
} ,
65
74
} ) ;
66
75
67
- function coerceFloat ( value : mixed ) : number {
76
+ function serializeFloat ( value : mixed ) : number {
68
77
if ( Array . isArray ( value ) ) {
69
78
throw new TypeError (
70
- `Float cannot represent an array value: [ ${ String ( value ) } ] ` ,
79
+ `Float cannot represent an array value: ${ inspect ( value ) } ` ,
71
80
) ;
72
81
}
73
- if ( value === '' ) {
82
+ const num = Number ( value ) ;
83
+ if ( value === '' || ! isFinite ( num ) ) {
74
84
throw new TypeError (
75
- ' Float cannot represent non numeric value: (empty string)' ,
85
+ ` Float cannot represent non numeric value: ${ inspect ( value ) } ` ,
76
86
) ;
77
87
}
78
- const num = Number ( value ) ;
79
- if ( isFinite ( num ) ) {
80
- return num ;
88
+ return num ;
89
+ }
90
+
91
+ function coerceFloat ( value : mixed ) : number {
92
+ if ( ! isFinite ( value ) ) {
93
+ throw new TypeError (
94
+ `Float cannot represent non numeric value: ${ inspect ( value ) } ` ,
95
+ ) ;
81
96
}
82
- throw new TypeError (
83
- 'Float cannot represent non numeric value: ' + inspect ( value ) ,
84
- ) ;
97
+ return value ;
85
98
}
86
99
87
100
export const GraphQLFloat = new GraphQLScalarType ( {
@@ -90,7 +103,7 @@ export const GraphQLFloat = new GraphQLScalarType({
90
103
'The `Float` scalar type represents signed double-precision fractional ' +
91
104
'values as specified by ' +
92
105
'[IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). ' ,
93
- serialize : coerceFloat ,
106
+ serialize : serializeFloat ,
94
107
parseValue : coerceFloat ,
95
108
parseLiteral ( ast ) {
96
109
return ast . kind === Kind . FLOAT || ast . kind === Kind . INT
@@ -99,7 +112,7 @@ export const GraphQLFloat = new GraphQLScalarType({
99
112
} ,
100
113
} ) ;
101
114
102
- function coerceString ( value : mixed ) : string {
115
+ function serializeString ( value : mixed ) : string {
103
116
if ( Array . isArray ( value ) ) {
104
117
throw new TypeError (
105
118
`String cannot represent an array value: ${ inspect ( value ) } ` ,
@@ -108,38 +121,81 @@ function coerceString(value: mixed): string {
108
121
return String ( value ) ;
109
122
}
110
123
124
+ function coerceString ( value : mixed ) : string {
125
+ if ( typeof value !== 'string' ) {
126
+ throw new TypeError (
127
+ `String cannot represent a non string value: ${ inspect ( value ) } ` ,
128
+ ) ;
129
+ }
130
+ return value ;
131
+ }
132
+
111
133
export const GraphQLString = new GraphQLScalarType ( {
112
134
name : 'String' ,
113
135
description :
114
136
'The `String` scalar type represents textual data, represented as UTF-8 ' +
115
137
'character sequences. The String type is most often used by GraphQL to ' +
116
138
'represent free-form human-readable text.' ,
117
- serialize : coerceString ,
139
+ serialize : serializeString ,
118
140
parseValue : coerceString ,
119
141
parseLiteral ( ast ) {
120
142
return ast . kind === Kind . STRING ? ast . value : undefined ;
121
143
} ,
122
144
} ) ;
123
145
124
- function coerceBoolean ( value : mixed ) : boolean {
146
+ function serializeBoolean ( value : mixed ) : boolean {
125
147
if ( Array . isArray ( value ) ) {
126
148
throw new TypeError (
127
- `Boolean cannot represent an array value: [ ${ String ( value ) } ] ` ,
149
+ `Boolean cannot represent an array value: ${ inspect ( value ) } ` ,
128
150
) ;
129
151
}
130
152
return Boolean ( value ) ;
131
153
}
132
154
155
+ function coerceBoolean ( value : mixed ) : boolean {
156
+ if ( typeof value !== 'boolean' ) {
157
+ throw new TypeError (
158
+ `Boolean cannot represent a non boolean value: ${ inspect ( value ) } ` ,
159
+ ) ;
160
+ }
161
+ return value ;
162
+ }
163
+
133
164
export const GraphQLBoolean = new GraphQLScalarType ( {
134
165
name : 'Boolean' ,
135
166
description : 'The `Boolean` scalar type represents `true` or `false`.' ,
136
- serialize : coerceBoolean ,
167
+ serialize : serializeBoolean ,
137
168
parseValue : coerceBoolean ,
138
169
parseLiteral ( ast ) {
139
170
return ast . kind === Kind . BOOLEAN ? ast . value : undefined ;
140
171
} ,
141
172
} ) ;
142
173
174
+ function serializeID ( value : mixed ) : string {
175
+ // Support serializing objects with custom valueOf() functions - a common way
176
+ // to represent an object identifier.
177
+ const result = value && value . valueOf !== Object . prototype . valueOf
178
+ ? value . valueOf ( )
179
+ : value ;
180
+ if (
181
+ typeof result !== 'string' &&
182
+ ( typeof result !== 'number' || ! isInteger ( result ) )
183
+ ) {
184
+ throw new TypeError ( `ID cannot represent value: ${ inspect ( value ) } ` ) ;
185
+ }
186
+ return String ( result ) ;
187
+ }
188
+
189
+ function coerceID ( value : mixed ) : string {
190
+ if (
191
+ typeof value !== 'string' &&
192
+ ( typeof value !== 'number' || ! isInteger ( value ) )
193
+ ) {
194
+ throw new TypeError ( `ID cannot represent value: ${ inspect ( value ) } ` ) ;
195
+ }
196
+ return String ( value ) ;
197
+ }
198
+
143
199
export const GraphQLID = new GraphQLScalarType ( {
144
200
name : 'ID' ,
145
201
description :
@@ -148,8 +204,8 @@ export const GraphQLID = new GraphQLScalarType({
148
204
'response as a String; however, it is not intended to be human-readable. ' +
149
205
'When expected as an input type, any string (such as `"4"`) or integer ' +
150
206
'(such as `4`) input value will be accepted as an ID.' ,
151
- serialize : coerceString ,
152
- parseValue : coerceString ,
207
+ serialize : serializeID ,
208
+ parseValue : coerceID ,
153
209
parseLiteral ( ast ) {
154
210
return ast . kind === Kind . STRING || ast . kind === Kind . INT
155
211
? ast . value
0 commit comments