@@ -193,13 +193,12 @@ func GetNamed(ttype Type) Named {
193193//
194194// Example:
195195//
196- // var OddType = new Scalar({
197- // name: 'Odd',
198- // serialize(value) {
199- // return value % 2 === 1 ? value : null;
200- // }
201- // });
202- //
196+ // var OddType = new Scalar({
197+ // name: 'Odd',
198+ // serialize(value) {
199+ // return value % 2 === 1 ? value : null;
200+ // }
201+ // });
203202type Scalar struct {
204203 PrivateName string `json:"name"`
205204 PrivateDescription string `json:"description"`
@@ -306,33 +305,33 @@ func (st *Scalar) Error() error {
306305// have a name, but most importantly describe their fields.
307306// Example:
308307//
309- // var AddressType = new Object({
310- // name: 'Address',
311- // fields: {
312- // street: { type: String },
313- // number: { type: Int },
314- // formatted: {
315- // type: String,
316- // resolve(obj) {
317- // return obj.number + ' ' + obj.street
318- // }
319- // }
320- // }
321- // });
308+ // var AddressType = new Object({
309+ // name: 'Address',
310+ // fields: {
311+ // street: { type: String },
312+ // number: { type: Int },
313+ // formatted: {
314+ // type: String,
315+ // resolve(obj) {
316+ // return obj.number + ' ' + obj.street
317+ // }
318+ // }
319+ // }
320+ // });
322321//
323322// When two types need to refer to each other, or a type needs to refer to
324323// itself in a field, you can use a function expression (aka a closure or a
325324// thunk) to supply the fields lazily.
326325//
327326// Example:
328327//
329- // var PersonType = new Object({
330- // name: 'Person',
331- // fields: () => ({
332- // name: { type: String },
333- // bestFriend: { type: PersonType },
334- // })
335- // });
328+ // var PersonType = new Object({
329+ // name: 'Person',
330+ // fields: () => ({
331+ // name: { type: String },
332+ // bestFriend: { type: PersonType },
333+ // })
334+ // });
336335//
337336// /
338337type Object struct {
@@ -419,7 +418,7 @@ func (gt *Object) Name() string {
419418 return gt .PrivateName
420419}
421420func (gt * Object ) Description () string {
422- return ""
421+ return gt . PrivateDescription
423422}
424423func (gt * Object ) String () string {
425424 return gt .PrivateName
@@ -669,14 +668,12 @@ func (st *Argument) Error() error {
669668//
670669// Example:
671670//
672- // var EntityType = new Interface({
673- // name: 'Entity',
674- // fields: {
675- // name: { type: String }
676- // }
677- // });
678- //
679- //
671+ // var EntityType = new Interface({
672+ // name: 'Entity',
673+ // fields: {
674+ // name: { type: String }
675+ // }
676+ // });
680677type Interface struct {
681678 PrivateName string `json:"name"`
682679 PrivateDescription string `json:"description"`
@@ -780,32 +777,36 @@ func (it *Interface) Error() error {
780777//
781778// Example:
782779//
783- // var PetType = new Union({
784- // name: 'Pet',
785- // types: [ DogType, CatType ],
786- // resolveType(value) {
787- // if (value instanceof Dog) {
788- // return DogType;
789- // }
790- // if (value instanceof Cat) {
791- // return CatType;
792- // }
793- // }
794- // });
780+ // var PetType = new Union({
781+ // name: 'Pet',
782+ // types: [ DogType, CatType ],
783+ // resolveType(value) {
784+ // if (value instanceof Dog) {
785+ // return DogType;
786+ // }
787+ // if (value instanceof Cat) {
788+ // return CatType;
789+ // }
790+ // }
791+ // });
795792type Union struct {
796793 PrivateName string `json:"name"`
797794 PrivateDescription string `json:"description"`
798795 ResolveType ResolveTypeFn
799796
800- typeConfig UnionConfig
801- types []* Object
802- possibleTypes map [string ]bool
797+ typeConfig UnionConfig
798+ initalizedTypes bool
799+ types []* Object
800+ possibleTypes map [string ]bool
803801
804802 err error
805803}
804+
805+ type UnionTypesThunk func () []* Object
806+
806807type UnionConfig struct {
807- Name string `json:"name"`
808- Types [] * Object `json:"types"`
808+ Name string `json:"name"`
809+ Types interface {} `json:"types"`
809810 ResolveType ResolveTypeFn
810811 Description string `json:"description"`
811812}
@@ -823,48 +824,80 @@ func NewUnion(config UnionConfig) *Union {
823824 objectType .PrivateDescription = config .Description
824825 objectType .ResolveType = config .ResolveType
825826
826- if objectType .err = invariantf (
827- len (config .Types ) > 0 ,
828- `Must provide Array of types for Union %v.` , config .Name ,
829- ); objectType .err != nil {
830- return objectType
827+ objectType .typeConfig = config
828+
829+ return objectType
830+ }
831+
832+ func (ut * Union ) Types () []* Object {
833+ if ut .initalizedTypes {
834+ return ut .types
835+ }
836+
837+ var unionTypes []* Object
838+ switch utype := ut .typeConfig .Types .(type ) {
839+ case UnionTypesThunk :
840+ unionTypes = utype ()
841+ case []* Object :
842+ unionTypes = utype
843+ case nil :
844+ default :
845+ ut .err = fmt .Errorf ("Unknown Union.Types type: %T" , ut .typeConfig .Types )
846+ ut .initalizedTypes = true
847+ return nil
831848 }
832- for _ , ttype := range config .Types {
833- if objectType .err = invariantf (
849+
850+ ut .types , ut .err = defineUnionTypes (ut , unionTypes )
851+ ut .initalizedTypes = true
852+ return ut .types
853+ }
854+
855+ func defineUnionTypes (objectType * Union , unionTypes []* Object ) ([]* Object , error ) {
856+ definedUnionTypes := []* Object {}
857+
858+ if err := invariantf (
859+ len (unionTypes ) > 0 ,
860+ `Must provide Array of types for Union %v.` , objectType .Name (),
861+ ); err != nil {
862+ return definedUnionTypes , err
863+ }
864+
865+ for _ , ttype := range unionTypes {
866+ if err := invariantf (
834867 ttype != nil ,
835868 `%v may only contain Object types, it cannot contain: %v.` , objectType , ttype ,
836- ); objectType . err != nil {
837- return objectType
869+ ); err != nil {
870+ return definedUnionTypes , err
838871 }
839872 if objectType .ResolveType == nil {
840- if objectType . err = invariantf (
873+ if err : = invariantf (
841874 ttype .IsTypeOf != nil ,
842875 `Union Type %v does not provide a "resolveType" function ` +
843876 `and possible Type %v does not provide a "isTypeOf" ` +
844877 `function. There is no way to resolve this possible type ` +
845878 `during execution.` , objectType , ttype ,
846- ); objectType . err != nil {
847- return objectType
879+ ); err != nil {
880+ return definedUnionTypes , err
848881 }
849882 }
883+ definedUnionTypes = append (definedUnionTypes , ttype )
850884 }
851- objectType .types = config .Types
852- objectType .typeConfig = config
853885
854- return objectType
855- }
856- func (ut * Union ) Types () []* Object {
857- return ut .types
886+ return definedUnionTypes , nil
858887}
888+
859889func (ut * Union ) String () string {
860890 return ut .PrivateName
861891}
892+
862893func (ut * Union ) Name () string {
863894 return ut .PrivateName
864895}
896+
865897func (ut * Union ) Description () string {
866898 return ut .PrivateDescription
867899}
900+
868901func (ut * Union ) Error () error {
869902 return ut .err
870903}
@@ -1050,18 +1083,18 @@ func (gt *Enum) getNameLookup() map[string]*EnumValueDefinition {
10501083// An input object defines a structured collection of fields which may be
10511084// supplied to a field argument.
10521085//
1053- // Using `NonNull` will ensure that a value must be provided by the query
1086+ // # Using `NonNull` will ensure that a value must be provided by the query
10541087//
10551088// Example:
10561089//
1057- // var GeoPoint = new InputObject({
1058- // name: 'GeoPoint',
1059- // fields: {
1060- // lat: { type: new NonNull(Float) },
1061- // lon: { type: new NonNull(Float) },
1062- // alt: { type: Float, defaultValue: 0 },
1063- // }
1064- // });
1090+ // var GeoPoint = new InputObject({
1091+ // name: 'GeoPoint',
1092+ // fields: {
1093+ // lat: { type: new NonNull(Float) },
1094+ // lon: { type: new NonNull(Float) },
1095+ // alt: { type: Float, defaultValue: 0 },
1096+ // }
1097+ // });
10651098type InputObject struct {
10661099 PrivateName string `json:"name"`
10671100 PrivateDescription string `json:"description"`
@@ -1200,14 +1233,13 @@ func (gt *InputObject) Error() error {
12001233//
12011234// Example:
12021235//
1203- // var PersonType = new Object({
1204- // name: 'Person',
1205- // fields: () => ({
1206- // parents: { type: new List(Person) },
1207- // children: { type: new List(Person) },
1208- // })
1209- // })
1210- //
1236+ // var PersonType = new Object({
1237+ // name: 'Person',
1238+ // fields: () => ({
1239+ // parents: { type: new List(Person) },
1240+ // children: { type: new List(Person) },
1241+ // })
1242+ // })
12111243type List struct {
12121244 OfType Type `json:"ofType"`
12131245
@@ -1226,14 +1258,14 @@ func NewList(ofType Type) *List {
12261258 return gl
12271259}
12281260func (gl * List ) Name () string {
1229- return fmt .Sprintf ("%v " , gl .OfType )
1261+ return fmt .Sprintf ("[%v] " , gl .OfType )
12301262}
12311263func (gl * List ) Description () string {
12321264 return ""
12331265}
12341266func (gl * List ) String () string {
12351267 if gl .OfType != nil {
1236- return fmt . Sprintf ( "[%v]" , gl .OfType )
1268+ return gl .Name ( )
12371269 }
12381270 return ""
12391271}
@@ -1251,12 +1283,12 @@ func (gl *List) Error() error {
12511283//
12521284// Example:
12531285//
1254- // var RowType = new Object({
1255- // name: 'Row',
1256- // fields: () => ({
1257- // id: { type: new NonNull(String) },
1258- // })
1259- // })
1286+ // var RowType = new Object({
1287+ // name: 'Row',
1288+ // fields: () => ({
1289+ // id: { type: new NonNull(String) },
1290+ // })
1291+ // })
12601292//
12611293// Note: the enforcement of non-nullability occurs within the executor.
12621294type NonNull struct {
0 commit comments