@@ -187,6 +187,17 @@ export function getNamedType(type: ?GraphQLType): ?GraphQLNamedType {
187
187
}
188
188
189
189
190
+ /**
191
+ * Used while defining GraphQL types to allow for circular references in
192
+ * otherwise immutable type definitions.
193
+ */
194
+ export type Thunk < T > = ( ( ) => T ) | T ;
195
+
196
+ function resolveThunk < T > (thunk: Thunk< T > ): T {
197
+ return typeof thunk === 'function' ? thunk ( ) : thunk ;
198
+ }
199
+
200
+
190
201
/**
191
202
* Scalar Type Definition
192
203
*
@@ -204,13 +215,13 @@ export function getNamedType(type: ?GraphQLType): ?GraphQLNamedType {
204
215
* } ) ;
205
216
*
206
217
* /
207
- export class GraphQLScalarType < InternalType > {
218
+ export class GraphQLScalarType < TInternal , TExternal > {
208
219
name : string ;
209
220
description : ?string ;
210
221
211
- _scalarConfig : GraphQLScalarTypeConfig < InternalType > ;
222
+ _scalarConfig : GraphQLScalarTypeConfig < TInternal , TExternal > ;
212
223
213
- constructor ( config : GraphQLScalarTypeConfig < InternalType > ) {
224
+ constructor ( config : GraphQLScalarTypeConfig < TInternal , TExternal > ) {
214
225
invariant ( config . name , 'Type must be named.' ) ;
215
226
assertValidName ( config . name ) ;
216
227
this . name = config . name ;
@@ -232,17 +243,17 @@ export class GraphQLScalarType<InternalType> {
232
243
this . _scalarConfig = config ;
233
244
}
234
245
235
- serialize ( value : InternalType ) : mixed {
246
+ serialize ( value : TInternal ) : ? TExternal {
236
247
const serializer = this . _scalarConfig . serialize ;
237
248
return serializer ( value ) ;
238
249
}
239
250
240
- parseValue ( value : mixed ) : ?InternalType {
251
+ parseValue ( value : TExternal ) : ?TInternal {
241
252
const parser = this . _scalarConfig . parseValue ;
242
253
return parser ? parser ( value ) : null ;
243
254
}
244
255
245
- parseLiteral ( valueAST : Value ) : ?InternalType {
256
+ parseLiteral ( valueAST : Value ) : ?TInternal {
246
257
const parser = this . _scalarConfig . parseLiteral ;
247
258
return parser ? parser ( valueAST ) : null ;
248
259
}
@@ -252,12 +263,12 @@ export class GraphQLScalarType<InternalType> {
252
263
}
253
264
}
254
265
255
- export type GraphQLScalarTypeConfig < InternalType > = {
266
+ export type GraphQLScalarTypeConfig < TInternal , TExternal > = {
256
267
name : string ;
257
268
description ?: ?string ;
258
- serialize : ( value : mixed ) => ?InternalType ;
259
- parseValue ?: ( value : mixed ) => ?InternalType ;
260
- parseLiteral ?: ( valueAST : Value ) => ?InternalType ;
269
+ serialize : ( value : TInternal ) => ?TExternal ;
270
+ parseValue ?: ( value : TExternal ) => ?TInternal ;
271
+ parseLiteral ?: ( valueAST : Value ) => ?TInternal ;
261
272
}
262
273
263
274
@@ -304,11 +315,11 @@ export class GraphQLObjectType {
304
315
description : ?string ;
305
316
isTypeOf : ?GraphQLIsTypeOfFn ;
306
317
307
- _typeConfig : GraphQLObjectTypeConfig ;
318
+ _typeConfig : GraphQLObjectTypeConfig < * > ;
308
319
_fields : GraphQLFieldDefinitionMap ;
309
320
_interfaces : Array < GraphQLInterfaceType > ;
310
321
311
- constructor ( config : GraphQLObjectTypeConfig ) {
322
+ constructor ( config : GraphQLObjectTypeConfig < * > ) {
312
323
invariant ( config . name , 'Type must be named . ') ;
313
324
assertValidName ( config . name ) ;
314
325
this . name = config . name ;
@@ -340,15 +351,11 @@ export class GraphQLObjectType {
340
351
}
341
352
}
342
353
343
- function resolveMaybeThunk < T > ( thingOrThunk : T | ( ) => T ) : T {
344
- return typeof thingOrThunk === 'function ' ? thingOrThunk ( ) : thingOrThunk ;
345
- }
346
-
347
354
function defineInterfaces (
348
355
type : GraphQLObjectType ,
349
- interfacesOrThunk : Array < GraphQLInterfaceType > | ? GraphQLInterfacesThunk
356
+ interfacesThunk : Thunk < ? Array < GraphQLInterfaceType >>
350
357
) : Array < GraphQLInterfaceType > {
351
- const interfaces = resolveMaybeThunk ( interfacesOrThunk ) ;
358
+ const interfaces = resolveThunk ( interfacesThunk ) ;
352
359
if ( ! interfaces ) {
353
360
return [ ] ;
354
361
}
@@ -378,9 +385,9 @@ function defineInterfaces(
378
385
379
386
function defineFieldMap (
380
387
type : GraphQLNamedType ,
381
- fields : GraphQLFieldConfigMap | GraphQLFieldConfigMapThunk
388
+ fieldsThunk : Thunk < GraphQLFieldConfigMap < * >>
382
389
) : GraphQLFieldDefinitionMap {
383
- const fieldMap : any = resolveMaybeThunk ( fields ) ;
390
+ const fieldMap = resolveThunk ( fieldsThunk ) ;
384
391
invariant (
385
392
isPlainObj ( fieldMap ) ,
386
393
`${type . name } fields must be an object with field names as keys or a ` +
@@ -397,8 +404,9 @@ function defineFieldMap(
397
404
const resultFieldMap = { } ;
398
405
fieldNames . forEach ( fieldName => {
399
406
assertValidName ( fieldName ) ;
407
+ const fieldConfig = fieldMap [ fieldName ] ;
400
408
const field = {
401
- ...fieldMap [ fieldName ] ,
409
+ ...fieldConfig ,
402
410
name : fieldName
403
411
} ;
404
412
invariant (
@@ -411,17 +419,18 @@ function defineFieldMap(
411
419
`${type . name } . ${fieldName } field type must be Output Type but ` +
412
420
`got : ${String ( field . type ) } . `
413
421
) ;
414
- if ( ! field . args ) {
422
+ const argsConfig = fieldConfig . args ;
423
+ if ( ! argsConfig ) {
415
424
field . args = [ ] ;
416
425
} else {
417
426
invariant (
418
- isPlainObj ( field . args ) ,
427
+ isPlainObj ( argsConfig ) ,
419
428
`${type . name } . ${fieldName } args must be an object with argument ` +
420
429
'names as keys . '
421
430
) ;
422
- field . args = Object . keys ( field . args ) . map ( argName => {
431
+ field . args = Object . keys ( argsConfig ) . map ( argName => {
423
432
assertValidName ( argName ) ;
424
- const arg = field . args [ argName ] ;
433
+ const arg = argsConfig [ argName ] ;
425
434
invariant (
426
435
isInputType ( arg . type ) ,
427
436
`${type . name } . ${fieldName } ( ${argName } :) argument type must be ` +
@@ -444,32 +453,28 @@ function isPlainObj(obj) {
444
453
return obj && typeof obj === 'object ' && ! Array . isArray ( obj ) ;
445
454
}
446
455
447
- export type GraphQLObjectTypeConfig = {
456
+ export type GraphQLObjectTypeConfig < TSource > = {
448
457
name : string ;
449
- interfaces ?: GraphQLInterfacesThunk | Array < GraphQLInterfaceType > ;
450
- fields : GraphQLFieldConfigMapThunk | GraphQLFieldConfigMap ;
451
- isTypeOf ?: GraphQLIsTypeOfFn ;
458
+ interfaces ?: Thunk < ? Array < GraphQLInterfaceType > >;
459
+ fields : Thunk < GraphQLFieldConfigMap < TSource >> ;
460
+ isTypeOf ?: ? GraphQLIsTypeOfFn ;
452
461
description ?: ?string
453
462
}
454
463
455
- type GraphQLInterfacesThunk = ( ) => Array < GraphQLInterfaceType > ;
456
-
457
- type GraphQLFieldConfigMapThunk = ( ) => GraphQLFieldConfigMap ;
458
-
459
464
export type GraphQLTypeResolveFn = (
460
465
value : mixed ,
461
466
context : mixed ,
462
467
info : GraphQLResolveInfo
463
468
) => ?GraphQLObjectType
464
469
465
470
export type GraphQLIsTypeOfFn = (
466
- value : mixed ,
471
+ source : mixed ,
467
472
context : mixed ,
468
473
info : GraphQLResolveInfo
469
474
) => boolean
470
475
471
- export type GraphQLFieldResolveFn = (
472
- source : mixed ,
476
+ export type GraphQLFieldResolveFn < TSource > = (
477
+ source : TSource ,
473
478
args : { [ argName : string ] : mixed } ,
474
479
context : mixed ,
475
480
info : GraphQLResolveInfo
@@ -488,10 +493,10 @@ export type GraphQLResolveInfo = {
488
493
variableValues : { [ variableName : string ] : mixed } ;
489
494
}
490
495
491
- export type GraphQLFieldConfig = {
496
+ export type GraphQLFieldConfig < TSource > = {
492
497
type : GraphQLOutputType ;
493
498
args ?: GraphQLFieldConfigArgumentMap ;
494
- resolve ?: GraphQLFieldResolveFn ;
499
+ resolve ?: GraphQLFieldResolveFn < TSource > ;
495
500
deprecationReason ?: ?string ;
496
501
description ?: ?string ;
497
502
}
@@ -506,16 +511,16 @@ export type GraphQLArgumentConfig = {
506
511
description ?: ?string ;
507
512
}
508
513
509
- export type GraphQLFieldConfigMap = {
510
- [ fieldName : string ] : GraphQLFieldConfig ;
514
+ export type GraphQLFieldConfigMap < TSource > = {
515
+ [ fieldName : string ] : GraphQLFieldConfig < TSource > ;
511
516
} ;
512
517
513
518
export type GraphQLFieldDefinition = {
514
519
name : string ;
515
520
description : ?string ;
516
521
type : GraphQLOutputType ;
517
522
args : Array < GraphQLArgument > ;
518
- resolve ?: GraphQLFieldResolveFn ;
523
+ resolve ?: GraphQLFieldResolveFn < * > ;
519
524
deprecationReason ?: ?string ;
520
525
}
521
526
@@ -585,13 +590,13 @@ export class GraphQLInterfaceType {
585
590
586
591
export type GraphQLInterfaceTypeConfig = {
587
592
name : string ,
588
- fields : GraphQLFieldConfigMapThunk | GraphQLFieldConfigMap ,
593
+ fields : Thunk < GraphQLFieldConfigMap < mixed >> ,
589
594
/**
590
595
* Optionally provide a custom type resolver function. If one is not provided,
591
596
* the default implementation will call `isTypeOf` on each implementing
592
597
* Object type.
593
598
*/
594
- resolveType ?: GraphQLTypeResolveFn ,
599
+ resolveType ?: ? GraphQLTypeResolveFn ,
595
600
description ?: ?string
596
601
} ;
597
602
@@ -880,7 +885,7 @@ export class GraphQLInputObjectType {
880
885
}
881
886
882
887
_defineFieldMap ( ) : InputObjectFieldMap {
883
- const fieldMap : any = resolveMaybeThunk ( this . _typeConfig . fields ) ;
888
+ const fieldMap : any = resolveThunk ( this . _typeConfig . fields ) ;
884
889
invariant (
885
890
isPlainObj ( fieldMap ) ,
886
891
`${this . name } fields must be an object with field names as keys or a ` +
@@ -916,12 +921,10 @@ export class GraphQLInputObjectType {
916
921
917
922
export type InputObjectConfig = {
918
923
name : string ;
919
- fields : InputObjectConfigFieldMapThunk | InputObjectConfigFieldMap ;
924
+ fields : Thunk < InputObjectConfigFieldMap > ;
920
925
description ?: ?string ;
921
926
}
922
927
923
- export type InputObjectConfigFieldMapThunk = ( ) => InputObjectConfigFieldMap ;
924
-
925
928
export type InputObjectFieldConfig = {
926
929
type : GraphQLInputType ;
927
930
defaultValue ?: mixed ;
0 commit comments