diff --git a/demo/pkg/subgraphs/test1/subgraph/generated/generated.go b/demo/pkg/subgraphs/test1/subgraph/generated/generated.go
index 40afe123fb..9ebc8745f1 100644
--- a/demo/pkg/subgraphs/test1/subgraph/generated/generated.go
+++ b/demo/pkg/subgraphs/test1/subgraph/generated/generated.go
@@ -674,10 +674,16 @@ type ComplexityRoot struct {
Value func(childComplexity int) int
}
+ SubscribeMetadata struct {
+ InitialPayload func(childComplexity int) int
+ SubscribeExtensions func(childComplexity int) int
+ }
+
Subscription struct {
HeaderValue func(childComplexity int, name string, repeat *int) int
InitPayloadValue func(childComplexity int, key string, repeat *int) int
InitialPayload func(childComplexity int, repeat *int) int
+ Metadata func(childComplexity int, repeat int) int
ReturnsError func(childComplexity int) int
}
@@ -715,6 +721,7 @@ type ComplexityRoot struct {
}
TimestampedString struct {
+ Extensions func(childComplexity int) int
InitialPayload func(childComplexity int) int
Seq func(childComplexity int) int
Total func(childComplexity int) int
@@ -925,7 +932,8 @@ type SubscriptionResolver interface {
HeaderValue(ctx context.Context, name string, repeat *int) (<-chan *model.TimestampedString, error)
InitPayloadValue(ctx context.Context, key string, repeat *int) (<-chan *model.TimestampedString, error)
InitialPayload(ctx context.Context, repeat *int) (<-chan map[string]any, error)
- ReturnsError(ctx context.Context) (<-chan *string, error)
+ ReturnsError(ctx context.Context) (<-chan string, error)
+ Metadata(ctx context.Context, repeat int) (<-chan *model.SubscribeMetadata, error)
}
type executableSchema struct {
@@ -4825,6 +4833,20 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.Secret.Value(childComplexity), true
+ case "SubscribeMetadata.initialPayload":
+ if e.complexity.SubscribeMetadata.InitialPayload == nil {
+ break
+ }
+
+ return e.complexity.SubscribeMetadata.InitialPayload(childComplexity), true
+
+ case "SubscribeMetadata.subscribeExtensions":
+ if e.complexity.SubscribeMetadata.SubscribeExtensions == nil {
+ break
+ }
+
+ return e.complexity.SubscribeMetadata.SubscribeExtensions(childComplexity), true
+
case "Subscription.headerValue":
if e.complexity.Subscription.HeaderValue == nil {
break
@@ -4861,6 +4883,18 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.Subscription.InitialPayload(childComplexity, args["repeat"].(*int)), true
+ case "Subscription.metadata":
+ if e.complexity.Subscription.Metadata == nil {
+ break
+ }
+
+ args, err := ec.field_Subscription_metadata_args(ctx, rawArgs)
+ if err != nil {
+ return 0, false
+ }
+
+ return e.complexity.Subscription.Metadata(childComplexity, args["repeat"].(int)), true
+
case "Subscription.returnsError":
if e.complexity.Subscription.ReturnsError == nil {
break
@@ -5057,6 +5091,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.Thing.B(childComplexity), true
+ case "TimestampedString.extensions":
+ if e.complexity.TimestampedString.Extensions == nil {
+ break
+ }
+
+ return e.complexity.TimestampedString.Extensions(childComplexity), true
+
case "TimestampedString.initialPayload":
if e.complexity.TimestampedString.InitialPayload == nil {
break
@@ -6377,6 +6418,12 @@ type TimestampedString {
"Total number of responses to be sent"
total: Int!
initialPayload: Map
+ extensions: Map
+}
+
+type SubscribeMetadata {
+ initialPayload: Map
+ subscribeExtensions: Map
}
type Subscription {
@@ -6386,7 +6433,9 @@ type Subscription {
initPayloadValue(key: String!, repeat: Int): TimestampedString!
"Returns a stream with the value of the WS initial payload."
initialPayload(repeat: Int): Map
- returnsError: String
+ returnsError: String!
+ "Returns a stream with the values of the WS initial payload and subscribe extensions"
+ metadata(repeat: Int! = 1): SubscribeMetadata!
}
type Employee @key(fields: "id") {
@@ -7185,7 +7234,8 @@ type ZBigObject {
xFieldOnZBigObject: Float!
yFieldOnZBigObject: String!
zFieldOnZBigObject: Int!
-}`, BuiltIn: false},
+}
+`, BuiltIn: false},
{Name: "../../federation/directives.graphql", Input: `
directive @authenticated on FIELD_DEFINITION | OBJECT | INTERFACE | SCALAR | ENUM
directive @composeDirective(name: String!) repeatable on SCHEMA
@@ -7950,6 +8000,34 @@ func (ec *executionContext) field_Subscription_initialPayload_argsRepeat(
return zeroVal, nil
}
+func (ec *executionContext) field_Subscription_metadata_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
+ var err error
+ args := map[string]any{}
+ arg0, err := ec.field_Subscription_metadata_argsRepeat(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["repeat"] = arg0
+ return args, nil
+}
+func (ec *executionContext) field_Subscription_metadata_argsRepeat(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (int, error) {
+ if _, ok := rawArgs["repeat"]; !ok {
+ var zeroVal int
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("repeat"))
+ if tmp, ok := rawArgs["repeat"]; ok {
+ return ec.unmarshalNInt2int(ctx, tmp)
+ }
+
+ var zeroVal int
+ return zeroVal, nil
+}
+
func (ec *executionContext) field___Directive_args_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
var err error
args := map[string]any{}
@@ -32354,6 +32432,88 @@ func (ec *executionContext) fieldContext_Secret_value(_ context.Context, field g
return fc, nil
}
+func (ec *executionContext) _SubscribeMetadata_initialPayload(ctx context.Context, field graphql.CollectedField, obj *model.SubscribeMetadata) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_SubscribeMetadata_initialPayload(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.InitialPayload, nil
+ })
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ if resTmp == nil {
+ return graphql.Null
+ }
+ res := resTmp.(map[string]any)
+ fc.Result = res
+ return ec.marshalOMap2map(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_SubscribeMetadata_initialPayload(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "SubscribeMetadata",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Map does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _SubscribeMetadata_subscribeExtensions(ctx context.Context, field graphql.CollectedField, obj *model.SubscribeMetadata) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_SubscribeMetadata_subscribeExtensions(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.SubscribeExtensions, nil
+ })
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ if resTmp == nil {
+ return graphql.Null
+ }
+ res := resTmp.(map[string]any)
+ fc.Result = res
+ return ec.marshalOMap2map(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_SubscribeMetadata_subscribeExtensions(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "SubscribeMetadata",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Map does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
func (ec *executionContext) _Subscription_headerValue(ctx context.Context, field graphql.CollectedField) (ret func(ctx context.Context) graphql.Marshaler) {
fc, err := ec.fieldContext_Subscription_headerValue(ctx, field)
if err != nil {
@@ -32417,6 +32577,8 @@ func (ec *executionContext) fieldContext_Subscription_headerValue(ctx context.Co
return ec.fieldContext_TimestampedString_total(ctx, field)
case "initialPayload":
return ec.fieldContext_TimestampedString_initialPayload(ctx, field)
+ case "extensions":
+ return ec.fieldContext_TimestampedString_extensions(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type TimestampedString", field.Name)
},
@@ -32498,6 +32660,8 @@ func (ec *executionContext) fieldContext_Subscription_initPayloadValue(ctx conte
return ec.fieldContext_TimestampedString_total(ctx, field)
case "initialPayload":
return ec.fieldContext_TimestampedString_initialPayload(ctx, field)
+ case "extensions":
+ return ec.fieldContext_TimestampedString_extensions(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type TimestampedString", field.Name)
},
@@ -32603,11 +32767,14 @@ func (ec *executionContext) _Subscription_returnsError(ctx context.Context, fiel
return nil
}
if resTmp == nil {
+ if !graphql.HasFieldError(ctx, fc) {
+ ec.Errorf(ctx, "must not be null")
+ }
return nil
}
return func(ctx context.Context) graphql.Marshaler {
select {
- case res, ok := <-resTmp.(<-chan *string):
+ case res, ok := <-resTmp.(<-chan string):
if !ok {
return nil
}
@@ -32615,7 +32782,7 @@ func (ec *executionContext) _Subscription_returnsError(ctx context.Context, fiel
w.Write([]byte{'{'})
graphql.MarshalString(field.Alias).MarshalGQL(w)
w.Write([]byte{':'})
- ec.marshalOString2ᚖstring(ctx, field.Selections, res).MarshalGQL(w)
+ ec.marshalNString2string(ctx, field.Selections, res).MarshalGQL(w)
w.Write([]byte{'}'})
})
case <-ctx.Done():
@@ -32637,6 +32804,81 @@ func (ec *executionContext) fieldContext_Subscription_returnsError(_ context.Con
return fc, nil
}
+func (ec *executionContext) _Subscription_metadata(ctx context.Context, field graphql.CollectedField) (ret func(ctx context.Context) graphql.Marshaler) {
+ fc, err := ec.fieldContext_Subscription_metadata(ctx, field)
+ if err != nil {
+ return nil
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = nil
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Subscription().Metadata(rctx, fc.Args["repeat"].(int))
+ })
+ if err != nil {
+ ec.Error(ctx, err)
+ return nil
+ }
+ if resTmp == nil {
+ if !graphql.HasFieldError(ctx, fc) {
+ ec.Errorf(ctx, "must not be null")
+ }
+ return nil
+ }
+ return func(ctx context.Context) graphql.Marshaler {
+ select {
+ case res, ok := <-resTmp.(<-chan *model.SubscribeMetadata):
+ if !ok {
+ return nil
+ }
+ return graphql.WriterFunc(func(w io.Writer) {
+ w.Write([]byte{'{'})
+ graphql.MarshalString(field.Alias).MarshalGQL(w)
+ w.Write([]byte{':'})
+ ec.marshalNSubscribeMetadata2ᚖgithubᚗcomᚋwundergraphᚋcosmoᚋdemoᚋpkgᚋsubgraphsᚋtest1ᚋsubgraphᚋmodelᚐSubscribeMetadata(ctx, field.Selections, res).MarshalGQL(w)
+ w.Write([]byte{'}'})
+ })
+ case <-ctx.Done():
+ return nil
+ }
+ }
+}
+
+func (ec *executionContext) fieldContext_Subscription_metadata(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "Subscription",
+ Field: field,
+ IsMethod: true,
+ IsResolver: true,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ switch field.Name {
+ case "initialPayload":
+ return ec.fieldContext_SubscribeMetadata_initialPayload(ctx, field)
+ case "subscribeExtensions":
+ return ec.fieldContext_SubscribeMetadata_subscribeExtensions(ctx, field)
+ }
+ return nil, fmt.Errorf("no field named %q was found under type SubscribeMetadata", field.Name)
+ },
+ }
+ defer func() {
+ if r := recover(); r != nil {
+ err = ec.Recover(ctx, r)
+ ec.Error(ctx, err)
+ }
+ }()
+ ctx = graphql.WithFieldContext(ctx, fc)
+ if fc.Args, err = ec.field_Subscription_metadata_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
+ ec.Error(ctx, err)
+ return fc, err
+ }
+ return fc, nil
+}
+
func (ec *executionContext) _TBigObject_aFieldOnTBigObject(ctx context.Context, field graphql.CollectedField, obj *model.TBigObject) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_TBigObject_aFieldOnTBigObject(ctx, field)
if err != nil {
@@ -34042,6 +34284,47 @@ func (ec *executionContext) fieldContext_TimestampedString_initialPayload(_ cont
return fc, nil
}
+func (ec *executionContext) _TimestampedString_extensions(ctx context.Context, field graphql.CollectedField, obj *model.TimestampedString) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_TimestampedString_extensions(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Extensions, nil
+ })
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ if resTmp == nil {
+ return graphql.Null
+ }
+ res := resTmp.(map[string]any)
+ fc.Result = res
+ return ec.marshalOMap2map(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_TimestampedString_extensions(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "TimestampedString",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Map does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
func (ec *executionContext) _UBigObject_aFieldOnUBigObject(ctx context.Context, field graphql.CollectedField, obj *model.UBigObject) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_UBigObject_aFieldOnUBigObject(ctx, field)
if err != nil {
@@ -47135,6 +47418,44 @@ func (ec *executionContext) _Secret(ctx context.Context, sel ast.SelectionSet, o
return out
}
+var subscribeMetadataImplementors = []string{"SubscribeMetadata"}
+
+func (ec *executionContext) _SubscribeMetadata(ctx context.Context, sel ast.SelectionSet, obj *model.SubscribeMetadata) graphql.Marshaler {
+ fields := graphql.CollectFields(ec.OperationContext, sel, subscribeMetadataImplementors)
+
+ out := graphql.NewFieldSet(fields)
+ deferred := make(map[string]*graphql.FieldSet)
+ for i, field := range fields {
+ switch field.Name {
+ case "__typename":
+ out.Values[i] = graphql.MarshalString("SubscribeMetadata")
+ case "initialPayload":
+ out.Values[i] = ec._SubscribeMetadata_initialPayload(ctx, field, obj)
+ case "subscribeExtensions":
+ out.Values[i] = ec._SubscribeMetadata_subscribeExtensions(ctx, field, obj)
+ default:
+ panic("unknown field " + strconv.Quote(field.Name))
+ }
+ }
+ out.Dispatch(ctx)
+ if out.Invalids > 0 {
+ return graphql.Null
+ }
+
+ atomic.AddInt32(&ec.deferred, int32(len(deferred)))
+
+ for label, dfs := range deferred {
+ ec.processDeferredGroup(graphql.DeferredGroup{
+ Label: label,
+ Path: graphql.GetPath(ctx),
+ FieldSet: dfs,
+ Context: ctx,
+ })
+ }
+
+ return out
+}
+
var subscriptionImplementors = []string{"Subscription"}
func (ec *executionContext) _Subscription(ctx context.Context, sel ast.SelectionSet) func(ctx context.Context) graphql.Marshaler {
@@ -47156,6 +47477,8 @@ func (ec *executionContext) _Subscription(ctx context.Context, sel ast.Selection
return ec._Subscription_initialPayload(ctx, fields[0])
case "returnsError":
return ec._Subscription_returnsError(ctx, fields[0])
+ case "metadata":
+ return ec._Subscription_metadata(ctx, fields[0])
default:
panic("unknown field " + strconv.Quote(fields[0].Name))
}
@@ -47397,6 +47720,8 @@ func (ec *executionContext) _TimestampedString(ctx context.Context, sel ast.Sele
}
case "initialPayload":
out.Values[i] = ec._TimestampedString_initialPayload(ctx, field, obj)
+ case "extensions":
+ out.Values[i] = ec._TimestampedString_extensions(ctx, field, obj)
default:
panic("unknown field " + strconv.Quote(field.Name))
}
@@ -49239,6 +49564,20 @@ func (ec *executionContext) marshalNString2ᚕᚕstringᚄ(ctx context.Context,
return ret
}
+func (ec *executionContext) marshalNSubscribeMetadata2githubᚗcomᚋwundergraphᚋcosmoᚋdemoᚋpkgᚋsubgraphsᚋtest1ᚋsubgraphᚋmodelᚐSubscribeMetadata(ctx context.Context, sel ast.SelectionSet, v model.SubscribeMetadata) graphql.Marshaler {
+ return ec._SubscribeMetadata(ctx, sel, &v)
+}
+
+func (ec *executionContext) marshalNSubscribeMetadata2ᚖgithubᚗcomᚋwundergraphᚋcosmoᚋdemoᚋpkgᚋsubgraphsᚋtest1ᚋsubgraphᚋmodelᚐSubscribeMetadata(ctx context.Context, sel ast.SelectionSet, v *model.SubscribeMetadata) graphql.Marshaler {
+ if v == nil {
+ if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
+ ec.Errorf(ctx, "the requested element is null which the schema does not allow")
+ }
+ return graphql.Null
+ }
+ return ec._SubscribeMetadata(ctx, sel, v)
+}
+
func (ec *executionContext) marshalNThing2ᚕᚖgithubᚗcomᚋwundergraphᚋcosmoᚋdemoᚋpkgᚋsubgraphsᚋtest1ᚋsubgraphᚋmodelᚐThingᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Thing) graphql.Marshaler {
ret := make(graphql.Array, len(v))
var wg sync.WaitGroup
diff --git a/demo/pkg/subgraphs/test1/subgraph/model/models_gen.go b/demo/pkg/subgraphs/test1/subgraph/model/models_gen.go
index 877f127fbe..996603e3a3 100644
--- a/demo/pkg/subgraphs/test1/subgraph/model/models_gen.go
+++ b/demo/pkg/subgraphs/test1/subgraph/model/models_gen.go
@@ -668,6 +668,11 @@ type Secret struct {
Value *string `json:"value,omitempty"`
}
+type SubscribeMetadata struct {
+ InitialPayload map[string]any `json:"initialPayload,omitempty"`
+ SubscribeExtensions map[string]any `json:"subscribeExtensions,omitempty"`
+}
+
type Subscription struct {
}
@@ -716,6 +721,7 @@ type TimestampedString struct {
// Total number of responses to be sent
Total int `json:"total"`
InitialPayload map[string]any `json:"initialPayload,omitempty"`
+ Extensions map[string]any `json:"extensions,omitempty"`
}
type UBigObject struct {
diff --git a/demo/pkg/subgraphs/test1/subgraph/schema.graphqls b/demo/pkg/subgraphs/test1/subgraph/schema.graphqls
index 8b6b90b885..9866d4d021 100644
--- a/demo/pkg/subgraphs/test1/subgraph/schema.graphqls
+++ b/demo/pkg/subgraphs/test1/subgraph/schema.graphqls
@@ -75,6 +75,12 @@ type TimestampedString {
"Total number of responses to be sent"
total: Int!
initialPayload: Map
+ extensions: Map
+}
+
+type SubscribeMetadata {
+ initialPayload: Map
+ subscribeExtensions: Map
}
type Subscription {
@@ -84,7 +90,9 @@ type Subscription {
initPayloadValue(key: String!, repeat: Int): TimestampedString!
"Returns a stream with the value of the WS initial payload."
initialPayload(repeat: Int): Map
- returnsError: String
+ returnsError: String!
+ "Returns a stream with the values of the WS initial payload and subscribe extensions"
+ metadata(repeat: Int! = 1): SubscribeMetadata!
}
type Employee @key(fields: "id") {
@@ -883,4 +891,4 @@ type ZBigObject {
xFieldOnZBigObject: Float!
yFieldOnZBigObject: String!
zFieldOnZBigObject: Int!
-}
\ No newline at end of file
+}
diff --git a/demo/pkg/subgraphs/test1/subgraph/schema.resolvers.go b/demo/pkg/subgraphs/test1/subgraph/schema.resolvers.go
index a545c32a27..c767bee58f 100644
--- a/demo/pkg/subgraphs/test1/subgraph/schema.resolvers.go
+++ b/demo/pkg/subgraphs/test1/subgraph/schema.resolvers.go
@@ -11,6 +11,7 @@ import (
"strings"
"time"
+ "github.com/99designs/gqlgen/graphql"
"github.com/wundergraph/cosmo/demo/pkg/injector"
"github.com/wundergraph/cosmo/demo/pkg/subgraphs/test1/subgraph/generated"
"github.com/wundergraph/cosmo/demo/pkg/subgraphs/test1/subgraph/model"
@@ -188,6 +189,8 @@ func (r *subscriptionResolver) HeaderValue(ctx context.Context, name string, rep
}
ch := make(chan *model.TimestampedString, 1)
+ opCtx := graphql.GetOperationContext(ctx)
+
if repeat == nil {
repeat = new(int)
*repeat = 1
@@ -214,6 +217,7 @@ func (r *subscriptionResolver) HeaderValue(ctx context.Context, name string, rep
Seq: ii,
Total: *repeat,
InitialPayload: payload,
+ Extensions: opCtx.Extensions,
}:
}
}
@@ -229,6 +233,8 @@ func (r *subscriptionResolver) InitPayloadValue(ctx context.Context, key string,
}
ch := make(chan *model.TimestampedString, 1)
+ opCtx := graphql.GetOperationContext(ctx)
+
if repeat == nil {
repeat = new(int)
*repeat = 1
@@ -250,6 +256,7 @@ func (r *subscriptionResolver) InitPayloadValue(ctx context.Context, key string,
Seq: ii,
Total: *repeat,
InitialPayload: payload,
+ Extensions: opCtx.Extensions,
}:
}
}
@@ -289,10 +296,44 @@ func (r *subscriptionResolver) InitialPayload(ctx context.Context, repeat *int)
}
// ReturnsError is the resolver for the returnsError field.
-func (r *subscriptionResolver) ReturnsError(ctx context.Context) (<-chan *string, error) {
+func (r *subscriptionResolver) ReturnsError(ctx context.Context) (<-chan string, error) {
return nil, errors.New("this is an error")
}
+// Metadata is the resolver for the metadata field.
+func (r *subscriptionResolver) Metadata(ctx context.Context, repeat int) (<-chan *model.SubscribeMetadata, error) {
+ payload := injector.InitPayload(ctx)
+ if payload == nil {
+ payload = make(map[string]any)
+ }
+
+ opCtx := graphql.GetOperationContext(ctx)
+ if opCtx == nil {
+ return nil, errors.New("operation context not found")
+ }
+
+ ch := make(chan *model.SubscribeMetadata, 1)
+
+ go func() {
+ defer close(ch)
+
+ for range repeat {
+ time.Sleep(100 * time.Millisecond)
+ select {
+ case <-ctx.Done():
+ return
+
+ case ch <- &model.SubscribeMetadata{
+ InitialPayload: payload,
+ SubscribeExtensions: opCtx.Extensions,
+ }:
+ }
+ }
+ }()
+
+ return ch, nil
+}
+
// Query returns generated.QueryResolver implementation.
func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} }
diff --git a/docs-website/docs.json b/docs-website/docs.json
index fc6b4f6d4e..2f197f4e77 100644
--- a/docs-website/docs.json
+++ b/docs-website/docs.json
@@ -162,7 +162,8 @@
"router/subscriptions/server-sent-events-sse",
"router/subscriptions/multipart-http-requests",
"router/subscriptions/websocket-subprotocols",
- "router/subscriptions/router-configuration-for-subscriptions"
+ "router/subscriptions/router-configuration-for-subscriptions",
+ "router/subscriptions-migration"
]
},
{
diff --git a/docs-website/router/configuration.mdx b/docs-website/router/configuration.mdx
index 1c157274a0..a728d12003 100644
--- a/docs-website/router/configuration.mdx
+++ b/docs-website/router/configuration.mdx
@@ -1846,14 +1846,16 @@ Configure the GraphQL Execution Engine of the Router.
| ENGINE_ENABLE_REQUEST_TRACING | enable_request_tracing | | Enable [Advanced Request Tracing (ART)](/router/advanced-request-tracing-art)This config is not correlated to OTEL tracing. | true |
| ENGINE_ENABLE_EXECUTION_PLAN_CACHE_RESPONSE_HEADER | enable_execution_plan_cache_response_header | | **Deprecated**, use ["enable_cache_response_headers"](/router/configuration#debug-configuration) instead. When enabled, the Router sets the response Header "X-WG-Execution-Plan-Cache" to "HIT" or "MISS" | false |
| ENGINE_MAX_CONCURRENT_RESOLVERS | max_concurrent_resolvers | | Use this to limit the concurrency in the GraphQL Engine. A high number will lead to more memory usage. A number too low will slow down your Router. | 32 |
-| ENGINE_ENABLE_NET_POLL | enable_net_poll | | Enables the more efficient poll implementation for all WebSocket implementations (client, server) of the router. This is only available on Linux and MacOS. On Windows or when the host system is limited, the default synchronous implementation is used. | true |
-| ENGINE_WEBSOCKET_CLIENT_POLL_TIMEOUT | websocket_client_poll_timeout | | The timeout for the poll loop of the WebSocket client implementation. The period is specified as a string with a number and a unit | 1s |
-| ENGINE_WEBSOCKET_CLIENT_CONN_BUFFER_SIZE | websocket_client_conn_buffer_size | | The buffer size for the poll buffer of the WebSocket client implementation. The buffer size determines how many connections can be handled in one loop. | 128 |
-| ENGINE_WEBSOCKET_CLIENT_READ_TIMEOUT | websocket_client_read_timeout | | The timeout for the websocket read of the WebSocket client implementation. | 5s |
+| ENGINE_ENABLE_NET_POLL | enable_net_poll | | Enables the more efficient poll implementation for the server-side WebSocket handler of the router. This is only available on Linux and MacOS. On Windows or when the host system is limited, the default synchronous implementation is used. Has no effect on the router's upstream connections to subgraphs. | true |
+| ENGINE_WEBSOCKET_SERVER_READ_TIMEOUT | websocket_server_read_timeout | | Read timeout on the server-side WebSocket handler (router accepting clients). Specified as a Go duration string, e.g. `10ms`, `1s`, `1m`. | 5s |
+| ENGINE_WEBSOCKET_SERVER_WRITE_TIMEOUT | websocket_server_write_timeout | | Write timeout on the server-side WebSocket handler (router accepting clients). | 10s |
+| ENGINE_WEBSOCKET_SERVER_POLL_TIMEOUT | websocket_server_poll_timeout | | The timeout for the poll loop of the server-side WebSocket handler. The period is specified as a string with a number and a unit. | 1s |
+| ENGINE_WEBSOCKET_SERVER_CONN_BUFFER_SIZE | websocket_server_conn_buffer_size | | The buffer size for the poll buffer of the server-side WebSocket handler. The buffer size determines how many connections can be handled in one loop. | 128 |
| ENGINE_WEBSOCKET_CLIENT_WRITE_TIMEOUT | websocket_client_write_timeout | | The timeout for the websocket write of the WebSocket client implementation. | 10s |
| ENGINE_WEBSOCKET_CLIENT_PING_INTERVAL | websocket_client_ping_interval | | The Websocket client ping interval to the subgraph. Defines how often the router will ping the subgraph to signal that the connection is still alive. Timeout needs to be coordinated with the subgraph. The timeout is specified as a string with a number and a unit, e.g. 10ms, 1s, 1m, 1h. The supported units are 'ms', 's', 'm', 'h'. | 15s |
| ENGINE_WEBSOCKET_CLIENT_PING_TIMEOUT | websocket_client_ping_timeout | | The Websocket client ping timeout to the subgraph. Defines how long the router will wait for a ping response from the subgraph. The timeout is specified as a string with a number and a unit, e.g. 10ms, 1s, 1m, 1h. The supported units are 'ms', 's', 'm', 'h'. | 30s |
-| ENGINE_WEBSOCKET_CLIENT_FRAME_TIMEOUT | websocket_client_frame_timeout | | The Websocket client frame timeout to the subgraph. Defines how long the router will wait for a frame response from the subgraph. The timeout is specified as a string with a number and a unit, e.g. 10ms, 1s, 1m, 1h. The supported units are 'ms', 's', 'm', 'h'. | 100ms |
+| ENGINE_WEBSOCKET_CLIENT_ACK_TIMEOUT | websocket_client_ack_timeout | | How long the router waits for a `connection_ack` from a subgraph after sending `connection_init`. Minimum `1s`. | 30s |
+| ENGINE_WEBSOCKET_CLIENT_READ_LIMIT | websocket_client_read_limit | | Maximum size of an incoming WebSocket message from a subgraph. Specified as a byte string, e.g. `512KB`, `1MB`. Minimum `1KB`. | 1MB |
| ENGINE_EXECUTION_PLAN_CACHE_SIZE | execution_plan_cache_size | | Define how many GraphQL Operations should be stored in the execution plan cache. A low number will lead to more frequent cache misses, which will lead to increased latency. | 1024 |
| ENGINE_SLOW_PLAN_CACHE_SIZE | slow_plan_cache_size | | The maximum number of entries in the slow plan cache. This cache protects slow-to-plan queries from being evicted by the main plan cache's LFU policy. Only used when `in_memory_fallback` is enabled. See [Slow Plan Cache](/concepts/cache-warmer#slow-plan-cache). | 300 |
| ENGINE_SLOW_PLAN_CACHE_THRESHOLD | slow_plan_cache_threshold | | The minimum planning duration for a query to be promoted into the slow plan cache. Queries that take longer than this threshold to plan are considered expensive and protected from eviction. The period is specified as a string with a number and a unit, e.g. 10ms, 1s, 5s. The supported units are 'ms', 's', 'm', 'h'. | 100ms |
@@ -1872,6 +1874,14 @@ Configure the GraphQL Execution Engine of the Router.
| ENGINE_SUBSCRIPTION_FETCH_TIMEOUT | subscription_fetch_timeout | | The maximum time a subscription fetch can take before it is considered timed out. | 30s |
| ENGINE_RELAX_SUBGRAPH_OPERATION_FIELD_SELECTION_MERGING_NULLABILITY | relax_subgraph_operation_field_selection_merging_nullability | | Relaxes nullability validation for [field selection merging](/router/relaxed-field-selection-merging-nullability) across union member types. | false |
+
+ **Subject to change.** `enable_net_poll`, `websocket_server_poll_timeout`, and `websocket_server_conn_buffer_size` may be removed or changed in a future release without a standard deprecation cycle. Avoid depending on them.
+
+
+
+ If you're upgrading from a previous release and set `websocket_client_read_timeout`, `websocket_client_poll_timeout`, `websocket_client_conn_buffer_size`, `websocket_client_frame_timeout`, or `websocket_client_write_timeout`, see the [subscriptions overhaul migration guide](/router/subscriptions-migration). Several of these were removed and one (`websocket_client_write_timeout`) kept its name but changed scope.
+
+
### Example YAML config:
@@ -1885,11 +1895,17 @@ engine:
enable_websocket_epoll_kqueue: true
epoll_kqueue_poll_timeout: "1s"
epoll_kqueue_conn_buffer_size: 128
- websocket_client_read_timeout: "1s"
- websocket_client_write_timeout: "5s"
+ # Server-side WebSocket handler (router accepting clients)
+ websocket_server_read_timeout: "5s"
+ websocket_server_write_timeout: "10s"
+ websocket_server_poll_timeout: "1s"
+ websocket_server_conn_buffer_size: 128
+ # Upstream subscription client (router connecting to subgraphs)
+ websocket_client_write_timeout: "10s"
websocket_client_ping_interval: "15s"
websocket_client_ping_timeout: "30s"
- websocket_client_frame_timeout: "100ms"
+ websocket_client_ack_timeout: "30s"
+ websocket_client_read_limit: "1MB"
execution_plan_cache_size: 10000
slow_plan_cache_size: 300
slow_plan_cache_threshold: 100ms
diff --git a/docs-website/router/subgraph-error-propagation.mdx b/docs-website/router/subgraph-error-propagation.mdx
index 9e7f34c3ff..ea78f8bf58 100644
--- a/docs-website/router/subgraph-error-propagation.mdx
+++ b/docs-website/router/subgraph-error-propagation.mdx
@@ -178,6 +178,46 @@ subgraph_error_propagation:
}
```
+## Upstream WebSocket errors during subscriptions
+
+When a subgraph WebSocket connection carrying active subscriptions fails — TCP drop, EOF, or a close frame from the subgraph — the router delivers a GraphQL error on each affected subscription and terminates that subscription. The downstream client's WebSocket stays open and other subscriptions on that connection continue normally.
+
+The error uses the `message` `"upstream service error"` and the `code` extension is set to the value configured in `subgraph_error_propagation.default_extension_code` (default `DOWNSTREAM_SERVICE_ERROR`).
+
+**Sudden closure (TCP drop, EOF):**
+
+```json
+{
+ "errors": [
+ {
+ "message": "upstream service error",
+ "extensions": { "code": "DOWNSTREAM_SERVICE_ERROR" }
+ }
+ ]
+}
+```
+
+**Close frame from subgraph:** when the failure carries a WebSocket close frame, the router additionally populates `closeCode` and `closeReason` extensions:
+
+```json
+{
+ "errors": [
+ {
+ "message": "upstream service error",
+ "extensions": {
+ "code": "DOWNSTREAM_SERVICE_ERROR",
+ "closeCode": 1011,
+ "closeReason": "internal error"
+ }
+ }
+ ]
+}
+```
+
+
+ Prior to the [subscription overhaul release](/router/subscriptions-migration), upstream WebSocket failures during an active subscription terminated the entire downstream client WebSocket with close code `1001` and no GraphQL error payload. Clients that detected upstream failures via that close code must now inspect the `code` extension on GraphQL errors.
+
+
## Fallback status code errors
In cases where the router cannot parse a properly formed error from the subgraph response, e.g.
diff --git a/docs-website/router/subscriptions-migration.mdx b/docs-website/router/subscriptions-migration.mdx
new file mode 100644
index 0000000000..f4f9c77229
--- /dev/null
+++ b/docs-website/router/subscriptions-migration.mdx
@@ -0,0 +1,133 @@
+---
+title: "Migration: Subscriptions Overhaul"
+description: "Migration guide for the subscriptions overhaul. Covers the three behavioral changes and the engine WebSocket configuration renames."
+icon: "arrows-turn-right"
+---
+
+This release ships three behavioral changes alongside configuration renames. Each behavioral change is documented in its reference page; this guide links to those and summarizes what an upgrader needs to check.
+
+The router's WebSocket protocol behavior is a strict superset of the `graphql-transport-ws` and `graphql-ws` specifications. Spec-compliant clients are unaffected by the spec-fix change below. The other two changes may require adjustments.
+
+## Subgraph `connection_init` payload no longer merges subscribe extensions
+
+Previously the `extensions` field from each subscribe message was merged into `connection_init.payload.extensions` on the subgraph WebSocket, overriding any existing extensions set via `initial_payload`. The router now forwards subscribe-message extensions in the per-operation `subscribe.payload.extensions` field, where the spec places them.
+
+**Action for subgraph implementations:** if your subgraph reads subscribe-message extensions from `connection_init.payload.extensions`, update it to read them from `subscribe.payload.extensions`.
+
+See [Subscriptions - Using the extensions field](/router/subscriptions#using-the-extensions-field) for the new behavior.
+
+## Upstream connection errors no longer tear down the client WebSocket
+
+Previously, when a subgraph WebSocket died during active subscriptions (TCP drop, EOF, or a close frame from the subgraph), the router sent a WebSocket close frame with code `1001` to the downstream client and tore down the entire client connection. No GraphQL error payload was delivered for the affected subscription.
+
+The router now emits a per-subscription GraphQL error and terminates that subscription. The downstream client's WebSocket stays open and other subscriptions on the same connection continue. The error uses the message `"upstream service error"` and sets the `code` extension to `subgraph_error_propagation.default_extension_code` (default `DOWNSTREAM_SERVICE_ERROR`). When the failure includes a WebSocket close frame, the router additionally populates `closeCode` and `closeReason` extensions.
+
+**Action for clients:** if your client detected upstream subgraph failures by observing a WebSocket close with code `1001`, inspect the GraphQL error `code` extension instead. Reconnect logic that previously operated at the whole-connection level may need to move to individual subscriptions.
+
+See [Subgraph Error Propagation - Upstream WebSocket errors during subscriptions](/router/subgraph-error-propagation#upstream-websocket-errors-during-subscriptions) for the new behavior and example payloads.
+
+## `complete` is no longer sent after `error` on `graphql-transport-ws`
+
+Previously, when a subscription's backing async iterable raised an error, the router sent both `error` and `complete` for the same operation ID:
+
+```
+{"id":"1","type":"error","payload":[{"message":"..."}]}
+{"id":"1","type":"complete"}
+```
+
+This mirrored a bug in the [`graphql-ws` reference implementation](https://github.com/enisdenjo/graphql-ws), accepted upstream as a fix in [enisdenjo/graphql-ws#667](https://github.com/enisdenjo/graphql-ws/pull/667). The router now sends only the `error` message, matching the `graphql-transport-ws` spec:
+
+> **Error:** This message terminates the operation and no further messages will be sent.
+>
+> **Complete (Server → Client):** If the server dispatched the `Error` message relative to the original `Subscribe` message, no `Complete` message will be emitted.
+
+**Action:** none required. Spec-compliant clients ignore messages for operations they consider already completed.
+
+## Engine WebSocket configuration
+
+Several `websocket_client_*` options were named as if they tuned the router's upstream connections to subgraphs, but were actually used for the server-side WebSocket handler (the router's downstream endpoint accepting client connections). This release splits those roles cleanly. All changes are listed below.
+
+
+ The old `websocket_client_poll_timeout`, `websocket_client_conn_buffer_size`, `websocket_client_read_timeout`, and `websocket_client_frame_timeout` router configuration options are no longer available, and their `ENGINE_WEBSOCKET_CLIENT_*` environment variables are no longer recognized. One option - `websocket_client_write_timeout` - keeps its name but now applies to a different side of the router. Review each section below before upgrading.
+
+
+### Renamed: server-side options
+
+These were always server-side despite the `websocket_client_*` name. They are renamed, and the old names are removed entirely.
+
+| Old YAML / env var | New YAML / env var |
+|-|-|
+| `engine.websocket_client_poll_timeout` / `ENGINE_WEBSOCKET_CLIENT_POLL_TIMEOUT` | `engine.websocket_server_poll_timeout` / `ENGINE_WEBSOCKET_SERVER_POLL_TIMEOUT` |
+| `engine.websocket_client_conn_buffer_size` / `ENGINE_WEBSOCKET_CLIENT_CONN_BUFFER_SIZE` | `engine.websocket_server_conn_buffer_size` / `ENGINE_WEBSOCKET_SERVER_CONN_BUFFER_SIZE` |
+
+### Split: `websocket_client_read_timeout`
+
+The old `websocket_client_read_timeout` served two purposes. Both are affected.
+
+- The server-side read timeout is now `engine.websocket_server_read_timeout` / `ENGINE_WEBSOCKET_SERVER_READ_TIMEOUT`. Default `5s`.
+- The upstream subscription client no longer has a generic read timeout. Use the finer-grained `websocket_client_ping_timeout` and `websocket_client_ack_timeout` below.
+
+### Scope change: `websocket_client_write_timeout`
+
+This option keeps its name but changes scope. Previously it governed the **server-side** write timeout (router writing to clients). It now governs the **upstream** write timeout (router writing to subgraphs), matching what its name implies.
+
+If you were setting this option in a previous release to tune server-side writes, set `engine.websocket_server_write_timeout` / `ENGINE_WEBSOCKET_SERVER_WRITE_TIMEOUT` to the same value on upgrade. Otherwise the server-side falls back to its default of `10s`.
+
+### New: `websocket_server_write_timeout`
+
+`engine.websocket_server_write_timeout` / `ENGINE_WEBSOCKET_SERVER_WRITE_TIMEOUT`. Server-side write timeout (router writing to clients). Default `10s`. Previously this behavior was governed by `websocket_client_write_timeout` (see above).
+
+### New: upstream client options
+
+These tune the router's outbound WebSocket connections to subgraphs.
+
+- `engine.websocket_client_ack_timeout` / `ENGINE_WEBSOCKET_CLIENT_ACK_TIMEOUT`. Maximum wait for a subgraph `connection_ack` after the router sends `connection_init`. Default `30s`, minimum `1s`.
+- `engine.websocket_client_read_limit` / `ENGINE_WEBSOCKET_CLIENT_READ_LIMIT`. Maximum size of a single incoming WebSocket message from a subgraph. Default `1MB`, minimum `1KB`.
+
+### Removed: `websocket_client_frame_timeout`
+
+`engine.websocket_client_frame_timeout` / `ENGINE_WEBSOCKET_CLIENT_FRAME_TIMEOUT` is removed with no replacement. Remove it from your config.
+
+### Unchanged
+
+These keep both their name and their scope:
+
+- `engine.websocket_client_ping_interval`
+- `engine.websocket_client_ping_timeout`
+- `engine.enable_net_poll` (applies to the server-side WebSocket handler only; has no effect on upstream subgraph connections)
+
+
+ **Subject to change.** `enable_net_poll`, `websocket_server_poll_timeout`, and `websocket_server_conn_buffer_size` may be removed or changed in a future release without a standard deprecation cycle. Avoid depending on them.
+
+
+### Before / after
+
+```yaml
+# Before
+engine:
+ enable_net_poll: true
+ websocket_client_poll_timeout: 1s
+ websocket_client_conn_buffer_size: 128
+ websocket_client_read_timeout: 5s
+ websocket_client_write_timeout: 10s
+ websocket_client_frame_timeout: 100ms
+ websocket_client_ping_interval: 15s
+ websocket_client_ping_timeout: 30s
+
+# After
+engine:
+ enable_net_poll: true
+ # Server-side WebSocket handler (router accepting clients)
+ websocket_server_read_timeout: 5s
+ websocket_server_write_timeout: 10s # previously the misnamed websocket_client_write_timeout
+ websocket_server_poll_timeout: 1s
+ websocket_server_conn_buffer_size: 128
+ # Upstream subscription client (router connecting to subgraphs)
+ websocket_client_write_timeout: 10s # same name, now actually upstream-only
+ websocket_client_ping_interval: 15s
+ websocket_client_ping_timeout: 30s
+ websocket_client_ack_timeout: 30s
+ websocket_client_read_limit: 1MB
+```
+
+See [Router Engine Configuration](/router/configuration#router-engine-configuration) for the full reference.
diff --git a/docs-website/router/subscriptions.mdx b/docs-website/router/subscriptions.mdx
index a687d7794e..c2901d8988 100644
--- a/docs-website/router/subscriptions.mdx
+++ b/docs-website/router/subscriptions.mdx
@@ -67,11 +67,11 @@ wscat -c wss://demo-router.fly.dev/graphql --subprotocol graphql-transport-ws
{"id":"6e6f71d0-2729-4db5-baee-8b6fc88721a7","type":"subscribe","payload":{"query":"subscription {\n currentTime {\n unixTime\n }\n}"}}
```
-### Using the "extensions" field
+### Using the extensions field
Cosmo Router allows you to leverage the "extensions" field of a GraphQL Request JSON to add additional meta information to the subscription message.
-This is useful, e.g. if you're trying to send an additional parameter, like a Bearer token with the initial payload. The feature in enabled by default, here's an example on how to use it:
+This is useful, e.g. if you're trying to send an additional parameter, like a Bearer token with the subscription. The feature is enabled by default, here's an example on how to use it:
```bash
# 1. Establish a secure WebSocket connection with our demo Router.
@@ -82,7 +82,13 @@ wscat -c wss://demo-router.fly.dev/graphql --subprotocol graphql-transport-ws
{"id":"1","type":"subscribe","payload":{"extensions":{"token":"asd"},"query":"subscription {\n currentTime {\n unixTime\n }\n}"}}
```
-When establishing a connection from the Router to the Subgraph, we will automatically include the "extensions" field from the initial payload. More specifically, the Router will include this "extensions" field in all (subsequent) Subgraph requests. E.g. if a Subscription depends on a nested entity field that will be resolved through a GraphQL Query, the extensions field will be included as well.
+The router forwards each subscribe message's `extensions` to the subgraph in the per-operation `subscribe.payload.extensions` field, where the `graphql-transport-ws` spec places them. Subsequent subgraph requests that resolve nested fields for the same subscription also include the extensions.
+
+The router does not merge subscribe-message `extensions` into `connection_init.payload`. The `connection_init.payload` carries only the downstream client's initial payload, unchanged.
+
+
+ Prior to the subscription overhaul release, the router merged subscribe-message extensions into `connection_init.payload.extensions`, overriding any `initial_payload` extensions. Subgraphs that read extensions from `connection_init` must now read them from `subscribe.payload.extensions`.
+
### Header forwarding
diff --git a/docs-website/router/subscriptions/router-configuration-for-subscriptions.mdx b/docs-website/router/subscriptions/router-configuration-for-subscriptions.mdx
index 3ede5fa716..a71e9d2824 100644
--- a/docs-website/router/subscriptions/router-configuration-for-subscriptions.mdx
+++ b/docs-website/router/subscriptions/router-configuration-for-subscriptions.mdx
@@ -74,3 +74,48 @@ npx wgc subgraph publish products --subscription-url "http://localhost:4001/subs
You can also use \`wgc subgraph update ...\` to update the Subscriptions protocol or URL for a specific Subgraph.
+## Tuning the upstream subscription client
+
+The router's upstream WebSocket client (the one that connects to subgraphs for subscriptions) is configured under the `engine` block. The defaults suit most deployments. The options below are listed with their YAML field and the matching environment variable.
+
+| Option | Env var | Default | Purpose |
+|-|-|-|-|
+| `websocket_client_write_timeout` | `ENGINE_WEBSOCKET_CLIENT_WRITE_TIMEOUT` | `10s` | The timeout for the websocket write of the WebSocket client implementation. |
+| `websocket_client_ping_interval` | `ENGINE_WEBSOCKET_CLIENT_PING_INTERVAL` | `15s` | The Websocket client ping interval to the subgraph. Defines how often the router will ping the subgraph to signal that the connection is still alive. |
+| `websocket_client_ping_timeout` | `ENGINE_WEBSOCKET_CLIENT_PING_TIMEOUT` | `30s` | The Websocket client ping timeout to the subgraph. Defines how long the router will wait for a ping response from the subgraph. |
+| `websocket_client_ack_timeout` | `ENGINE_WEBSOCKET_CLIENT_ACK_TIMEOUT` | `30s` | How long the router waits for `connection_ack` from a subgraph after sending `connection_init`. |
+| `websocket_client_read_limit` | `ENGINE_WEBSOCKET_CLIENT_READ_LIMIT` | `1MB` | Maximum size of a single incoming WebSocket message from a subgraph. |
+
+Example:
+
+```yaml
+version: "1"
+
+engine:
+ websocket_client_write_timeout: 10s
+ websocket_client_ping_interval: 15s
+ websocket_client_ping_timeout: 30s
+ websocket_client_ack_timeout: 30s
+ websocket_client_read_limit: 1MB
+```
+
+## Tuning the server-side WebSocket handler
+
+These options apply to the router's own WebSocket endpoint (the one clients connect to). They are separate from the upstream client options above.
+
+| Option | Env var | Default | Purpose |
+|-|-|-|-|
+| `websocket_server_read_timeout` | `ENGINE_WEBSOCKET_SERVER_READ_TIMEOUT` | `5s` | Read timeout for the server-side WebSocket handler. |
+| `websocket_server_write_timeout` | `ENGINE_WEBSOCKET_SERVER_WRITE_TIMEOUT` | `10s` | Write timeout for the server-side WebSocket handler. |
+| `websocket_server_poll_timeout` | `ENGINE_WEBSOCKET_SERVER_POLL_TIMEOUT` | `1s` | Timeout for the poll loop of the server-side WebSocket handler. |
+| `websocket_server_conn_buffer_size` | `ENGINE_WEBSOCKET_SERVER_CONN_BUFFER_SIZE` | `128` | Buffer size for the poll buffer of the server-side WebSocket handler. Determines how many connections can be handled in one loop. |
+| `enable_net_poll` | `ENGINE_ENABLE_NET_POLL` | `true` | Enables the more efficient poll implementation for the server-side WebSocket handler. Linux and macOS only. Has no effect on upstream subgraph connections. |
+
+
+ **Subject to change.** `enable_net_poll`, `websocket_server_poll_timeout`, and `websocket_server_conn_buffer_size` may be removed or changed in a future release without a standard deprecation cycle. Avoid depending on them.
+
+
+
+ If you are upgrading from an older release and your configuration sets `websocket_client_poll_timeout`, `websocket_client_read_timeout`, `websocket_client_conn_buffer_size`, or `websocket_client_frame_timeout`, see the [Subscriptions Overhaul migration guide](/router/subscriptions-migration).
+
+
diff --git a/router-tests/events/kafka_events_test.go b/router-tests/events/kafka_events_test.go
index 6ccc052ef6..9e284a42c9 100644
--- a/router-tests/events/kafka_events_test.go
+++ b/router-tests/events/kafka_events_test.go
@@ -274,7 +274,6 @@ func TestKafkaEvents(t *testing.T) {
testenv.AwaitChannelWithT(t, EventWaitTimeout, clientRunCh, func(t *testing.T, err error) {
require.NoError(t, err)
}, "unable to close client before timeout")
-
})
})
@@ -364,6 +363,67 @@ func TestKafkaEvents(t *testing.T) {
})
})
+ t.Run("subscribe async netPoll disabled", func(t *testing.T) {
+ t.Parallel()
+
+ topics := []string{"employeeUpdated", "employeeUpdatedTwo"}
+
+ testenv.Run(t, &testenv.Config{
+ RouterConfigJSONTemplate: testenv.ConfigWithEdfsKafkaJSONTemplate,
+ EnableKafka: true,
+ ModifyEngineExecutionConfiguration: func(engineExecutionConfiguration *config.EngineExecutionConfiguration) {
+ engineExecutionConfiguration.EnableNetPoll = false
+ engineExecutionConfiguration.WebSocketServerReadTimeout = time.Millisecond * 100
+ },
+ }, func(t *testing.T, xEnv *testenv.Environment) {
+ events.KafkaEnsureTopicExists(t, xEnv, EventWaitTimeout, topics...)
+
+ var subscriptionOne struct {
+ employeeUpdatedMyKafka struct {
+ ID float64 `graphql:"id"`
+ Details struct {
+ Forename string `graphql:"forename"`
+ Surname string `graphql:"surname"`
+ } `graphql:"details"`
+ } `graphql:"employeeUpdatedMyKafka(employeeID: 3)"`
+ }
+
+ surl := xEnv.GraphQLWebSocketSubscriptionURL()
+ client := graphql.NewSubscriptionClient(surl)
+
+ subscriptionOneArgsCh := make(chan kafkaSubscriptionArgs)
+ subscriptionOneID, err := client.Subscribe(&subscriptionOne, nil, func(dataValue []byte, errValue error) error {
+ subscriptionOneArgsCh <- kafkaSubscriptionArgs{
+ dataValue: dataValue,
+ errValue: errValue,
+ }
+ return nil
+ })
+ require.NoError(t, err)
+ require.NotEmpty(t, subscriptionOneID)
+
+ clientRunCh := make(chan error)
+ go func() {
+ clientRunCh <- client.Run()
+ }()
+
+ xEnv.WaitForSubscriptionCount(1, EventWaitTimeout)
+
+ events.ProduceKafkaMessage(t, xEnv, EventWaitTimeout, topics[0], `{"__typename":"Employee","id": 1,"update":{"name":"foo"}}`)
+
+ testenv.AwaitChannelWithT(t, EventWaitTimeout, subscriptionOneArgsCh, func(t *testing.T, args kafkaSubscriptionArgs) {
+ require.NoError(t, args.errValue)
+ require.JSONEq(t, `{"employeeUpdatedMyKafka":{"id":1,"details":{"forename":"Jens","surname":"Neuse"}}}`, string(args.dataValue))
+ })
+
+ require.NoError(t, client.Close())
+
+ testenv.AwaitChannelWithT(t, EventWaitTimeout, clientRunCh, func(t *testing.T, err error) {
+ require.NoError(t, err)
+ }, "unable to close client before timeout")
+ })
+ })
+
t.Run("multipart", func(t *testing.T) {
t.Parallel()
@@ -487,7 +547,8 @@ func TestKafkaEvents(t *testing.T) {
testenv.AwaitChannelWithT(t, EventWaitTimeout, responseCh, func(t *testing.T, response struct {
response *http.Response
err error
- }) {
+ },
+ ) {
require.NoError(t, response.err)
require.Equal(t, http.StatusOK, response.response.StatusCode)
reader := bufio.NewReader(response.response.Body)
@@ -548,7 +609,8 @@ func TestKafkaEvents(t *testing.T) {
testenv.AwaitChannelWithT(t, EventWaitTimeout, responseCh, func(t *testing.T, resp struct {
response *http.Response
err error
- }) {
+ },
+ ) {
require.NoError(t, resp.err)
require.Equal(t, http.StatusOK, resp.response.StatusCode)
defer resp.response.Body.Close()
@@ -1139,7 +1201,7 @@ func TestKafkaEvents(t *testing.T) {
EnableKafka: true,
ModifyEngineExecutionConfiguration: func(engineExecutionConfiguration *config.EngineExecutionConfiguration) {
engineExecutionConfiguration.EnableNetPoll = false
- engineExecutionConfiguration.WebSocketClientReadTimeout = time.Millisecond * 100
+ engineExecutionConfiguration.WebSocketServerReadTimeout = time.Millisecond * 100
},
}, func(t *testing.T, xEnv *testenv.Environment) {
events.KafkaEnsureTopicExists(t, xEnv, EventWaitTimeout, topics...)
diff --git a/router-tests/events/nats_events_test.go b/router-tests/events/nats_events_test.go
index 7b3f3822b5..926dc6bd26 100644
--- a/router-tests/events/nats_events_test.go
+++ b/router-tests/events/nats_events_test.go
@@ -30,9 +30,7 @@ import (
nodev1 "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/node/v1"
)
-var (
- _ configpoller.ConfigPoller = (*ConfigPollerMock)(nil)
-)
+var _ configpoller.ConfigPoller = (*ConfigPollerMock)(nil)
type ConfigPollerMock struct {
initConfig *nodev1.RouterConfig
@@ -154,10 +152,9 @@ func TestNatsEvents(t *testing.T) {
EnableNats: true,
ModifyEngineExecutionConfiguration: func(engineExecutionConfiguration *config.EngineExecutionConfiguration) {
engineExecutionConfiguration.EnableNetPoll = false
- engineExecutionConfiguration.WebSocketClientReadTimeout = time.Second
+ engineExecutionConfiguration.WebSocketServerReadTimeout = time.Second
},
}, func(t *testing.T, xEnv *testenv.Environment) {
-
var subscription struct {
employeeUpdated struct {
ID float64 `graphql:"id"`
@@ -247,7 +244,6 @@ func TestNatsEvents(t *testing.T) {
KeyFile: "../testdata/tls/key.pem",
},
}, func(t *testing.T, xEnv *testenv.Environment) {
-
subscribePayload := []byte(`{"query":"subscription { employeeUpdated(employeeID: 3) { id details { forename surname } } }"}`)
req := xEnv.MakeGraphQLMultipartRequest(http.MethodPost, bytes.NewReader(subscribePayload))
@@ -296,7 +292,6 @@ func TestNatsEvents(t *testing.T) {
core.WithSubscriptionHeartbeatInterval(heartbeatInterval),
},
}, func(t *testing.T, xEnv *testenv.Environment) {
-
subscribePayload := []byte(`{"query":"subscription { employeeUpdated(employeeID: 3) { id details { forename surname } } }"}`)
client := &http.Client{}
@@ -321,7 +316,6 @@ func TestNatsEvents(t *testing.T) {
})
t.Run("subscribe with closing channel", func(t *testing.T) {
-
testenv.Run(t, &testenv.Config{
RouterConfigJSONTemplate: testenv.ConfigWithEdfsNatsJSONTemplate,
EnableNats: true,
@@ -397,7 +391,6 @@ func TestNatsEvents(t *testing.T) {
},
EnableNats: true,
}, func(t *testing.T, xEnv *testenv.Environment) {
-
subscribePayload := []byte(`{"query":"subscription { countFor(count: 0) }"}`)
client := http.Client{}
@@ -429,7 +422,6 @@ func TestNatsEvents(t *testing.T) {
RouterConfigJSONTemplate: testenv.ConfigWithEdfsNatsJSONTemplate,
EnableNats: true,
}, func(t *testing.T, xEnv *testenv.Environment) {
-
subscribePayload := []byte(`{"query":"subscription { countFor(count: 3) }"}`)
client := http.Client{}
req := xEnv.MakeGraphQLMultipartRequest(http.MethodPost, bytes.NewReader(subscribePayload))
@@ -487,7 +479,6 @@ func TestNatsEvents(t *testing.T) {
},
EnableNats: true,
}, func(t *testing.T, xEnv *testenv.Environment) {
-
subscribePayload := []byte(`{"query":"subscription { countFor(count: 0) }"}`)
client := http.Client{}
@@ -526,7 +517,6 @@ func TestNatsEvents(t *testing.T) {
},
EnableNats: true,
}, func(t *testing.T, xEnv *testenv.Environment) {
-
subscribePayload := []byte(`{"query":"subscription { countFor(count: 3) }"}`)
client := http.Client{}
@@ -559,7 +549,6 @@ func TestNatsEvents(t *testing.T) {
RouterConfigJSONTemplate: testenv.ConfigWithEdfsNatsJSONTemplate,
EnableNats: true,
}, func(t *testing.T, xEnv *testenv.Environment) {
-
subscribePayload := []byte(`{"query":"subscription { employeeUpdated(employeeID: 3) { id details { forename surname } } }"}`)
client := http.Client{}
@@ -574,7 +563,7 @@ func TestNatsEvents(t *testing.T) {
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Cache-Control", "no-cache")
- var clientDoCh = make(chan struct {
+ clientDoCh := make(chan struct {
resp *http.Response
err error
})
@@ -601,11 +590,11 @@ func TestNatsEvents(t *testing.T) {
testenv.AwaitChannelWithT(t, EventWaitTimeout, clientDoCh, func(t *testing.T, clientDo struct {
resp *http.Response
err error
- }) {
+ },
+ ) {
require.NoError(t, clientDo.err)
require.Equal(t, http.StatusOK, clientDo.resp.StatusCode)
resp = clientDo.resp
-
})
defer resp.Body.Close()
reader := bufio.NewReader(resp.Body)
@@ -639,7 +628,6 @@ func TestNatsEvents(t *testing.T) {
RouterConfigJSONTemplate: testenv.ConfigWithEdfsNatsJSONTemplate,
EnableNats: true,
}, func(t *testing.T, xEnv *testenv.Environment) {
-
subscribePayload := []byte(`{"query":"subscription { employeeUpdated(employeeID: 3) { id details { forename surname } } }"}`)
client := http.Client{}
@@ -651,7 +639,7 @@ func TestNatsEvents(t *testing.T) {
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Cache-Control", "no-cache")
- var clientDoCh = make(chan struct {
+ clientDoCh := make(chan struct {
resp *http.Response
err error
})
@@ -680,7 +668,8 @@ func TestNatsEvents(t *testing.T) {
testenv.AwaitChannelWithT(t, EventWaitTimeout, clientDoCh, func(t *testing.T, clientDo struct {
resp *http.Response
err error
- }) {
+ },
+ ) {
require.NoError(t, clientDo.err)
require.Equal(t, http.StatusOK, clientDo.resp.StatusCode)
resp = clientDo.resp
@@ -777,7 +766,6 @@ func TestNatsEvents(t *testing.T) {
RouterConfigJSONTemplate: testenv.ConfigWithEdfsNatsJSONTemplate,
EnableNats: true,
}, func(t *testing.T, xEnv *testenv.Environment) {
-
firstSubscribePayload := []byte(`{"query":"subscription { employeeUpdated(employeeID: 3) { id details { forename surname } }}"}`)
client := http.Client{}
@@ -789,7 +777,7 @@ func TestNatsEvents(t *testing.T) {
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Cache-Control", "no-cache")
- var clientDoCh = make(chan struct {
+ clientDoCh := make(chan struct {
resp *http.Response
err error
})
@@ -815,7 +803,8 @@ func TestNatsEvents(t *testing.T) {
testenv.AwaitChannelWithT(t, EventWaitTimeout, clientDoCh, func(t *testing.T, clientDo struct {
resp *http.Response
err error
- }) {
+ },
+ ) {
require.NoError(t, clientDo.err)
require.Equal(t, http.StatusOK, clientDo.resp.StatusCode)
resp = clientDo.resp
@@ -850,7 +839,6 @@ func TestNatsEvents(t *testing.T) {
RouterConfigJSONTemplate: testenv.ConfigWithEdfsNatsJSONTemplate,
EnableNats: true,
}, func(t *testing.T, xEnv *testenv.Environment) {
-
firstSub, err := xEnv.NatsConnectionDefault.Subscribe(xEnv.GetPubSubName("getEmployee.3"), func(msg *nats.Msg) {
err := msg.Respond([]byte(`{"id": 3, "__typename": "Employee"}`))
require.NoError(t, err)
@@ -971,7 +959,7 @@ func TestNatsEvents(t *testing.T) {
RouterConfigJSONTemplate: testenv.ConfigWithEdfsNatsJSONTemplate,
EnableNats: true,
ModifyEngineExecutionConfiguration: func(engineExecutionConfiguration *config.EngineExecutionConfiguration) {
- engineExecutionConfiguration.WebSocketClientReadTimeout = time.Second
+ engineExecutionConfiguration.WebSocketServerReadTimeout = time.Second
},
}, func(t *testing.T, xEnv *testenv.Environment) {
type subscriptionPayload struct {
@@ -1216,7 +1204,7 @@ func TestNatsEvents(t *testing.T) {
})
require.NoError(t, err)
- var clientRunCh = make(chan error)
+ clientRunCh := make(chan error)
go func() {
clientRunCh <- client.Run()
}()
@@ -1438,7 +1426,7 @@ func TestNatsEvents(t *testing.T) {
RouterConfigJSONTemplate: testenv.ConfigWithEdfsNatsJSONTemplate,
EnableNats: true,
ModifyEngineExecutionConfiguration: func(engineExecutionConfiguration *config.EngineExecutionConfiguration) {
- engineExecutionConfiguration.WebSocketClientReadTimeout = time.Second
+ engineExecutionConfiguration.WebSocketServerReadTimeout = time.Second
},
}, func(t *testing.T, xEnv *testenv.Environment) {
type subscriptionPayload struct {
@@ -1866,7 +1854,6 @@ func TestFlakyNatsEvents(t *testing.T) {
RouterConfigJSONTemplate: testenv.ConfigWithEdfsNatsJSONTemplate,
EnableNats: true,
}, func(t *testing.T, xEnv *testenv.Environment) {
-
subscribePayload := []byte(`{"query":"subscription { filteredEmployeeUpdated(id: 1) { id details { forename surname } } }"}`)
// Use a context with timeout to prevent SSE reads from blocking
@@ -1883,7 +1870,7 @@ func TestFlakyNatsEvents(t *testing.T) {
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Cache-Control", "no-cache")
- var clientDoCh = make(chan struct {
+ clientDoCh := make(chan struct {
resp *http.Response
err error
})
@@ -1906,7 +1893,8 @@ func TestFlakyNatsEvents(t *testing.T) {
testenv.AwaitChannelWithT(t, EventWaitTimeout, clientDoCh, func(t *testing.T, clientDo struct {
resp *http.Response
err error
- }) {
+ },
+ ) {
resp = clientDo.resp
require.NoError(t, clientDo.err)
})
@@ -1963,7 +1951,7 @@ func TestFlakyNatsEvents(t *testing.T) {
RouterConfigJSONTemplate: testenv.ConfigWithEdfsNatsJSONTemplate,
EnableNats: true,
ModifyEngineExecutionConfiguration: func(engineExecutionConfiguration *config.EngineExecutionConfiguration) {
- engineExecutionConfiguration.WebSocketClientReadTimeout = time.Second
+ engineExecutionConfiguration.WebSocketServerReadTimeout = time.Second
},
}, func(t *testing.T, xEnv *testenv.Environment) {
type subscriptionPayload struct {
diff --git a/router-tests/events/redis_events_test.go b/router-tests/events/redis_events_test.go
index a3a8eae2e5..d48bed4e43 100644
--- a/router-tests/events/redis_events_test.go
+++ b/router-tests/events/redis_events_test.go
@@ -211,7 +211,6 @@ func TestRedisEvents(t *testing.T) {
RouterConfigJSONTemplate: testenv.ConfigWithEdfsRedisJSONTemplate,
EnableRedis: true,
}, func(t *testing.T, xEnv *testenv.Environment) {
-
var subscriptionOne struct {
employeeUpdates struct {
ID float64 `graphql:"id"`
@@ -294,7 +293,6 @@ func TestRedisEvents(t *testing.T) {
RouterConfigJSONTemplate: testenv.ConfigWithEdfsRedisJSONTemplate,
EnableRedis: true,
}, func(t *testing.T, xEnv *testenv.Environment) {
-
var subscriptionOne struct {
employeeUpdates struct {
ID float64 `graphql:"id"`
@@ -398,7 +396,7 @@ func TestRedisEvents(t *testing.T) {
EnableRedis: true,
ModifyEngineExecutionConfiguration: func(engineExecutionConfiguration *config.EngineExecutionConfiguration) {
engineExecutionConfiguration.EnableNetPoll = false
- engineExecutionConfiguration.WebSocketClientReadTimeout = time.Millisecond * 100
+ engineExecutionConfiguration.WebSocketServerReadTimeout = time.Millisecond * 100
},
}, func(t *testing.T, xEnv *testenv.Environment) {
var subscriptionOne struct {
@@ -541,7 +539,6 @@ func TestRedisEvents(t *testing.T) {
RouterConfigJSONTemplate: testenv.ConfigWithEdfsRedisJSONTemplate,
EnableRedis: true,
}, func(t *testing.T, xEnv *testenv.Environment) {
-
subscribePayload := []byte(`{"query":"subscription { employeeUpdates { id details { forename surname } }}"}`)
client := http.Client{
Timeout: time.Second * 30,
@@ -653,7 +650,6 @@ func TestRedisEvents(t *testing.T) {
RouterConfigJSONTemplate: testenv.ConfigWithEdfsRedisJSONTemplate,
EnableRedis: true,
}, func(t *testing.T, xEnv *testenv.Environment) {
-
type subscriptionPayload struct {
Data struct {
FilteredEmployeeUpdatedMyRedis struct {
@@ -851,7 +847,6 @@ func TestRedisEvents(t *testing.T) {
RouterConfigJSONTemplate: testenv.ConfigWithEdfsRedisJSONTemplate,
EnableRedis: true,
}, func(t *testing.T, xEnv *testenv.Environment) {
-
var subscriptionOne struct {
employeeUpdates struct {
ID int `graphql:"id"`
@@ -1049,5 +1044,4 @@ func TestRedisClusterEvents(t *testing.T) {
}
})
})
-
}
diff --git a/router-tests/go.mod b/router-tests/go.mod
index be48cbff5d..862856a1ae 100644
--- a/router-tests/go.mod
+++ b/router-tests/go.mod
@@ -25,11 +25,12 @@ require (
github.com/twmb/franz-go v1.16.1
github.com/twmb/franz-go/pkg/kadm v1.11.0
github.com/wundergraph/astjson v1.1.0
- github.com/wundergraph/cosmo/demo v0.0.0-20260213130455-6e3277e7b850
+ github.com/wundergraph/cosmo/demo v0.0.0-20260323091151-a7de617c31d0
github.com/wundergraph/cosmo/demo/pkg/subgraphs/projects v0.0.0-20250715110703-10f2e5f9c79e
- github.com/wundergraph/cosmo/router v0.0.0-20260318232543-0e5fa811a191
+ github.com/wundergraph/cosmo/router v0.0.0-20260323091151-a7de617c31d0
github.com/wundergraph/cosmo/router-plugin v0.0.0-20250808194725-de123ba1c65e
- github.com/wundergraph/graphql-go-tools/v2 v2.0.0
+ github.com/wundergraph/cosmo/speedtrap v0.0.0-00010101000000-000000000000
+ github.com/wundergraph/graphql-go-tools/v2 v2.1.0
go.opentelemetry.io/otel v1.39.0
go.opentelemetry.io/otel/sdk v1.39.0
go.opentelemetry.io/otel/sdk/metric v1.39.0
@@ -60,7 +61,7 @@ require (
github.com/cep21/circuit/v4 v4.0.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cilium/ebpf v0.16.0 // indirect
- github.com/coder/websocket v1.8.13 // indirect
+ github.com/coder/websocket v1.8.14 // indirect
github.com/containerd/cgroups/v3 v3.0.2 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
@@ -102,6 +103,7 @@ require (
github.com/invopop/jsonschema v0.13.0 // indirect
github.com/jensneuse/abstractlogger v0.0.4 // indirect
github.com/jensneuse/byte-template v0.0.0-20231025215717-69252eb3ed56 // indirect
+ github.com/kinbiko/jsonassert v1.2.0 // indirect
github.com/kingledion/go-tools v0.6.0 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
@@ -132,7 +134,7 @@ require (
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/r3labs/sse/v2 v2.8.1 // indirect
- github.com/rs/xid v1.5.0 // indirect
+ github.com/rs/xid v1.6.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect
github.com/segmentio/asm v1.1.3 // indirect
@@ -215,5 +217,6 @@ replace (
github.com/wundergraph/cosmo/demo/pkg/subgraphs/projects => ../demo/pkg/subgraphs/projects
github.com/wundergraph/cosmo/router => ../router
github.com/wundergraph/cosmo/router-plugin => ../router-plugin
-// github.com/wundergraph/graphql-go-tools/v2 => ../../graphql-go-tools/v2
+ github.com/wundergraph/cosmo/speedtrap => ../speedtrap
+//github.com/wundergraph/graphql-go-tools/v2 => ../../graphql-go-tools/v2
)
diff --git a/router-tests/go.sum b/router-tests/go.sum
index 583b1c76c3..28e214572e 100644
--- a/router-tests/go.sum
+++ b/router-tests/go.sum
@@ -53,8 +53,8 @@ github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok=
github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE=
github.com/cloudflare/backoff v0.0.0-20240920015135-e46b80a3a7d0 h1:pRcxfaAlK0vR6nOeQs7eAEvjJzdGXl8+KaBlcvpQTyQ=
github.com/cloudflare/backoff v0.0.0-20240920015135-e46b80a3a7d0/go.mod h1:rzgs2ZOiguV6/NpiDgADjRLPNyZlApIWxKpkT+X8SdY=
-github.com/coder/websocket v1.8.13 h1:f3QZdXy7uGVz+4uCJy2nTZyM0yTBj8yANEHhqlXZ9FE=
-github.com/coder/websocket v1.8.13/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs=
+github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g=
+github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg=
github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0=
github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE=
github.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRccTampEyKpjpOnS3CyiV1Ebr8=
@@ -184,6 +184,8 @@ github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtL
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/jsimonetti/rtnetlink/v2 v2.0.1 h1:xda7qaHDSVOsADNouv7ukSuicKZO7GgVUCXxpaIEIlM=
github.com/jsimonetti/rtnetlink/v2 v2.0.1/go.mod h1:7MoNYNbb3UaDHtF8udiJo/RH6VsTKP1pqKLUTVCvToE=
+github.com/kinbiko/jsonassert v1.2.0 h1:+/JthIVXdIrThrOtSN9ry0mNtWKXMWuvxR0nU7gQ+tI=
+github.com/kinbiko/jsonassert v1.2.0/go.mod h1:pCc3uudOt+lVAbkji9O0uw8MSVt4s+1ZJ0y8Ux2F1Og=
github.com/kingledion/go-tools v0.6.0 h1:y8C/4mWoHgLkO45dB+Y/j0o4Y4WUB5lDTAcMPMtFpTg=
github.com/kingledion/go-tools v0.6.0/go.mod h1:qcDJQxBui/H/hterGb90GMlLs9Yi7QrwaJL8OGdbsms=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
@@ -283,8 +285,8 @@ github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRl
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
-github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
-github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
+github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
+github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=
@@ -365,8 +367,8 @@ github.com/wundergraph/astjson v1.1.0 h1:xORDosrZ87zQFJwNGe/HIHXqzpdHOFmqWgykCLV
github.com/wundergraph/astjson v1.1.0/go.mod h1:h12D/dxxnedtLzsKyBLK7/Oe4TAoGpRVC9nDpDrZSWw=
github.com/wundergraph/go-arena v1.1.0 h1:9+wSRkJAkA2vbYHp6s8tEGhPViRGQNGXqPHT0QzhdIc=
github.com/wundergraph/go-arena v1.1.0/go.mod h1:ROOysEHWJjLQ8FSfNxZCziagb7Qw2nXY3/vgKRh7eWw=
-github.com/wundergraph/graphql-go-tools/v2 v2.0.0 h1:F9hXgakaKxQen04cunNP2bdEl19GH/YGn7tISjeUf2M=
-github.com/wundergraph/graphql-go-tools/v2 v2.0.0/go.mod h1:HjTAO/cuICpu31IfHY9qmSPygx6Gza7Wt9hTSReTI+A=
+github.com/wundergraph/graphql-go-tools/v2 v2.1.0 h1:V1MU/uo+oc5b+aIh3SpCr0rJgLHuhonWg2fhN1sfMdY=
+github.com/wundergraph/graphql-go-tools/v2 v2.1.0/go.mod h1:UG/grnPEHumtD82H8FC+3dokiCGK8GF0b5IJc00lSbM=
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342 h1:FnBeRrxr7OU4VvAzt5X7s6266i6cSVkkFPS0TuXWbIg=
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
diff --git a/router-tests/modules/start_subscription_test.go b/router-tests/modules/start_subscription_test.go
index 24500c896f..470b798360 100644
--- a/router-tests/modules/start_subscription_test.go
+++ b/router-tests/modules/start_subscription_test.go
@@ -90,7 +90,6 @@ func TestStartSubscriptionHook(t *testing.T) {
require.NoError(t, client.Close())
testenv.AwaitChannelWithT(t, time.Second*10, clientRunCh, func(t *testing.T, err error) {
require.NoError(t, err)
-
}, "unable to close client before timeout")
assert.Equal(t, int32(1), customModule.HookCallCount.Load())
@@ -183,7 +182,6 @@ func TestStartSubscriptionHook(t *testing.T) {
require.NoError(t, client.Close())
testenv.AwaitChannelWithT(t, time.Second*10, clientRunCh, func(t *testing.T, err error) {
require.NoError(t, err)
-
}, "unable to close client before timeout")
assert.Equal(t, int32(1), customModule.HookCallCount.Load())
@@ -268,17 +266,17 @@ func TestStartSubscriptionHook(t *testing.T) {
}, "StartSubscription callback was not invoked")
xEnv.WaitForSubscriptionCount(0, time.Second*10)
- testenv.AwaitChannelWithT(t, time.Second*10, clientRunCh, func(t *testing.T, err error) {
- require.NoError(t, err)
-
- }, "unable to close client before timeout")
+ testenv.AwaitChannelWithT(t, time.Second*10, subscriptionArgsCh, func(t *testing.T, args kafkaSubscriptionArgs) {
+ require.Error(t, args.errValue)
+ require.Empty(t, args.dataValue)
+ }, "subscription error was not delivered to handler")
assert.Equal(t, int32(1), customModule.HookCallCount.Load())
- require.Len(t, subscriptionArgsCh, 1)
- subscriptionArgs := <-subscriptionArgsCh
- require.Error(t, subscriptionArgs.errValue)
- require.Empty(t, subscriptionArgs.dataValue)
+ require.NoError(t, client.Close())
+ testenv.AwaitChannelWithT(t, time.Second*10, clientRunCh, func(t *testing.T, err error) {
+ require.NoError(t, err)
+ }, "unable to close client before timeout")
})
})
@@ -381,9 +379,11 @@ func TestStartSubscriptionHook(t *testing.T) {
require.NoError(t, client.Close())
testenv.AwaitChannelWithT(t, time.Second*10, clientRunCh, func(t *testing.T, err error) {
require.NoError(t, err)
-
}, "unable to close client before timeout")
+ require.Eventually(t, func() bool {
+ return customModule.HookCallCount.Load() >= 2
+ }, time.Second*10, time.Millisecond*50)
assert.Equal(t, int32(2), customModule.HookCallCount.Load())
t.Cleanup(func() {
require.Len(t, subscriptionOneArgsCh, 0)
@@ -473,7 +473,6 @@ func TestStartSubscriptionHook(t *testing.T) {
require.NoError(t, client.Close())
testenv.AwaitChannelWithT(t, time.Second*10, clientRunCh, func(t *testing.T, err error) {
require.NoError(t, err)
-
}, "unable to close client before timeout")
assert.Equal(t, int32(1), customModule.HookCallCount.Load())
@@ -511,7 +510,6 @@ func TestStartSubscriptionHook(t *testing.T) {
LogLevel: zapcore.InfoLevel,
},
}, func(t *testing.T, xEnv *testenv.Environment) {
-
var subscriptionCountEmp struct {
CountEmp int `graphql:"countEmp(max: $max, intervalMilliseconds: $interval)"`
}
@@ -584,7 +582,6 @@ func TestStartSubscriptionHook(t *testing.T) {
LogLevel: zapcore.InfoLevel,
},
}, func(t *testing.T, xEnv *testenv.Environment) {
-
var subscriptionCountEmp struct {
CountEmp int `graphql:"countEmp(max: $max, intervalMilliseconds: $interval)"`
}
@@ -594,7 +591,7 @@ func TestStartSubscriptionHook(t *testing.T) {
vars := map[string]interface{}{
"max": 0,
- "interval": 0,
+ "interval": 500,
}
type subscriptionArgs struct {
@@ -632,7 +629,6 @@ func TestStartSubscriptionHook(t *testing.T) {
require.NoError(t, client.Close())
testenv.AwaitChannelWithT(t, time.Second*10, clientRunCh, func(t *testing.T, err error) {
require.NoError(t, err)
-
}, "unable to close client before timeout")
assert.Equal(t, int32(1), customModule.HookCallCount.Load())
@@ -713,13 +709,14 @@ func TestStartSubscriptionHook(t *testing.T) {
require.Empty(t, args.dataValue)
})
- testenv.AwaitChannelWithT(t, time.Second*10, clientRunCh, func(t *testing.T, err error) {
- require.NoError(t, err)
- }, "unable to close client before timeout")
-
require.Empty(t, originResponseCalled)
assert.Equal(t, int32(1), customModule.HookCallCount.Load())
+
+ require.NoError(t, client.Close())
+ testenv.AwaitChannelWithT(t, time.Second*10, clientRunCh, func(t *testing.T, err error) {
+ require.NoError(t, err)
+ }, "unable to close client before timeout")
})
})
}
diff --git a/router-tests/modules/stream_receive_test.go b/router-tests/modules/stream_receive_test.go
index 30fb26f490..b11fe9fb4e 100644
--- a/router-tests/modules/stream_receive_test.go
+++ b/router-tests/modules/stream_receive_test.go
@@ -635,15 +635,15 @@ func TestReceiveHook(t *testing.T) {
events.ProduceKafkaMessage(t, xEnv, Timeout, topics[0], `{"__typename":"Employee","id": 1,"update":{"name":"foo"}}`)
- // Wait for server to close the subscription connection
+ // Wait for server to close the subscription
xEnv.WaitForSubscriptionCount(0, Timeout)
+ xEnv.WaitForTriggerCount(0, Timeout)
- // Verify that client.Run() completed when server closed the connection
+ // Errors are non-terminal to the connection, so explicitly close
+ require.NoError(t, client.Close())
testenv.AwaitChannelWithT(t, Timeout, clientRunCh, func(t *testing.T, err error) {
require.NoError(t, err)
- }, "client should have completed when server closed connection")
-
- xEnv.WaitForTriggerCount(0, Timeout)
+ }, "client should have completed after explicit close")
})
})
diff --git a/router-tests/observability/prometheus_stream_metrics_test.go b/router-tests/observability/prometheus_stream_metrics_test.go
index 6c6d08b96c..0404d35a17 100644
--- a/router-tests/observability/prometheus_stream_metrics_test.go
+++ b/router-tests/observability/prometheus_stream_metrics_test.go
@@ -264,7 +264,7 @@ func TestFlakyEventMetrics(t *testing.T) {
PrometheusRegistry: promRegistry,
RouterConfigJSONTemplate: testenv.ConfigWithEdfsNatsJSONTemplate,
EnableNats: true,
- ModifyEngineExecutionConfiguration: func(ec *config.EngineExecutionConfiguration) { ec.WebSocketClientReadTimeout = time.Second },
+ ModifyEngineExecutionConfiguration: func(ec *config.EngineExecutionConfiguration) { ec.WebSocketServerReadTimeout = time.Second },
MetricOptions: testenv.MetricOptions{EnablePrometheusStreamMetrics: true},
}, func(t *testing.T, xEnv *testenv.Environment) {
var subscriptionOne struct {
diff --git a/router-tests/operations/automatic_persisted_queries_test.go b/router-tests/operations/automatic_persisted_queries_test.go
index 5b9f4f0685..24d19b0d31 100644
--- a/router-tests/operations/automatic_persisted_queries_test.go
+++ b/router-tests/operations/automatic_persisted_queries_test.go
@@ -225,7 +225,9 @@ func TestAutomaticPersistedQueries(t *testing.T) {
URLs: []string{redisUrl},
ID: "redis",
},
- }})},
+ },
+ }),
+ },
ApqConfig: config.AutomaticPersistedQueriesConfig{
Enabled: true,
Storage: config.AutomaticPersistedQueriesStorageConfig{
@@ -258,7 +260,9 @@ func TestAutomaticPersistedQueries(t *testing.T) {
URLs: []string{redisUrl},
ID: "redis",
},
- }})},
+ },
+ }),
+ },
ApqConfig: config.AutomaticPersistedQueriesConfig{
Enabled: true,
Storage: config.AutomaticPersistedQueriesStorageConfig{
@@ -315,7 +319,9 @@ func TestAutomaticPersistedQueries(t *testing.T) {
URLs: []string{redisUrl},
ID: "redis",
},
- }})},
+ },
+ }),
+ },
ApqConfig: config.AutomaticPersistedQueriesConfig{
Enabled: true,
Cache: config.AutomaticPersistedQueriesCacheConfig{
@@ -364,7 +370,9 @@ func TestAutomaticPersistedQueries(t *testing.T) {
URLs: []string{redisUrl},
ID: "redis",
},
- }})},
+ },
+ }),
+ },
ApqConfig: config.AutomaticPersistedQueriesConfig{
Enabled: true,
Cache: config.AutomaticPersistedQueriesCacheConfig{
@@ -405,7 +413,6 @@ func TestAutomaticPersistedQueries(t *testing.T) {
})
t.Run("works with cluster mode", func(t *testing.T) {
-
if _, set := os.LookupEnv("SKIP_REDIS_CLUSTER_TESTS"); set {
t.Skip("skipping redis cluster tests")
}
@@ -434,7 +441,9 @@ func TestAutomaticPersistedQueries(t *testing.T) {
URLs: clusterUrls,
ID: "redis",
},
- }})},
+ },
+ }),
+ },
ApqConfig: config.AutomaticPersistedQueriesConfig{
Enabled: true,
Storage: config.AutomaticPersistedQueriesStorageConfig{
@@ -480,7 +489,6 @@ func TestAPQNormalizationCacheWithMultiOperationDocument(t *testing.T) {
t.Parallel()
t.Run("Should identify correct document after removing unused operations during normalization", func(t *testing.T) {
-
document := `query A {
a: employee(id: 1) {
id
@@ -557,7 +565,6 @@ query B ($id: Int!) {
require.Equal(t, `{"data":{"b":{"id":3,"details":{"pets":[{"name":"Snappy"}]}}}}`, res.Body)
})
})
-
}
func BenchmarkAutomaticPersistedQueriesCacheEnabled(b *testing.B) {
diff --git a/router-tests/operations/introspection_test.go b/router-tests/operations/introspection_test.go
index 40b59fb2a2..b5ad908f6b 100644
--- a/router-tests/operations/introspection_test.go
+++ b/router-tests/operations/introspection_test.go
@@ -151,5 +151,4 @@ func TestIntrospection(t *testing.T) {
g.Assert(t, "feature-graph-schema", body.Bytes())
})
})
-
}
diff --git a/router-tests/operations/testdata/introspection/base-graph-schema.json b/router-tests/operations/testdata/introspection/base-graph-schema.json
index 6290a53116..db8591e8f9 100644
--- a/router-tests/operations/testdata/introspection/base-graph-schema.json
+++ b/router-tests/operations/testdata/introspection/base-graph-schema.json
@@ -1675,9 +1675,46 @@
"description": "",
"args": [],
"type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "metadata",
+ "description": "Returns a stream with the values of the WS initial payload and subscribe extensions",
+ "args": [
+ {
+ "name": "repeat",
+ "description": "",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "defaultValue": "1",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "SubscribeMetadata",
+ "ofType": null
+ }
},
"isDeprecated": false,
"deprecationReason": null
@@ -4086,6 +4123,53 @@
},
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "extensions",
+ "description": "",
+ "args": [],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Map",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": [],
+ "interfaces": [],
+ "enumValues": null,
+ "possibleTypes": []
+ },
+ {
+ "kind": "OBJECT",
+ "name": "SubscribeMetadata",
+ "description": "",
+ "fields": [
+ {
+ "name": "initialPayload",
+ "description": "",
+ "args": [],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Map",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "subscribeExtensions",
+ "description": "",
+ "args": [],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Map",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"inputFields": [],
diff --git a/router-tests/operations/testdata/introspection/feature-graph-schema.json b/router-tests/operations/testdata/introspection/feature-graph-schema.json
index ba777cc91f..db932d87ec 100644
--- a/router-tests/operations/testdata/introspection/feature-graph-schema.json
+++ b/router-tests/operations/testdata/introspection/feature-graph-schema.json
@@ -1634,9 +1634,46 @@
"description": "",
"args": [],
"type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "metadata",
+ "description": "Returns a stream with the values of the WS initial payload and subscribe extensions",
+ "args": [
+ {
+ "name": "repeat",
+ "description": "",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "defaultValue": "1",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "SubscribeMetadata",
+ "ofType": null
+ }
},
"isDeprecated": false,
"deprecationReason": null
@@ -4029,6 +4066,53 @@
},
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "extensions",
+ "description": "",
+ "args": [],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Map",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": [],
+ "interfaces": [],
+ "enumValues": null,
+ "possibleTypes": []
+ },
+ {
+ "kind": "OBJECT",
+ "name": "SubscribeMetadata",
+ "description": "",
+ "fields": [
+ {
+ "name": "initialPayload",
+ "description": "",
+ "args": [],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Map",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "subscribeExtensions",
+ "description": "",
+ "args": [],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Map",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"inputFields": [],
diff --git a/router-tests/protocol/cors_test.go b/router-tests/protocol/cors_test.go
index 5846fdffe8..24f600936e 100644
--- a/router-tests/protocol/cors_test.go
+++ b/router-tests/protocol/cors_test.go
@@ -20,7 +20,7 @@ func TestCors(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(cfg *config.EngineExecutionConfiguration) {
- cfg.WebSocketClientReadTimeout = time.Millisecond * 10
+ cfg.WebSocketServerReadTimeout = time.Millisecond * 10
},
RouterOptions: []core.Option{
core.WithCors(&cors.Config{
diff --git a/router-tests/protocol/headers_test.go b/router-tests/protocol/headers_test.go
index 939644f8e5..2274f8f570 100644
--- a/router-tests/protocol/headers_test.go
+++ b/router-tests/protocol/headers_test.go
@@ -60,7 +60,7 @@ func TestForwardHeaders(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(cfg *config.EngineExecutionConfiguration) {
- cfg.WebSocketClientReadTimeout = time.Millisecond * 10
+ cfg.WebSocketServerReadTimeout = time.Millisecond * 10
},
RouterOptions: []core.Option{
core.WithHeaderRules(config.HeaderRules{
@@ -89,7 +89,6 @@ func TestForwardHeaders(t *testing.T) {
Query: `query { headerValue(name:"Cookie") }`,
})
require.Equal(t, `{"data":{"headerValue":"allowed=allowed; allowed_as_well=allowed"}}`, res.Body)
-
})
})
@@ -98,7 +97,7 @@ func TestForwardHeaders(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(cfg *config.EngineExecutionConfiguration) {
- cfg.WebSocketClientReadTimeout = time.Millisecond * 10
+ cfg.WebSocketServerReadTimeout = time.Millisecond * 10
},
RouterOptions: []core.Option{
core.WithHeaderRules(config.HeaderRules{
@@ -128,7 +127,6 @@ func TestForwardHeaders(t *testing.T) {
Query: `query { headerValue(name:"Cookie") }`,
})
require.Equal(t, `{"data":{"headerValue":"allowed=allowed; allowed_as_well=allowed"}}`, res.Body)
-
})
})
@@ -137,7 +135,7 @@ func TestForwardHeaders(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(cfg *config.EngineExecutionConfiguration) {
- cfg.WebSocketClientReadTimeout = time.Millisecond * 10
+ cfg.WebSocketServerReadTimeout = time.Millisecond * 10
},
RouterOptions: []core.Option{
core.WithHeaderRules(config.HeaderRules{
@@ -167,7 +165,6 @@ func TestForwardHeaders(t *testing.T) {
Query: `query { headerValue(name:"Cookie") }`,
})
require.Equal(t, `{"data":{"headerValue":"allowed=allowed"}}`, res.Body)
-
})
})
@@ -184,7 +181,7 @@ func TestForwardHeaders(t *testing.T) {
}
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(cfg *config.EngineExecutionConfiguration) {
- cfg.WebSocketClientReadTimeout = time.Millisecond * 10
+ cfg.WebSocketServerReadTimeout = time.Millisecond * 10
},
RouterOptions: []core.Option{
core.WithHeaderRules(headerRules),
@@ -200,7 +197,6 @@ func TestForwardHeaders(t *testing.T) {
Query: `query { headerValue(name:"` + headerName + `") }`,
})
require.Equal(t, `{"data":{"headerValue":"`+headerValue+`"}}`, res.Body)
-
})
}
})
@@ -219,7 +215,12 @@ func TestForwardHeaders(t *testing.T) {
Name: headerName,
ValueFrom: &config.CustomDynamicAttribute{
ContextField: contextField,
- }}}}})}
+ },
+ },
+ },
+ },
+ }),
+ }
}
opNameHeader := "x-operation-info"
@@ -262,7 +263,7 @@ func TestForwardHeaders(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(cfg *config.EngineExecutionConfiguration) {
- cfg.WebSocketClientReadTimeout = time.Millisecond * 10
+ cfg.WebSocketServerReadTimeout = time.Millisecond * 10
},
RouterOptions: []core.Option{
core.WithHeaderRules(headerRules),
@@ -289,16 +290,14 @@ func TestForwardHeaders(t *testing.T) {
}
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(cfg *config.EngineExecutionConfiguration) {
- cfg.WebSocketClientReadTimeout = time.Millisecond * 10
+ cfg.WebSocketServerReadTimeout = time.Millisecond * 10
},
RouterOptions: []core.Option{
core.WithHeaderRules(headerRules),
},
}, func(t *testing.T, xEnv *testenv.Environment) {
for _, c := range cases {
- c := c
t.Run(c.testName, func(t *testing.T) {
-
header := http.Header{
c.headerName: []string{headerValue},
}
@@ -323,7 +322,7 @@ func TestForwardHeaders(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(cfg *config.EngineExecutionConfiguration) {
- cfg.WebSocketClientReadTimeout = time.Millisecond * 10
+ cfg.WebSocketServerReadTimeout = time.Millisecond * 10
},
RouterOptions: []core.Option{
core.WithHeaderRules(headerRules),
@@ -333,13 +332,13 @@ func TestForwardHeaders(t *testing.T) {
err := conn.WriteJSON(&testenv.WebSocketMessage{
ID: "1",
Type: "subscribe",
- Payload: []byte(`{"query":"subscription { headerValue(name:\"foo\", repeat:3) { value initialPayload }}","extensions":{"token":"123"}}`),
+ Payload: []byte(`{"query":"subscription { headerValue(name:\"foo\", repeat:3) { value extensions }}","extensions":{"token":"123"}}`),
})
require.NoError(t, err)
var msg testenv.WebSocketMessage
err = conn.ReadJSON(&msg)
require.NoError(t, err)
- require.Equal(t, `{"data":{"headerValue":{"value":"","initialPayload":{"extensions":{"token":"123"}}}}}`, string(msg.Payload))
+ require.Equal(t, `{"data":{"headerValue":{"value":"","extensions":{"token":"123"}}}}`, string(msg.Payload))
})
})
@@ -357,7 +356,7 @@ func TestForwardHeaders(t *testing.T) {
}
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(cfg *config.EngineExecutionConfiguration) {
- cfg.WebSocketClientReadTimeout = time.Millisecond * 10
+ cfg.WebSocketServerReadTimeout = time.Millisecond * 10
},
RouterOptions: []core.Option{
core.WithHeaderRules(headerRules),
@@ -590,7 +589,7 @@ func TestForwardRenamedHeaders(t *testing.T) {
}
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(cfg *config.EngineExecutionConfiguration) {
- cfg.WebSocketClientReadTimeout = time.Millisecond * 10
+ cfg.WebSocketServerReadTimeout = time.Millisecond * 10
},
RouterOptions: []core.Option{
core.WithHeaderRules(headerRules),
@@ -609,7 +608,6 @@ func TestForwardRenamedHeaders(t *testing.T) {
})
log.Println(res.Body)
require.Equal(t, `{"data":{"headerValue":"`+headerValue+`"}}`, res.Body)
-
})
}
})
@@ -620,7 +618,7 @@ func TestForwardRenamedHeaders(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(cfg *config.EngineExecutionConfiguration) {
- cfg.WebSocketClientReadTimeout = time.Millisecond * 10
+ cfg.WebSocketServerReadTimeout = time.Millisecond * 10
},
RouterOptions: []core.Option{
core.WithHeaderRules(headerRules),
@@ -647,7 +645,7 @@ func TestForwardRenamedHeaders(t *testing.T) {
}
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(cfg *config.EngineExecutionConfiguration) {
- cfg.WebSocketClientReadTimeout = time.Millisecond * 10
+ cfg.WebSocketServerReadTimeout = time.Millisecond * 10
},
RouterOptions: []core.Option{
core.WithHeaderRules(headerRules),
@@ -656,7 +654,6 @@ func TestForwardRenamedHeaders(t *testing.T) {
for _, c := range cases {
c := c
t.Run(c.testName, func(t *testing.T) {
-
header := http.Header{
c.headerName: []string{headerValue},
}
@@ -681,7 +678,7 @@ func TestForwardRenamedHeaders(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(cfg *config.EngineExecutionConfiguration) {
- cfg.WebSocketClientReadTimeout = time.Millisecond * 10
+ cfg.WebSocketServerReadTimeout = time.Millisecond * 10
},
RouterOptions: []core.Option{
core.WithHeaderRules(headerRules),
@@ -691,13 +688,13 @@ func TestForwardRenamedHeaders(t *testing.T) {
err := conn.WriteJSON(&testenv.WebSocketMessage{
ID: "1",
Type: "subscribe",
- Payload: []byte(`{"query":"subscription { headerValue(name:\"light\", repeat:3) { value initialPayload }}","extensions":{"token":"123"}}`),
+ Payload: []byte(`{"query":"subscription { headerValue(name:\"light\", repeat:3) { value extensions }}","extensions":{"token":"123"}}`),
})
require.NoError(t, err)
var msg testenv.WebSocketMessage
err = conn.ReadJSON(&msg)
require.NoError(t, err)
- require.Equal(t, `{"data":{"headerValue":{"value":"","initialPayload":{"extensions":{"token":"123"}}}}}`, string(msg.Payload))
+ require.Equal(t, `{"data":{"headerValue":{"value":"","extensions":{"token":"123"}}}}`, string(msg.Payload))
})
})
@@ -715,7 +712,7 @@ func TestForwardRenamedHeaders(t *testing.T) {
}
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(cfg *config.EngineExecutionConfiguration) {
- cfg.WebSocketClientReadTimeout = time.Millisecond * 10
+ cfg.WebSocketServerReadTimeout = time.Millisecond * 10
},
RouterOptions: []core.Option{
core.WithHeaderRules(headerRules),
@@ -857,6 +854,5 @@ func TestForwardRenamedHeaders(t *testing.T) {
require.Equal(t, headerPayloadEntry.Data["val3"], value3)
})
})
-
})
}
diff --git a/router-tests/subscriptions/http_subscriptions_test.go b/router-tests/subscriptions/http_subscriptions_test.go
index d3fe7d1570..5ab3cd9607 100644
--- a/router-tests/subscriptions/http_subscriptions_test.go
+++ b/router-tests/subscriptions/http_subscriptions_test.go
@@ -3,6 +3,7 @@ package integration
import (
"bufio"
"bytes"
+ "errors"
"fmt"
"io"
"net/http"
@@ -81,39 +82,81 @@ func TestHeartbeats(t *testing.T) {
defer resp.Body.Close()
reader := bufio.NewReader(resp.Body)
- messages := make(chan string, 1)
+ type timestampedMsg struct {
+ body string
+ at time.Time
+ }
+ raw := make(chan timestampedMsg, 50)
+
+ type readerResult struct {
+ err error
+ msgCount int
+ }
+ errCh := make(chan readerResult, 1)
go func() {
- defer close(messages)
+ defer close(raw)
+ count := 0
for {
err := readMultipartPrefix(reader)
if err != nil {
+ errCh <- readerResult{err: err, msgCount: count}
return
}
line, _, err := reader.ReadLine()
if err != nil {
+ errCh <- readerResult{err: fmt.Errorf("ReadLine after prefix: %w", err), msgCount: count}
return
}
- messages <- string(line)
+ raw <- timestampedMsg{body: string(line), at: time.Now()}
+ count++
}
}()
- for i := 0; i <= 5; i++ {
- testenv.AwaitChannelWithT(t, 5*time.Second, messages, func(t *testing.T, msg string) {
- assert.Equal(t, fmt.Sprintf(`{"payload":{"data":{"countEmp":%d}}}`, i), msg)
- })
+ type received struct {
+ body string
+ sincePrevMsg time.Duration
+ }
+ var msgs []received
+ var lastReceive time.Time
+ for tm := range raw {
+ var sincePrev time.Duration
+ if !lastReceive.IsZero() {
+ sincePrev = tm.at.Sub(lastReceive)
+ }
+ msgs = append(msgs, received{body: tm.body, sincePrevMsg: sincePrev})
+ lastReceive = tm.at
+ }
- testenv.AwaitChannelWithT(t, 5*time.Second, messages, func(t *testing.T, msg string) {
- assert.Equal(t, `{}`, msg)
- })
+ result := <-errCh
+ if errors.Is(result.err, io.EOF) {
+ t.Logf("stream ended normally (EOF) after %d messages", result.msgCount)
+ } else {
+ t.Logf("stream ended: %d messages, final error: %v", result.msgCount, result.err)
}
- // Channel should be closed after all heartbeats are received
- testenv.AwaitChannelWithCloseWithT(t, 5*time.Second, messages, func(t *testing.T, _ string, ok bool) {
- require.False(t, ok, "channel should be closed")
- })
+ require.NotEmpty(t, msgs,
+ "multipart stream closed with 0 messages (reader saw %d frames, error: %v); "+
+ "this usually means the SSE connection to the subgraph was reset before any data was sent",
+ result.msgCount, result.err)
+
+ // Every message must be either a heartbeat ({}) or the next expected
+ // data payload, and gaps between consecutive messages must stay within
+ // the allowed threshold.
+ maxAllowedGap := subscriptionHeartbeatInterval * 2
+ dataIdx := 0
+ for _, m := range msgs {
+ assert.LessOrEqual(t, m.sincePrevMsg, maxAllowedGap,
+ "gap between consecutive messages (%s) exceeded max allowed (%s)", m.sincePrevMsg, maxAllowedGap)
+ if m.body == `{}` {
+ continue // valid multipart heartbeat
+ }
+ assert.Equal(t, fmt.Sprintf(`{"payload":{"data":{"countEmp":%d}}}`, dataIdx), m.body)
+ dataIdx++
+ }
+ assert.Equal(t, 6, dataIdx, "expected 6 data messages")
})
})
@@ -144,61 +187,56 @@ func TestHeartbeats(t *testing.T) {
reader := bufio.NewReader(resp.Body)
- lines := make(chan string, 50)
+ type timestampedLine struct {
+ text string
+ at time.Time
+ }
+ raw := make(chan timestampedLine, 50)
go func() {
- defer close(lines)
+ defer close(raw)
for {
line, _, err := reader.ReadLine()
if err != nil {
return
}
- lines <- string(line)
+ raw <- timestampedLine{text: string(line), at: time.Now()}
}
}()
- // Assert the expected SSE sequence
- for i := 0; i <= 5; i++ {
- // Expect "event: next"
- testenv.AwaitChannelWithT(t, 5*time.Second, lines, func(t *testing.T, line string) {
- assert.Equal(t, "event: next", line)
- })
-
- // Expect data line with count
- testenv.AwaitChannelWithT(t, 5*time.Second, lines, func(t *testing.T, line string) {
- assert.Equal(t, fmt.Sprintf(`data: {"data":{"countEmp":%d}}`, i), line)
- })
-
- // Expect blank line
- testenv.AwaitChannelWithT(t, 5*time.Second, lines, func(t *testing.T, line string) {
- assert.Equal(t, "", line)
- })
-
- // Expect heartbeat
- testenv.AwaitChannelWithT(t, 5*time.Second, lines, func(t *testing.T, line string) {
- assert.Equal(t, ":heartbeat", line)
- })
-
- // Expect blank line after heartbeat
- testenv.AwaitChannelWithT(t, 5*time.Second, lines, func(t *testing.T, line string) {
- assert.Equal(t, "", line)
- })
- }
-
- // Expect completion event
- testenv.AwaitChannelWithT(t, 5*time.Second, lines, func(t *testing.T, line string) {
- assert.Equal(t, "event: complete", line)
- })
-
- // Expect empty data line event
- testenv.AwaitChannelWithT(t, 5*time.Second, lines, func(t *testing.T, line string) {
- assert.Equal(t, "data: ", line)
- })
+ // For each non-empty line, assert it is one of:
+ // 1. ":heartbeat" — valid SSE keep-alive comment
+ // 2. "event: next" / "event: complete" — SSE event type framing
+ // 3. "data: ..." — the next expected data payload in sequence
+ // Additionally, the gap between consecutive data/heartbeat lines must
+ // not exceed the allowed threshold.
+ maxAllowedGap := subscriptionHeartbeatInterval * 2
+ dataIdx := 0
+ gotComplete := false
+ var lastActivity time.Time
+ for tl := range raw {
+ switch tl.text {
+ case "", "event: next", "data: ":
+ continue // SSE framing — not content
+ case ":heartbeat":
+ // valid SSE heartbeat
+ case "event: complete":
+ gotComplete = true
+ default:
+ assert.Equal(t, fmt.Sprintf(`data: {"data":{"countEmp":%d}}`, dataIdx), tl.text)
+ dataIdx++
+ }
- // Expect blank line after complete
- testenv.AwaitChannelWithT(t, 5*time.Second, lines, func(t *testing.T, line string) {
- assert.Equal(t, "", line)
- })
+ // Gap check applies to heartbeats, data, and complete events.
+ if !lastActivity.IsZero() {
+ gap := tl.at.Sub(lastActivity)
+ assert.LessOrEqual(t, gap, maxAllowedGap,
+ "gap between consecutive activity (%s) exceeded max allowed (%s)", gap, maxAllowedGap)
+ }
+ lastActivity = tl.at
+ }
+ assert.Equal(t, 6, dataIdx, "expected 6 data messages")
+ assert.True(t, gotComplete, "expected completion event")
})
})
diff --git a/router-tests/subscriptions/speedtrap_test.go b/router-tests/subscriptions/speedtrap_test.go
new file mode 100644
index 0000000000..9a081cda23
--- /dev/null
+++ b/router-tests/subscriptions/speedtrap_test.go
@@ -0,0 +1,97 @@
+package integration
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/wundergraph/cosmo/router-tests/testenv"
+ "github.com/wundergraph/cosmo/router/core"
+ "github.com/wundergraph/cosmo/router/pkg/config"
+ "github.com/wundergraph/cosmo/speedtrap"
+ cosmo "github.com/wundergraph/cosmo/speedtrap/scenarios/graphql/configs/cosmo"
+ "github.com/wundergraph/cosmo/speedtrap/scenarios/graphql/proxy/graphqltransportws"
+ "github.com/wundergraph/cosmo/speedtrap/scenarios/graphql/proxy/graphqlws"
+)
+
+// speedtrapHeaderRules configures header propagation for all speedtrap
+// scenarios. Authorization and X-Custom-* are forwarded as HTTP headers on the
+// upstream WebSocket dial so header-forwarding scenarios can assert them via
+// UpgradeHeaders on the backend connection.
+var speedtrapHeaderRules = config.HeaderRules{
+ All: &config.GlobalHeaderRule{
+ Request: []*config.RequestHeaderRule{
+ {
+ Operation: config.HeaderRuleOperationPropagate,
+ Named: "Authorization",
+ },
+ {
+ Operation: config.HeaderRuleOperationPropagate,
+ Matching: "(?i)^X-Custom-.*",
+ },
+ },
+ },
+}
+
+// runSpeedtrapScenarios is the shared harness for all speedtrap proxy scenarios.
+// Each scenario gets its own backend, subgraph server, and router instance.
+func runSpeedtrapScenarios(t *testing.T, scenarios []speedtrap.Scenario) {
+ t.Helper()
+ t.Parallel()
+
+ for _, scenario := range scenarios {
+ t.Run(scenario.Name, func(t *testing.T) {
+ t.Parallel()
+
+ backendA := speedtrap.NewBackend(speedtrap.WithSubprotocol("graphql-transport-ws"))
+
+ // Start an HTTP server for subgraph-a that routes WS to the speedtrap backend
+ subgraphA := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Header.Get("Upgrade") == "websocket" {
+ backendA.Handler().ServeHTTP(w, r)
+ return
+ }
+ w.WriteHeader(http.StatusOK)
+ }))
+ t.Cleanup(subgraphA.Close)
+
+ // Replace placeholder URLs in the speedtrap config with actual test server URLs
+ configJSON := strings.ReplaceAll(cosmo.ConfigJSON, cosmo.SubgraphAPlaceholderURL, testenv.GqlURL(subgraphA))
+
+ testenv.Run(t, &testenv.Config{
+ RouterConfigJSONTemplate: configJSON,
+ ModifyEngineExecutionConfiguration: func(cfg *config.EngineExecutionConfiguration) {
+ cfg.MinifySubgraphOperations = false
+ cfg.DisableVariablesRemapping = true
+ cfg.WebSocketClientAckTimeout = 3 * time.Second
+ },
+ ModifyWebsocketConfiguration: func(cfg *config.WebSocketConfiguration) {
+ cfg.ForwardUpgradeHeaders.Enabled = false
+ cfg.ForwardUpgradeQueryParams.Enabled = false
+ cfg.ForwardInitialPayload = false
+ },
+ RouterOptions: []core.Option{
+ core.WithHeaderRules(speedtrapHeaderRules),
+ },
+ }, func(t *testing.T, xEnv *testenv.Environment) {
+ cfg := speedtrap.HarnessConfig{
+ TargetAddr: xEnv.GraphQLWebSocketSubscriptionURL(),
+ Backends: map[string]*speedtrap.Backend{"subgraph-a": backendA},
+ }
+ speedtrap.RequireScenario(t, cfg, scenario)
+ })
+ })
+ }
+}
+
+func TestSpeedtrapScenarios(t *testing.T) {
+ t.Run("graphql-transport-ws", func(t *testing.T) {
+ runSpeedtrapScenarios(t, graphqltransportws.Scenarios)
+ })
+
+ t.Run("graphql-ws", func(t *testing.T) {
+ runSpeedtrapScenarios(t, graphqlws.Scenarios)
+ })
+}
diff --git a/router-tests/subscriptions/websocket_test.go b/router-tests/subscriptions/websocket_test.go
index 723b80fee3..c221a6ecd6 100644
--- a/router-tests/subscriptions/websocket_test.go
+++ b/router-tests/subscriptions/websocket_test.go
@@ -226,9 +226,9 @@ func TestWebSockets(t *testing.T) {
var res testenv.WebSocketMessage
err = testenv.WSReadJSON(t, conn, &res)
require.NoError(t, err)
- require.Equal(t, "error", res.Type)
+ require.Equal(t, "next", res.Type)
require.Equal(t, "1", res.ID)
- require.Equal(t, `[{"message":"Unauthorized to load field 'Query.employees.startDate', Reason: not authenticated.","path":["employees",0,"startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}},{"message":"Unauthorized to load field 'Query.employees.startDate', Reason: not authenticated.","path":["employees",1,"startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}},{"message":"Unauthorized to load field 'Query.employees.startDate', Reason: not authenticated.","path":["employees",2,"startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}},{"message":"Unauthorized to load field 'Query.employees.startDate', Reason: not authenticated.","path":["employees",3,"startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}},{"message":"Unauthorized to load field 'Query.employees.startDate', Reason: not authenticated.","path":["employees",4,"startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}},{"message":"Unauthorized to load field 'Query.employees.startDate', Reason: not authenticated.","path":["employees",5,"startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}},{"message":"Unauthorized to load field 'Query.employees.startDate', Reason: not authenticated.","path":["employees",6,"startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}},{"message":"Unauthorized to load field 'Query.employees.startDate', Reason: not authenticated.","path":["employees",7,"startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}},{"message":"Unauthorized to load field 'Query.employees.startDate', Reason: not authenticated.","path":["employees",8,"startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}},{"message":"Unauthorized to load field 'Query.employees.startDate', Reason: not authenticated.","path":["employees",9,"startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}}]`, string(res.Payload))
+ require.Equal(t, `{"errors":[{"message":"Unauthorized to load field 'Query.employees.startDate', Reason: not authenticated.","path":["employees",0,"startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}},{"message":"Unauthorized to load field 'Query.employees.startDate', Reason: not authenticated.","path":["employees",1,"startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}},{"message":"Unauthorized to load field 'Query.employees.startDate', Reason: not authenticated.","path":["employees",2,"startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}},{"message":"Unauthorized to load field 'Query.employees.startDate', Reason: not authenticated.","path":["employees",3,"startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}},{"message":"Unauthorized to load field 'Query.employees.startDate', Reason: not authenticated.","path":["employees",4,"startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}},{"message":"Unauthorized to load field 'Query.employees.startDate', Reason: not authenticated.","path":["employees",5,"startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}},{"message":"Unauthorized to load field 'Query.employees.startDate', Reason: not authenticated.","path":["employees",6,"startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}},{"message":"Unauthorized to load field 'Query.employees.startDate', Reason: not authenticated.","path":["employees",7,"startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}},{"message":"Unauthorized to load field 'Query.employees.startDate', Reason: not authenticated.","path":["employees",8,"startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}},{"message":"Unauthorized to load field 'Query.employees.startDate', Reason: not authenticated.","path":["employees",9,"startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}}],"data":{"employees":[null,null,null,null,null,null,null,null,null,null]}}`, string(res.Payload))
var complete testenv.WebSocketMessage
err = testenv.WSReadJSON(t, conn, &complete)
require.NoError(t, err)
@@ -294,9 +294,9 @@ func TestWebSockets(t *testing.T) {
var res testenv.WebSocketMessage
err = testenv.WSReadJSON(t, conn, &res)
require.NoError(t, err)
- require.Equal(t, "error", res.Type)
+ require.Equal(t, "next", res.Type)
require.Equal(t, "1", res.ID)
- require.Equal(t, `[{"message":"Unauthorized to load field 'Subscription.employeeUpdated.startDate', Reason: not authenticated.","path":["employeeUpdated","startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}}]`, string(res.Payload))
+ require.Equal(t, `{"errors":[{"message":"Unauthorized to load field 'Subscription.employeeUpdated.startDate', Reason: not authenticated.","path":["employeeUpdated","startDate"],"extensions":{"code":"UNAUTHORIZED_FIELD_OR_TYPE"}}],"data":null}`, string(res.Payload))
require.NoError(t, conn.Close())
xEnv.WaitForSubscriptionCount(0, time.Second*15)
@@ -587,7 +587,7 @@ func TestWebSockets(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(engineExecutionConfiguration *config.EngineExecutionConfiguration) {
- engineExecutionConfiguration.WebSocketClientReadTimeout = time.Millisecond * 500
+ engineExecutionConfiguration.WebSocketServerReadTimeout = time.Millisecond * 500
},
}, func(t *testing.T, xEnv *testenv.Environment) {
expectConnectAndReadCurrentTime(t, xEnv)
@@ -624,7 +624,7 @@ func TestWebSockets(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(engineExecutionConfiguration *config.EngineExecutionConfiguration) {
- engineExecutionConfiguration.WebSocketClientReadTimeout = time.Millisecond * 500
+ engineExecutionConfiguration.WebSocketServerReadTimeout = time.Millisecond * 500
},
RouterOptions: []core.Option{
core.WithHeaderRules(headerRules),
@@ -651,32 +651,35 @@ func TestWebSockets(t *testing.T) {
_, message, err := testenv.WSReadMessage(t, conn)
require.NoError(t, err)
- require.Equal(t, `{"type":"connection_init","payload":{"Custom-Auth":"test","extensions":{"upgradeHeaders":{"Authorization":"Bearer test","Canonical-Header-Name":"matches","Reverse-Canonical-Header-Name":"matches as well","X-Custom-Auth":"customAuth"},"upgradeQueryParams":{"token":"Bearer Something"},"initialPayload":{"Custom-Auth":"test"}}}}`, string(message))
+ require.Equal(t, `{"type":"connection_init","payload":{"Custom-Auth":"test"}}`, strings.TrimSpace(string(message)))
err = testenv.WSWriteMessage(t, conn, websocket.TextMessage, []byte(`{"type":"connection_ack"}`))
require.NoError(t, err)
_, message, err = testenv.WSReadMessage(t, conn)
require.NoError(t, err)
- require.Equal(t, `{"id":"1","type":"subscribe","payload":{"query":"subscription{currentTime {unixTime timeStamp}}","extensions":{"upgradeHeaders":{"Authorization":"Bearer test","Canonical-Header-Name":"matches","Reverse-Canonical-Header-Name":"matches as well","X-Custom-Auth":"customAuth"},"upgradeQueryParams":{"token":"Bearer Something"},"initialPayload":{"Custom-Auth":"test"}}}}`, string(message))
- err = testenv.WSWriteMessage(t, conn, websocket.TextMessage, []byte(`{"type":"next","id":"1","payload":{"data":{"currentTime":{"unixTime":1,"timeStamp":"2021-09-01T12:00:00Z"}}}}`))
+ id, err := jsonparser.GetString(message, "id") // id is generated by the client
+ require.NoError(t, err)
+
+ require.Equal(t, fmt.Sprintf(`{"id":"%s","type":"subscribe","payload":{"query":"subscription{currentTime {unixTime timeStamp}}","extensions":{"upgradeHeaders":{"Authorization":"Bearer test","Canonical-Header-Name":"matches","Reverse-Canonical-Header-Name":"matches as well","X-Custom-Auth":"customAuth"},"upgradeQueryParams":{"token":"Bearer Something"},"initialPayload":{"Custom-Auth":"test"}}}}`, id), strings.TrimSpace(string(message)))
+
+ err = testenv.WSWriteMessage(t, conn, websocket.TextMessage, fmt.Appendf(nil, `{"type":"next","id":"%s","payload":{"data":{"currentTime":{"unixTime":1,"timeStamp":"2021-09-01T12:00:00Z"}}}}`, id))
require.NoError(t, err)
_, message, err = testenv.WSReadMessage(t, conn)
if errors.Is(err, websocket.ErrCloseSent) {
return
}
- require.Equal(t, `{"id":"1","type":"complete"}`, string(message))
+ require.Equal(t, fmt.Sprintf(`{"id":"%s","type":"complete"}`, id), strings.TrimSpace(string(message)))
- err = testenv.WSWriteMessage(t, conn, websocket.TextMessage, []byte(`{"type":"complete","id":"1"}`))
+ err = testenv.WSWriteMessage(t, conn, websocket.TextMessage, fmt.Appendf(nil, `{"type":"complete","id":"%s"}`, id))
require.NoError(t, err)
})
},
},
},
}, func(t *testing.T, xEnv *testenv.Environment) {
-
type currentTimePayload struct {
Data struct {
CurrentTime struct {
@@ -761,7 +764,7 @@ func TestWebSockets(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(engineExecutionConfiguration *config.EngineExecutionConfiguration) {
- engineExecutionConfiguration.WebSocketClientReadTimeout = time.Millisecond * 500
+ engineExecutionConfiguration.WebSocketServerReadTimeout = time.Millisecond * 500
},
ModifyWebsocketConfiguration: func(cfg *config.WebSocketConfiguration) {
cfg.ForwardUpgradeHeaders.AllowList = nil
@@ -793,33 +796,37 @@ func TestWebSockets(t *testing.T) {
_, message, err := testenv.WSReadMessage(t, conn)
require.NoError(t, err)
message = jsonparser.Delete(message, "payload", "extensions", "upgradeHeaders", "Sec-Websocket-Key") // Sec-Websocket-Key is a random value
- require.Equal(t, `{"type":"connection_init","payload":{"Custom-Auth":"test","extensions":{"upgradeHeaders":{"Authorization":"Bearer test","Canonical-Header-Name":"matches","Connection":"Upgrade","Ignored":"ignored","Not-Allowlisted-But-Forwarded":"but still part of the origin upgrade request","Reverse-Canonical-Header-Name":"matches as well","Sec-Websocket-Protocol":"graphql-transport-ws","Sec-Websocket-Version":"13","Upgrade":"websocket","User-Agent":"Go-http-client/1.1","X-Custom-Auth":"customAuth"},"upgradeQueryParams":{"ignored":"ignored","token":"Bearer Something","x-custom-auth":"customAuth"},"initialPayload":{"Custom-Auth":"test"}}}}`, string(message))
+ require.Equal(t, `{"type":"connection_init","payload":{"Custom-Auth":"test"}}`, strings.TrimSpace(string(message)))
err = testenv.WSWriteMessage(t, conn, websocket.TextMessage, []byte(`{"type":"connection_ack"}`))
require.NoError(t, err)
_, message, err = testenv.WSReadMessage(t, conn)
require.NoError(t, err)
+
message = jsonparser.Delete(message, "payload", "extensions", "upgradeHeaders", "Sec-Websocket-Key") // Sec-Websocket-Key is a random value
- require.Equal(t, `{"id":"1","type":"subscribe","payload":{"query":"subscription{currentTime {unixTime timeStamp}}","extensions":{"upgradeHeaders":{"Authorization":"Bearer test","Canonical-Header-Name":"matches","Connection":"Upgrade","Ignored":"ignored","Not-Allowlisted-But-Forwarded":"but still part of the origin upgrade request","Reverse-Canonical-Header-Name":"matches as well","Sec-Websocket-Protocol":"graphql-transport-ws","Sec-Websocket-Version":"13","Upgrade":"websocket","User-Agent":"Go-http-client/1.1","X-Custom-Auth":"customAuth"},"upgradeQueryParams":{"ignored":"ignored","token":"Bearer Something","x-custom-auth":"customAuth"},"initialPayload":{"Custom-Auth":"test"}}}}`, string(message))
- err = testenv.WSWriteMessage(t, conn, websocket.TextMessage, []byte(`{"type":"next","id":"1","payload":{"data":{"currentTime":{"unixTime":1,"timeStamp":"2021-09-01T12:00:00Z"}}}}`))
+ id, err := jsonparser.GetString(message, "id") // id is generated by the client and must be filled into responses
+ require.NoError(t, err)
+
+ require.Equal(t, fmt.Sprintf(`{"id":"%s","type":"subscribe","payload":{"query":"subscription{currentTime {unixTime timeStamp}}","extensions":{"upgradeHeaders":{"Authorization":"Bearer test","Canonical-Header-Name":"matches","Connection":"Upgrade","Ignored":"ignored","Not-Allowlisted-But-Forwarded":"but still part of the origin upgrade request","Reverse-Canonical-Header-Name":"matches as well","Sec-Websocket-Protocol":"graphql-transport-ws","Sec-Websocket-Version":"13","Upgrade":"websocket","User-Agent":"Go-http-client/1.1","X-Custom-Auth":"customAuth"},"upgradeQueryParams":{"ignored":"ignored","token":"Bearer Something","x-custom-auth":"customAuth"},"initialPayload":{"Custom-Auth":"test"}}}}`, id), strings.TrimSpace(string(message)))
+
+ err = testenv.WSWriteMessage(t, conn, websocket.TextMessage, fmt.Appendf(nil, `{"type":"next","id":"%s","payload":{"data":{"currentTime":{"unixTime":1,"timeStamp":"2021-09-01T12:00:00Z"}}}}`, id))
require.NoError(t, err)
_, message, err = testenv.WSReadMessage(t, conn)
if errors.Is(err, websocket.ErrCloseSent) {
return
}
- require.Equal(t, `{"id":"1","type":"complete"}`, string(message))
+ assert.Equal(t, fmt.Sprintf(`{"id":"%s","type":"complete"}`, id), strings.TrimSpace(string(message)))
- err = testenv.WSWriteMessage(t, conn, websocket.TextMessage, []byte(`{"type":"complete","id":"1"}`))
+ err = testenv.WSWriteMessage(t, conn, websocket.TextMessage, fmt.Appendf(nil, `{"type":"complete","id":"%s"}`, id))
require.NoError(t, err)
})
},
},
},
}, func(t *testing.T, xEnv *testenv.Environment) {
-
type currentTimePayload struct {
Data struct {
CurrentTime struct {
@@ -843,6 +850,7 @@ func TestWebSockets(t *testing.T) {
},
[]byte(`{"Custom-Auth":"test"}`),
)
+
err := testenv.WSWriteJSON(t, conn, &testenv.WebSocketMessage{
ID: "1",
Type: "subscribe",
@@ -856,7 +864,8 @@ func TestWebSockets(t *testing.T) {
err = testenv.WSReadJSON(t, conn, &msg)
require.NoError(t, err)
require.Equal(t, "1", msg.ID)
- require.Equal(t, "next", msg.Type)
+ assert.Equal(t, "next", msg.Type, "payload: %s", string(msg.Payload))
+
err = json.Unmarshal(msg.Payload, &payload)
require.NoError(t, err)
require.Equal(t, float64(1), payload.Data.CurrentTime.UnixTime)
@@ -961,7 +970,6 @@ func TestWebSockets(t *testing.T) {
require.NoError(t, conn.Close())
xEnv.WaitForSubscriptionCount(0, time.Second*5)
})
-
})
t.Run("subscription with header propagation sse subgraph post", func(t *testing.T) {
t.Parallel()
@@ -979,7 +987,7 @@ func TestWebSockets(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(engineExecutionConfiguration *config.EngineExecutionConfiguration) {
- engineExecutionConfiguration.WebSocketClientReadTimeout = time.Millisecond * 500
+ engineExecutionConfiguration.WebSocketServerReadTimeout = time.Millisecond * 500
},
ModifyRouterConfig: func(cfg *nodev1.RouterConfig) {
for i := range cfg.EngineConfig.DatasourceConfigurations {
@@ -1038,7 +1046,6 @@ func TestWebSockets(t *testing.T) {
},
},
}, func(t *testing.T, xEnv *testenv.Environment) {
-
type currentTimePayload struct {
Data struct {
CurrentTime struct {
@@ -1112,7 +1119,7 @@ func TestWebSockets(t *testing.T) {
}
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(engineExecutionConfiguration *config.EngineExecutionConfiguration) {
- engineExecutionConfiguration.WebSocketClientReadTimeout = time.Millisecond * 500
+ engineExecutionConfiguration.WebSocketServerReadTimeout = time.Millisecond * 500
},
ModifyRouterConfig: func(cfg *nodev1.RouterConfig) {
for i := range cfg.EngineConfig.DatasourceConfigurations {
@@ -1171,7 +1178,6 @@ func TestWebSockets(t *testing.T) {
},
},
}, func(t *testing.T, xEnv *testenv.Environment) {
-
type currentTimePayload struct {
Data struct {
CurrentTime struct {
@@ -1234,7 +1240,7 @@ func TestWebSockets(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(engineExecutionConfiguration *config.EngineExecutionConfiguration) {
- engineExecutionConfiguration.WebSocketClientReadTimeout = time.Millisecond * 500
+ engineExecutionConfiguration.WebSocketServerReadTimeout = time.Millisecond * 500
},
Subgraphs: testenv.SubgraphsConfig{
Employees: testenv.SubgraphConfig{
@@ -1247,7 +1253,6 @@ func TestWebSockets(t *testing.T) {
},
},
}, func(t *testing.T, xEnv *testenv.Environment) {
-
conn := xEnv.InitGraphQLWebSocketConnection(nil, nil, nil)
err := testenv.WSWriteJSON(t, conn, &testenv.WebSocketMessage{
ID: "1",
@@ -1270,7 +1275,7 @@ func TestWebSockets(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(engineExecutionConfiguration *config.EngineExecutionConfiguration) {
- engineExecutionConfiguration.WebSocketClientReadTimeout = time.Millisecond * 500
+ engineExecutionConfiguration.WebSocketServerReadTimeout = time.Millisecond * 500
},
ModifySubgraphErrorPropagation: func(cfg *config.SubgraphErrorPropagationConfiguration) {
cfg.PropagateStatusCodes = false
@@ -1286,7 +1291,6 @@ func TestWebSockets(t *testing.T) {
},
},
}, func(t *testing.T, xEnv *testenv.Environment) {
-
conn := xEnv.InitGraphQLWebSocketConnection(nil, nil, nil)
err := testenv.WSWriteJSON(t, conn, &testenv.WebSocketMessage{
ID: "1",
@@ -1309,7 +1313,7 @@ func TestWebSockets(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(engineExecutionConfiguration *config.EngineExecutionConfiguration) {
- engineExecutionConfiguration.WebSocketClientReadTimeout = time.Millisecond * 500
+ engineExecutionConfiguration.WebSocketServerReadTimeout = time.Millisecond * 500
},
Subgraphs: testenv.SubgraphsConfig{
Employees: testenv.SubgraphConfig{
@@ -1322,7 +1326,6 @@ func TestWebSockets(t *testing.T) {
},
},
}, func(t *testing.T, xEnv *testenv.Environment) {
-
conn := xEnv.InitGraphQLWebSocketConnection(nil, nil, nil)
err := testenv.WSWriteJSON(t, conn, &testenv.WebSocketMessage{
ID: "1",
@@ -1336,8 +1339,8 @@ func TestWebSockets(t *testing.T) {
err = testenv.WSReadJSON(t, conn, &msg)
require.NoError(t, err)
require.Equal(t, "1", msg.ID)
- require.Equal(t, "error", msg.Type)
- require.Equal(t, `[{"message":"this is an error","path":["returnsError"]}]`, string(msg.Payload))
+ require.Equal(t, "next", msg.Type)
+ require.Equal(t, `{"errors":[{"message":"this is an error","path":["returnsError"]}],"data":null}`, string(msg.Payload))
})
})
t.Run("subscription error in resolver unexposed", func(t *testing.T) {
@@ -1345,7 +1348,7 @@ func TestWebSockets(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(engineExecutionConfiguration *config.EngineExecutionConfiguration) {
- engineExecutionConfiguration.WebSocketClientReadTimeout = time.Millisecond * 500
+ engineExecutionConfiguration.WebSocketServerReadTimeout = time.Millisecond * 500
},
ModifySubgraphErrorPropagation: func(cfg *config.SubgraphErrorPropagationConfiguration) {
cfg.Enabled = false
@@ -1361,7 +1364,6 @@ func TestWebSockets(t *testing.T) {
},
},
}, func(t *testing.T, xEnv *testenv.Environment) {
-
conn := xEnv.InitGraphQLWebSocketConnection(nil, nil, nil)
err := testenv.WSWriteJSON(t, conn, &testenv.WebSocketMessage{
ID: "1",
@@ -1375,8 +1377,8 @@ func TestWebSockets(t *testing.T) {
err = testenv.WSReadJSON(t, conn, &msg)
require.NoError(t, err)
require.Equal(t, "1", msg.ID)
- require.Equal(t, "error", msg.Type)
- require.Equal(t, `[{"message":"Unable to subscribe"}]`, string(msg.Payload))
+ require.Equal(t, "next", msg.Type)
+ require.Equal(t, `{"errors":[{"message":"Unable to subscribe"}],"data":null}`, string(msg.Payload))
})
})
t.Run("error", func(t *testing.T) {
@@ -1472,94 +1474,51 @@ func TestWebSockets(t *testing.T) {
_ = client.Run()
})
})
- t.Run("forward extensions", func(t *testing.T) {
+
+ t.Run("extensions are forwarded per subscription", func(t *testing.T) {
t.Parallel()
testenv.Run(t, &testenv.Config{}, func(t *testing.T, xEnv *testenv.Environment) {
- // Make sure sending two simultaneous subscriptions with different extensions
- // triggers two subscriptions to the upstream
conn1 := xEnv.InitGraphQLWebSocketConnection(nil, nil, nil)
conn2 := xEnv.InitGraphQLWebSocketConnection(nil, nil, nil)
+
var err error
err = conn1.WriteJSON(&testenv.WebSocketMessage{
ID: "1",
Type: "subscribe",
- Payload: []byte(`{"query":"subscription { initialPayload(repeat:3) }","extensions":{"token":"123"}}`),
+ Payload: []byte(`{"query":"subscription { metadata { subscribeExtensions } }","extensions":{"token":"conn1-token"}}`),
})
- require.NoError(t, err)
+ require.NoError(t, err, "write conn1 message")
err = conn2.WriteJSON(&testenv.WebSocketMessage{
ID: "2",
Type: "subscribe",
- Payload: []byte(`{"query":"subscription { initialPayload(repeat:3) }","extensions":{"token":"456"}}`),
+ Payload: []byte(`{"query":"subscription { metadata { subscribeExtensions } }","extensions":{"token":"conn2-token"}}`),
})
- require.NoError(t, err)
+ require.NoError(t, err, "write conn2 message")
- var msg testenv.WebSocketMessage
- var payload struct {
- Data struct {
- InitialPayload struct {
- Extensions struct {
- Token string `json:"token"`
- } `json:"extensions"`
- } `json:"initialPayload"`
- } `json:"data"`
+ {
+ var msg testenv.WebSocketMessage
+ err = testenv.WSReadJSON(t, conn1, &msg)
+ require.NoError(t, err, "read conn1 message")
+ require.Equal(t, `{"data":{"metadata":{"subscribeExtensions":{"token":"conn1-token"}}}}`, string(msg.Payload))
}
- err = conn1.ReadJSON(&msg)
- require.NoError(t, err)
- err = json.Unmarshal(msg.Payload, &payload)
- require.NoError(t, err)
- require.Equal(t, "123", payload.Data.InitialPayload.Extensions.Token)
-
- err = conn2.ReadJSON(&msg)
- require.NoError(t, err)
- err = json.Unmarshal(msg.Payload, &payload)
- require.NoError(t, err)
- require.Equal(t, "456", payload.Data.InitialPayload.Extensions.Token)
- })
- })
- t.Run("forward query params via initial payload", func(t *testing.T) {
- t.Parallel()
-
- testenv.Run(t, &testenv.Config{}, func(t *testing.T, xEnv *testenv.Environment) {
- // Make sure sending two simultaneous subscriptions with different extensions
- // triggers two subscriptions to the upstream
- xEnv.SetExtraURLQueryValues(url.Values{
- "Authorization": []string{"token 123"},
- })
-
- conn1 := xEnv.InitGraphQLWebSocketConnection(nil, nil, nil)
- var err error
- err = conn1.WriteJSON(&testenv.WebSocketMessage{
- ID: "1",
- Type: "subscribe",
- Payload: []byte(`{"query":"subscription { initialPayload(repeat:3) }","extensions":{"token":"456"}}`),
- })
- require.NoError(t, err)
-
- var msg testenv.WebSocketMessage
- var payload struct {
- Data struct {
- InitialPayload json.RawMessage `json:"initialPayload"`
- } `json:"data"`
+ {
+ var msg testenv.WebSocketMessage
+ err = testenv.WSReadJSON(t, conn2, &msg)
+ require.NoError(t, err, "read conn2 message")
+ require.Equal(t, `{"data":{"metadata":{"subscribeExtensions":{"token":"conn2-token"}}}}`, string(msg.Payload))
}
- err = conn1.ReadJSON(&msg)
- require.NoError(t, err)
- err = json.Unmarshal(msg.Payload, &payload)
- require.NoError(t, err)
- require.Equal(t, `{"extensions":{"token":"456","upgradeQueryParams":{"Authorization":"token 123"}}}`, string(payload.Data.InitialPayload))
})
})
- t.Run("forward query params via initial payload alongside existing", func(t *testing.T) {
+
+ t.Run("query params are forwarded via subscription extensions", func(t *testing.T) {
t.Parallel()
testenv.Run(t, &testenv.Config{}, func(t *testing.T, xEnv *testenv.Environment) {
- // Make sure sending two simultaneous subscriptions with different extensions
- // triggers two subscriptions to the upstream
-
xEnv.SetExtraURLQueryValues(url.Values{
- "Authorization": []string{"token 123"},
+ "Authorization": []string{"query token 123"},
})
conn1 := xEnv.InitGraphQLWebSocketConnection(nil, nil, nil)
@@ -1567,23 +1526,19 @@ func TestWebSockets(t *testing.T) {
err = conn1.WriteJSON(&testenv.WebSocketMessage{
ID: "1",
Type: "subscribe",
- Payload: []byte(`{"query":"subscription { initialPayload(repeat:3) }"}`),
+ Payload: []byte(`{"query":"subscription { metadata { subscribeExtensions } }","extensions":{"ext-token":"456"}}`),
})
require.NoError(t, err)
var msg testenv.WebSocketMessage
- var payload struct {
- Data struct {
- InitialPayload json.RawMessage `json:"initialPayload"`
- } `json:"data"`
- }
- err = conn1.ReadJSON(&msg)
- require.NoError(t, err)
- err = json.Unmarshal(msg.Payload, &payload)
- require.NoError(t, err)
- require.Equal(t, `{"extensions":{"upgradeQueryParams":{"Authorization":"token 123"}}}`, string(payload.Data.InitialPayload))
+ err = testenv.WSReadJSON(t, conn1, &msg)
+ require.NoError(t, err, "read msg err: %s", string(msg.Payload))
+
+ // Query params should be forwarded as part of the subscription payload extensions, actual extensions should be untouched
+ require.Equal(t, `{"data":{"metadata":{"subscribeExtensions":{"ext-token":"456","upgradeQueryParams":{"Authorization":"query token 123"}}}}}`, string(msg.Payload))
})
})
+
t.Run("same graphql path as playground", func(t *testing.T) {
t.Parallel()
@@ -1601,9 +1556,10 @@ func TestWebSockets(t *testing.T) {
var msg testenv.WebSocketMessage
err = testenv.WSReadJSON(t, conn, &msg)
require.NoError(t, err)
- require.Equal(t, `{"data":{"initialPayload":{"123":456,"extensions":{"initialPayload":{"123":456,"extensions":{"hello":"world"}}}}}}`, string(msg.Payload))
+ require.Equal(t, `{"data":{"initialPayload":{"123":456,"extensions":{"hello":"world"}}}}`, string(msg.Payload))
})
})
+
t.Run("different path", func(t *testing.T) {
t.Parallel()
@@ -1621,7 +1577,7 @@ func TestWebSockets(t *testing.T) {
var msg testenv.WebSocketMessage
err = testenv.WSReadJSON(t, conn, &msg)
require.NoError(t, err)
- require.Equal(t, `{"data":{"initialPayload":{"123":456,"extensions":{"initialPayload":{"123":456,"extensions":{"hello":"world"}}}}}}`, string(msg.Payload))
+ require.Equal(t, `{"data":{"initialPayload":{"123":456,"extensions":{"hello":"world"}}}}`, string(msg.Payload))
})
})
@@ -1684,7 +1640,7 @@ func TestWebSockets(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(cfg *config.EngineExecutionConfiguration) {
cfg.EnableNetPoll = true
- cfg.WebSocketClientReadTimeout = time.Millisecond * 500
+ cfg.WebSocketServerReadTimeout = time.Millisecond * 500
},
}, func(t *testing.T, xEnv *testenv.Environment) {
conn := xEnv.InitGraphQLWebSocketConnection(nil, nil, nil)
@@ -1700,11 +1656,11 @@ func TestWebSockets(t *testing.T) {
require.NoError(t, err)
xEnv.Shutdown()
_, _, err = conn.NextReader()
- // Check that the WS client error indicates the connection was unexpectedly closed
+ // The server sends a clean 1001 Going Away close frame on shutdown
var closeError *websocket.CloseError
if assert.ErrorAs(t, err, &closeError) {
- assert.Equal(t, websocket.CloseAbnormalClosure, closeError.Code)
- assert.Equal(t, "unexpected EOF", closeError.Text)
+ assert.Equal(t, websocket.CloseGoingAway, closeError.Code)
+ assert.Equal(t, "Going away", closeError.Text)
}
})
})
@@ -1715,7 +1671,7 @@ func TestWebSockets(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(cfg *config.EngineExecutionConfiguration) {
cfg.EnableNetPoll = false
- cfg.WebSocketClientReadTimeout = time.Millisecond * 500
+ cfg.WebSocketServerReadTimeout = time.Millisecond * 500
},
}, func(t *testing.T, xEnv *testenv.Environment) {
conn := xEnv.InitGraphQLWebSocketConnection(nil, nil, nil)
@@ -1731,11 +1687,11 @@ func TestWebSockets(t *testing.T) {
require.NoError(t, err)
xEnv.Shutdown()
_, _, err = conn.NextReader()
- // Check that the WS client error indicates the connection was unexpectedly closed
+ // The server sends a clean 1001 Going Away close frame on shutdown
var closeError *websocket.CloseError
if assert.ErrorAs(t, err, &closeError) {
- assert.Equal(t, websocket.CloseAbnormalClosure, closeError.Code)
- assert.Equal(t, "unexpected EOF", closeError.Text)
+ assert.Equal(t, websocket.CloseGoingAway, closeError.Code)
+ assert.Equal(t, "Going away", closeError.Text)
}
})
})
@@ -1744,7 +1700,7 @@ func TestWebSockets(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(cfg *config.EngineExecutionConfiguration) {
- cfg.WebSocketClientReadTimeout = time.Millisecond * 500
+ cfg.WebSocketServerReadTimeout = time.Millisecond * 500
},
}, func(t *testing.T, xEnv *testenv.Environment) {
conn := xEnv.InitGraphQLWebSocketConnection(nil, nil, []byte(`{"123":456,"extensions":{"hello":"world"}}`))
@@ -1757,7 +1713,7 @@ func TestWebSockets(t *testing.T) {
var msg testenv.WebSocketMessage
err = testenv.WSReadJSON(t, conn, &msg)
require.NoError(t, err)
- require.Equal(t, `{"data":{"initialPayload":{"123":456,"extensions":{"initialPayload":{"123":456,"extensions":{"hello":"world"}}}}}}`, string(msg.Payload))
+ require.Equal(t, `{"data":{"initialPayload":{"123":456,"extensions":{"hello":"world"}}}}`, string(msg.Payload))
})
})
t.Run("single connection with initial payload and extensions in the request", func(t *testing.T) {
@@ -1765,10 +1721,10 @@ func TestWebSockets(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(cfg *config.EngineExecutionConfiguration) {
- cfg.WebSocketClientReadTimeout = time.Millisecond * 500
+ cfg.WebSocketServerReadTimeout = time.Millisecond * 500
},
}, func(t *testing.T, xEnv *testenv.Environment) {
- // "extensions" in the request should override the "extensions" in initial payload
+ // "extensions" in the request should not affect the "extensions" in initial payload
conn := xEnv.InitGraphQLWebSocketConnection(nil, nil, []byte(`{"123":456,"extensions":{"hello":"world"}}`))
err := testenv.WSWriteJSON(t, conn, &testenv.WebSocketMessage{
ID: "1",
@@ -1779,7 +1735,7 @@ func TestWebSockets(t *testing.T) {
var msg testenv.WebSocketMessage
err = testenv.WSReadJSON(t, conn, &msg)
require.NoError(t, err)
- require.Equal(t, `{"data":{"initialPayload":{"123":456,"extensions":{"hello":"world2","initialPayload":{"123":456,"extensions":{"hello":"world"}}}}}}`, string(msg.Payload))
+ require.Equal(t, `{"data":{"initialPayload":{"123":456,"extensions":{"hello":"world"}}}}`, string(msg.Payload))
})
})
t.Run("single connection multiple differing subscriptions", func(t *testing.T) {
@@ -1789,7 +1745,6 @@ func TestWebSockets(t *testing.T) {
RouterConfigJSONTemplate: testenv.ConfigWithEdfsNatsJSONTemplate,
EnableNats: true,
}, func(t *testing.T, xEnv *testenv.Environment) {
-
conn := xEnv.InitGraphQLWebSocketConnection(nil, nil, nil)
xEnv.WaitForConnectionCount(1, time.Second*5)
@@ -1821,7 +1776,6 @@ func TestWebSockets(t *testing.T) {
sub2Count := 0
go func() {
-
defer conn.Close()
var msg testenv.WebSocketMessage
@@ -1900,10 +1854,9 @@ func TestWebSockets(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(cfg *config.EngineExecutionConfiguration) {
- cfg.WebSocketClientReadTimeout = time.Millisecond * 500
+ cfg.WebSocketServerReadTimeout = time.Millisecond * 500
},
}, func(t *testing.T, xEnv *testenv.Environment) {
- // "extensions" in the request should override the "extensions" in initial payload
conn1 := xEnv.InitGraphQLWebSocketConnection(nil, nil, []byte(`{"id":1}`))
conn2 := xEnv.InitGraphQLWebSocketConnection(nil, nil, []byte(`{"id":2}`))
err := conn1.WriteJSON(&testenv.WebSocketMessage{
@@ -1919,13 +1872,13 @@ func TestWebSockets(t *testing.T) {
})
require.NoError(t, err)
var msg testenv.WebSocketMessage
- err = conn1.ReadJSON(&msg)
+ err = testenv.WSReadJSON(t, conn1, &msg)
require.NoError(t, err)
- require.Equal(t, `{"data":{"initialPayload":{"extensions":{"initialPayload":{"id":1}},"id":1}}}`, string(msg.Payload))
+ require.Equal(t, `{"data":{"initialPayload":{"id":1}}}`, string(msg.Payload))
- err = conn2.ReadJSON(&msg)
+ err = testenv.WSReadJSON(t, conn2, &msg)
require.NoError(t, err)
- require.Equal(t, `{"data":{"initialPayload":{"extensions":{"initialPayload":{"id":2}},"id":2}}}`, string(msg.Payload))
+ require.Equal(t, `{"data":{"initialPayload":{"id":2}}}`, string(msg.Payload))
})
})
t.Run("absinthe subscription", func(t *testing.T) {
@@ -1933,10 +1886,9 @@ func TestWebSockets(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(engineExecutionConfiguration *config.EngineExecutionConfiguration) {
- engineExecutionConfiguration.WebSocketClientReadTimeout = time.Millisecond * 500
+ engineExecutionConfiguration.WebSocketServerReadTimeout = time.Millisecond * 500
},
}, func(t *testing.T, xEnv *testenv.Environment) {
-
type currentTimePayload struct {
Result struct {
Data struct {
@@ -2645,7 +2597,6 @@ func TestWebSockets(t *testing.T) {
})
})
})
-
}
func TestFlakyWebSockets(t *testing.T) {
@@ -2666,7 +2617,7 @@ func TestFlakyWebSockets(t *testing.T) {
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(engineExecutionConfiguration *config.EngineExecutionConfiguration) {
- engineExecutionConfiguration.WebSocketClientReadTimeout = time.Second
+ engineExecutionConfiguration.WebSocketServerReadTimeout = time.Second
},
}, func(t *testing.T, xEnv *testenv.Environment) {
client := graphql.NewSubscriptionClient(xEnv.GraphQLWebSocketSubscriptionURL()).
@@ -2873,10 +2824,10 @@ func expectConnectAndReadCurrentTime(t *testing.T, xEnv *testenv.Environment) {
}
}
-func TestWebSocketPingIntervalForGraphQLTransportWS(t *testing.T) {
+func TestWebSocketPing(t *testing.T) {
t.Parallel()
- t.Run("epoll", func(t *testing.T) {
+ t.Run("should send pings to graphql-transport-ws upstreams", func(t *testing.T) {
t.Parallel()
totalUpdates := 5
@@ -2935,30 +2886,28 @@ func TestWebSocketPingIntervalForGraphQLTransportWS(t *testing.T) {
})
}
-// Tests how the router handles scenarios where the subgraph does not properly complete a subscription before the connection is closed,
-// e.g. if the subgraph goes down before completing the subscription
+// Tests how the router terminates client subscriptions when things go wrong,
+// e.g. the subgraph closes mid-stream or the router itself is shutting down.
+// On modern graphql-transport-ws, per-subscription errors are terminal and do
+// NOT close the client connection; only router shutdown closes the socket.
func TestWebsocketClose(t *testing.T) {
t.Parallel()
totalUpdates := 5
- t.Run("should return 1001 Downstream service error when the subgraph becomes unavailable", func(t *testing.T) {
+ t.Run("delivers an error frame when the subgraph becomes unavailable", func(t *testing.T) {
wsMiddleware, _ := countEmpWsMiddleware(t, totalUpdates, false)
- // Configure and run the test
testenv.Run(t, &testenv.Config{
Subgraphs: testenv.SubgraphsConfig{
GlobalMiddleware: wsMiddleware,
},
ModifyEngineExecutionConfiguration: func(config *config.EngineExecutionConfiguration) {
- // Don't use too small ping intervals
config.WebSocketClientPingInterval = 500 * time.Millisecond
},
}, func(t *testing.T, xEnv *testenv.Environment) {
- // Setup client connection
conn := xEnv.InitGraphQLWebSocketConnection(nil, nil, nil)
- // Start the subscription
err := testenv.WSWriteJSON(t, conn, testenv.WebSocketMessage{
ID: "1",
Type: "subscribe",
@@ -2968,7 +2917,6 @@ func TestWebsocketClose(t *testing.T) {
xEnv.WaitForConnectionCount(1, 10*time.Second)
- // Process subscription updates
var receivedUpdates int
for receivedUpdates < totalUpdates {
var res testenv.WebSocketMessage
@@ -2986,37 +2934,36 @@ func TestWebsocketClose(t *testing.T) {
}
}
- // Attempt to read again, should get close error
- _, _, err = conn.NextReader()
- require.Error(t, err)
-
- var closeError *websocket.CloseError
- if assert.ErrorAs(t, err, &closeError) {
- assert.Equal(t, websocket.CloseGoingAway, closeError.Code)
- assert.Equal(t, "Downstream service error", closeError.Text)
- }
+ // graphql-transport-ws: error is terminal for the subscription. No
+ // "complete" follows and the router does not close the client
+ // connection — it stays open for other subscriptions.
+ var errMsg testenv.WebSocketMessage
+ err = testenv.WSReadJSON(t, conn, &errMsg)
+ require.NoError(t, err)
+ require.Equal(t, "error", errMsg.Type)
+ require.Equal(t, "1", errMsg.ID)
- xEnv.WaitForConnectionCount(0, 10*time.Second)
+ require.NoError(t, conn.SetReadDeadline(time.Now().Add(500*time.Millisecond)))
+ _, _, nextErr := conn.ReadMessage()
+ require.Error(t, nextErr, "no further frames should arrive after the terminal error")
+ var closeErr *websocket.CloseError
+ require.False(t, errors.As(nextErr, &closeErr), "router should not close the connection on per-subscription error, got %v", nextErr)
})
})
- t.Run("should complete normally when the subgraph remains available", func(t *testing.T) {
+ t.Run("completes the subscription when the subgraph remains available", func(t *testing.T) {
wsMiddleware, _ := countEmpWsMiddleware(t, totalUpdates, true)
- // Configure and run the test
testenv.Run(t, &testenv.Config{
Subgraphs: testenv.SubgraphsConfig{
GlobalMiddleware: wsMiddleware,
},
ModifyEngineExecutionConfiguration: func(config *config.EngineExecutionConfiguration) {
- // Don't use too small ping intervals
config.WebSocketClientPingInterval = 500 * time.Millisecond
},
}, func(t *testing.T, xEnv *testenv.Environment) {
- // Setup client connection
conn := xEnv.InitGraphQLWebSocketConnection(nil, nil, nil)
- // Start the subscription
err := testenv.WSWriteJSON(t, conn, testenv.WebSocketMessage{
ID: "1",
Type: "subscribe",
@@ -3024,7 +2971,6 @@ func TestWebsocketClose(t *testing.T) {
})
require.NoError(t, err)
- // Process subscription updates
var receivedUpdates int
for receivedUpdates < totalUpdates {
var res testenv.WebSocketMessage
@@ -3042,40 +2988,33 @@ func TestWebsocketClose(t *testing.T) {
}
}
- // Get the complete message
var complete testenv.WebSocketMessage
err = testenv.WSReadJSON(t, conn, &complete)
require.NoError(t, err)
require.Equal(t, "complete", complete.Type)
+ require.Equal(t, "1", complete.ID)
})
})
- t.Run("should return 1000 normal closure when upgrade is rejected", func(t *testing.T) {
- // Configure and run the test
+ t.Run("delivers an error frame when the subgraph upgrade is rejected", func(t *testing.T) {
testenv.Run(t, &testenv.Config{
Subgraphs: testenv.SubgraphsConfig{
GlobalMiddleware: func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- // Check if this is a WebSocket upgrade request
if websocket.IsWebSocketUpgrade(r) {
- // Reject with 401 Unauthorized
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
- // Pass through non-WebSocket requests
handler.ServeHTTP(w, r)
})
},
},
ModifyEngineExecutionConfiguration: func(config *config.EngineExecutionConfiguration) {
- // Don't use too small ping intervals
config.WebSocketClientPingInterval = 500 * time.Millisecond
},
}, func(t *testing.T, xEnv *testenv.Environment) {
- // Setup client connection
conn := xEnv.InitGraphQLWebSocketConnection(nil, nil, nil)
- // Start the subscription
err := testenv.WSWriteJSON(t, conn, testenv.WebSocketMessage{
ID: "1",
Type: "subscribe",
@@ -3083,42 +3022,34 @@ func TestWebsocketClose(t *testing.T) {
})
require.NoError(t, err)
- // Read the error response
+ // graphql-transport-ws: error is terminal for the subscription. No
+ // "complete" follows and the router does not close the client
+ // connection — it stays open for other subscriptions.
var res testenv.WebSocketMessage
err = testenv.WSReadJSON(t, conn, &res)
require.NoError(t, err)
-
- // Should get an error message
require.Equal(t, "error", res.Type)
-
- // Check the error payload
+ require.Equal(t, "1", res.ID)
require.JSONEq(t, `[{"message":"Subscription Upgrade request failed for Subgraph 'employees'.","extensions":{"statusCode":401}}]`, string(res.Payload))
- // Connection should be closed after error
- _, _, err = conn.NextReader()
- require.Error(t, err)
-
- var closeError *websocket.CloseError
- if assert.ErrorAs(t, err, &closeError) {
- assert.Equal(t, websocket.CloseNormalClosure, closeError.Code)
- assert.Equal(t, "Normal closure", closeError.Text)
- }
+ require.NoError(t, conn.SetReadDeadline(time.Now().Add(500*time.Millisecond)))
+ _, _, nextErr := conn.ReadMessage()
+ require.Error(t, nextErr, "no further frames should arrive after the terminal error")
+ var closeErr *websocket.CloseError
+ require.False(t, errors.As(nextErr, &closeErr), "router should not close the connection on per-subscription error, got %v", nextErr)
})
})
- t.Run("should return 1001 Going Away when router shuts down", func(t *testing.T) {
+ t.Run("closes the connection with 1001 Going Away when the router shuts down", func(t *testing.T) {
t.Parallel()
testenv.Run(t, &testenv.Config{
ModifyEngineExecutionConfiguration: func(config *config.EngineExecutionConfiguration) {
- // Use longer ping intervals to avoid interference
config.WebSocketClientPingInterval = 500 * time.Millisecond
},
}, func(t *testing.T, xEnv *testenv.Environment) {
- // Setup client connection
conn := xEnv.InitGraphQLWebSocketConnection(nil, nil, nil)
- // Start a subscription to keep the connection active
err := testenv.WSWriteJSON(t, conn, testenv.WebSocketMessage{
ID: "1",
Type: "subscribe",
@@ -3126,23 +3057,19 @@ func TestWebsocketClose(t *testing.T) {
})
require.NoError(t, err)
- // Read the first response to ensure subscription is active
var res testenv.WebSocketMessage
require.NoError(t, testenv.WSReadJSON(t, conn, &res))
require.Equal(t, "next", res.Type)
- // Shutdown the router while subscription is active
xEnv.Shutdown()
- // Try to read from the connection to detect the close
_, _, err = conn.NextReader()
require.Error(t, err, "should have received an error when router shuts down")
var closeError *websocket.CloseError
- if assert.ErrorAs(t, err, &closeError) {
- assert.Equal(t, websocket.CloseGoingAway, closeError.Code)
- assert.Equal(t, "Going away", closeError.Text)
- }
+ require.ErrorAs(t, err, &closeError)
+ require.Equal(t, websocket.CloseGoingAway, closeError.Code)
+ require.Equal(t, "Going away", closeError.Text)
})
})
}
diff --git a/router-tests/telemetry/stream_metrics_test.go b/router-tests/telemetry/stream_metrics_test.go
index 131c57508a..f9062dcbd1 100644
--- a/router-tests/telemetry/stream_metrics_test.go
+++ b/router-tests/telemetry/stream_metrics_test.go
@@ -279,7 +279,7 @@ func TestFlakyEventMetrics(t *testing.T) {
MetricReader: metricReader,
RouterConfigJSONTemplate: testenv.ConfigWithEdfsNatsJSONTemplate,
EnableNats: true,
- ModifyEngineExecutionConfiguration: func(ec *config.EngineExecutionConfiguration) { ec.WebSocketClientReadTimeout = time.Second },
+ ModifyEngineExecutionConfiguration: func(ec *config.EngineExecutionConfiguration) { ec.WebSocketServerReadTimeout = time.Second },
MetricOptions: testenv.MetricOptions{EnableOTLPStreamMetrics: true},
}, func(t *testing.T, xEnv *testenv.Environment) {
var subscriptionOne struct {
diff --git a/router-tests/testenv/testdata/config.json b/router-tests/testenv/testdata/config.json
index 01aa5b8445..bc08fc0d5d 100644
--- a/router-tests/testenv/testdata/config.json
+++ b/router-tests/testenv/testdata/config.json
@@ -855,7 +855,8 @@
"headerValue",
"initPayloadValue",
"initialPayload",
- "returnsError"
+ "returnsError",
+ "metadata"
]
},
{
@@ -892,7 +893,15 @@
"unixTime",
"seq",
"total",
- "initialPayload"
+ "initialPayload",
+ "extensions"
+ ]
+ },
+ {
+ "typeName": "SubscribeMetadata",
+ "fieldNames": [
+ "initialPayload",
+ "subscribeExtensions"
]
},
{
@@ -1766,10 +1775,10 @@
},
"federation": {
"enabled": true,
- "serviceSdl": "extend schema\n@link(url: \"https://specs.apollo.dev/federation/v2.5\", import: [\"@authenticated\", \"@composeDirective\", \"@external\", \"@extends\", \"@inaccessible\", \"@interfaceObject\", \"@override\", \"@provides\", \"@key\", \"@requires\", \"@requiresScopes\", \"@shareable\", \"@tag\"])\n\ntype Query {\n \"Returns the value of the received HTTP header.\"\n headerValue(name: String!): String!\n \"Returns the value of the given key in the WS initial payload.\"\n initPayloadValue(key: String!): String!\n initialPayload: Map\n \"Returns response after the given delay\"\n delay(response: String!, ms: Int!): String!\n\n bigResponse(\n artificialDelay: Int! = 0\n bigObjects: Int! = 100\n nestedObjects: Int! = 100\n deeplyNestedObjects: Int! = 100\n ): [BigObject!]!\n\n longResponse(artificialDelay: Int! = 0, bytes: Int!): String\n\n bigAbstractResponse: BigAbstractResponse\n\n rootFieldWithListArg(arg: [String!]!): [String!]!\n rootFieldWithNestedListArg(arg: [[String!]!]!): [[String!]!]!\n rootFieldWithListOfInputArg(arg: [InputType!]!): [InputResponse!]!\n rootFieldWithListOfEnumArg(arg: [EnumType!]!): [EnumType!]!\n rootFieldWithInput(arg: InputArg!): String!\n\n floatField(arg: Float): Float\n\n sharedThings(numOfA: Int! numOfB: Int!): [Thing!]! @shareable\n\n secret: Secret @requiresScopes(scopes: [[\"read:secret\"]])\n}\n\ntype Secret {\n value: String\n}\n\ntype Thing @shareable {\n b: String!\n}\n\ninput InputArg {\n enums: [EnumType!]\n enum: EnumType\n string: String\n strings: [String!]\n}\n\nenum EnumType {\n A\n B\n C\n}\n\ninput InputType {\n arg: String!\n}\n\ntype InputResponse {\n arg: String!\n}\n\nscalar Map\n\ntype TimestampedString {\n \"The value of the string.\"\n value: String!\n \"The timestamp when the response was generated.\"\n unixTime: Int!\n \"Sequence number\"\n seq: Int!\n \"Total number of responses to be sent\"\n total: Int!\n initialPayload: Map\n}\n\ntype Subscription {\n \"Returns a stream with the value of the received HTTP header.\"\n headerValue(name: String!, repeat: Int): TimestampedString!\n \"Returns a stream with the value of value of the given key in the WS initial payload.\"\n initPayloadValue(key: String!, repeat: Int): TimestampedString!\n \"Returns a stream with the value of the WS initial payload.\"\n initialPayload(repeat: Int): Map\n returnsError: String\n}\n\ntype Employee @key(fields: \"id\") {\n id: Int!\n fieldThrowsError: String\n}\n\ntype BigObject {\n nestedObjects: [NestedObject!]!\n}\n\ntype NestedObject {\n deeplyNestedObjects: [DeeplyNestedObject!]!\n}\n\ntype DeeplyNestedObject {\n aFieldOnDeeplyNestedObject: String!\n bFieldOnDeeplyNestedObject: Int!\n cFieldOnDeeplyNestedObject: Boolean!\n dFieldOnDeeplyNestedObject: Float!\n eFieldOnDeeplyNestedObject: String!\n fFieldOnDeeplyNestedObject: Int!\n gFieldOnDeeplyNestedObject: Boolean!\n hFieldOnDeeplyNestedObject: Float!\n iFieldOnDeeplyNestedObject: String!\n jFieldOnDeeplyNestedObject: Int!\n kFieldOnDeeplyNestedObject: Boolean!\n lFieldOnDeeplyNestedObject: Float!\n mFieldOnDeeplyNestedObject: String!\n nFieldOnDeeplyNestedObject: Int!\n oFieldOnDeeplyNestedObject: Boolean!\n pFieldOnDeeplyNestedObject: Float!\n qFieldOnDeeplyNestedObject: String!\n rFieldOnDeeplyNestedObject: Int!\n sFieldOnDeeplyNestedObject: Boolean!\n tFieldOnDeeplyNestedObject: Float!\n uFieldOnDeeplyNestedObject: String!\n vFieldOnDeeplyNestedObject: Int!\n wFieldOnDeeplyNestedObject: Boolean!\n xFieldOnDeeplyNestedObject: Float!\n yFieldOnDeeplyNestedObject: String!\n zFieldOnDeeplyNestedObject: Int!\n}\n\nunion BigAbstractResponse = ABigObject | BBigObject | CBigObject | DBigObject | EBigObject | FBigObject | GBigObject | HBigObject | IBigObject | JBigObject | KBigObject | LBigObject | MBigObject | NBigObject | OBigObject | PBigObject | QBigObject | RBigObject | SBigObject | TBigObject | UBigObject | VBigObject | WBigObject | XBigObject | YBigObject | ZBigObject\n\ntype ABigObject {\n aFieldOnABigObject: String!\n bFieldOnABigObject: Int!\n cFieldOnABigObject: Boolean!\n dFieldOnABigObject: Float!\n eFieldOnABigObject: String!\n fFieldOnABigObject: Int!\n gFieldOnABigObject: Boolean!\n hFieldOnABigObject: Float!\n iFieldOnABigObject: String!\n jFieldOnABigObject: Int!\n kFieldOnABigObject: Boolean!\n lFieldOnABigObject: Float!\n mFieldOnABigObject: String!\n nFieldOnABigObject: Int!\n oFieldOnABigObject: Boolean!\n pFieldOnABigObject: Float!\n qFieldOnABigObject: String!\n rFieldOnABigObject: Int!\n sFieldOnABigObject: Boolean!\n tFieldOnABigObject: Float!\n uFieldOnABigObject: String!\n vFieldOnABigObject: Int!\n wFieldOnABigObject: Boolean!\n xFieldOnABigObject: Float!\n yFieldOnABigObject: String!\n zFieldOnABigObject: Int!\n}\n\ntype BBigObject {\n aFieldOnBBigObject: String!\n bFieldOnBBigObject: Int!\n cFieldOnBBigObject: Boolean!\n dFieldOnBBigObject: Float!\n eFieldOnBBigObject: String!\n fFieldOnBBigObject: Int!\n gFieldOnBBigObject: Boolean!\n hFieldOnBBigObject: Float!\n iFieldOnBBigObject: String!\n jFieldOnBBigObject: Int!\n kFieldOnBBigObject: Boolean!\n lFieldOnBBigObject: Float!\n mFieldOnBBigObject: String!\n nFieldOnBBigObject: Int!\n oFieldOnBBigObject: Boolean!\n pFieldOnBBigObject: Float!\n qFieldOnBBigObject: String!\n rFieldOnBBigObject: Int!\n sFieldOnBBigObject: Boolean!\n tFieldOnBBigObject: Float!\n uFieldOnBBigObject: String!\n vFieldOnBBigObject: Int!\n wFieldOnBBigObject: Boolean!\n xFieldOnBBigObject: Float!\n yFieldOnBBigObject: String!\n zFieldOnBBigObject: Int!\n}\n\ntype CBigObject {\n aFieldOnCBigObject: String!\n bFieldOnCBigObject: Int!\n cFieldOnCBigObject: Boolean!\n dFieldOnCBigObject: Float!\n eFieldOnCBigObject: String!\n fFieldOnCBigObject: Int!\n gFieldOnCBigObject: Boolean!\n hFieldOnCBigObject: Float!\n iFieldOnCBigObject: String!\n jFieldOnCBigObject: Int!\n kFieldOnCBigObject: Boolean!\n lFieldOnCBigObject: Float!\n mFieldOnCBigObject: String!\n nFieldOnCBigObject: Int!\n oFieldOnCBigObject: Boolean!\n pFieldOnCBigObject: Float!\n qFieldOnCBigObject: String!\n rFieldOnCBigObject: Int!\n sFieldOnCBigObject: Boolean!\n tFieldOnCBigObject: Float!\n uFieldOnCBigObject: String!\n vFieldOnCBigObject: Int!\n wFieldOnCBigObject: Boolean!\n xFieldOnCBigObject: Float!\n yFieldOnCBigObject: String!\n zFieldOnCBigObject: Int!\n}\n\ntype DBigObject {\n aFieldOnDBigObject: String!\n bFieldOnDBigObject: Int!\n cFieldOnDBigObject: Boolean!\n dFieldOnDBigObject: Float!\n eFieldOnDBigObject: String!\n fFieldOnDBigObject: Int!\n gFieldOnDBigObject: Boolean!\n hFieldOnDBigObject: Float!\n iFieldOnDBigObject: String!\n jFieldOnDBigObject: Int!\n kFieldOnDBigObject: Boolean!\n lFieldOnDBigObject: Float!\n mFieldOnDBigObject: String!\n nFieldOnDBigObject: Int!\n oFieldOnDBigObject: Boolean!\n pFieldOnDBigObject: Float!\n qFieldOnDBigObject: String!\n rFieldOnDBigObject: Int!\n sFieldOnDBigObject: Boolean!\n tFieldOnDBigObject: Float!\n uFieldOnDBigObject: String!\n vFieldOnDBigObject: Int!\n wFieldOnDBigObject: Boolean!\n xFieldOnDBigObject: Float!\n yFieldOnDBigObject: String!\n zFieldOnDBigObject: Int!\n}\n\ntype EBigObject {\n aFieldOnEBigObject: String!\n bFieldOnEBigObject: Int!\n cFieldOnEBigObject: Boolean!\n dFieldOnEBigObject: Float!\n eFieldOnEBigObject: String!\n fFieldOnEBigObject: Int!\n gFieldOnEBigObject: Boolean!\n hFieldOnEBigObject: Float!\n iFieldOnEBigObject: String!\n jFieldOnEBigObject: Int!\n kFieldOnEBigObject: Boolean!\n lFieldOnEBigObject: Float!\n mFieldOnEBigObject: String!\n nFieldOnEBigObject: Int!\n oFieldOnEBigObject: Boolean!\n pFieldOnEBigObject: Float!\n qFieldOnEBigObject: String!\n rFieldOnEBigObject: Int!\n sFieldOnEBigObject: Boolean!\n tFieldOnEBigObject: Float!\n uFieldOnEBigObject: String!\n vFieldOnEBigObject: Int!\n wFieldOnEBigObject: Boolean!\n xFieldOnEBigObject: Float!\n yFieldOnEBigObject: String!\n zFieldOnEBigObject: Int!\n}\n\ntype FBigObject {\n aFieldOnFBigObject: String!\n bFieldOnFBigObject: Int!\n cFieldOnFBigObject: Boolean!\n dFieldOnFBigObject: Float!\n eFieldOnFBigObject: String!\n fFieldOnFBigObject: Int!\n gFieldOnFBigObject: Boolean!\n hFieldOnFBigObject: Float!\n iFieldOnFBigObject: String!\n jFieldOnFBigObject: Int!\n kFieldOnFBigObject: Boolean!\n lFieldOnFBigObject: Float!\n mFieldOnFBigObject: String!\n nFieldOnFBigObject: Int!\n oFieldOnFBigObject: Boolean!\n pFieldOnFBigObject: Float!\n qFieldOnFBigObject: String!\n rFieldOnFBigObject: Int!\n sFieldOnFBigObject: Boolean!\n tFieldOnFBigObject: Float!\n uFieldOnFBigObject: String!\n vFieldOnFBigObject: Int!\n wFieldOnFBigObject: Boolean!\n xFieldOnFBigObject: Float!\n yFieldOnFBigObject: String!\n zFieldOnFBigObject: Int!\n}\n\ntype GBigObject {\n aFieldOnGBigObject: String!\n bFieldOnGBigObject: Int!\n cFieldOnGBigObject: Boolean!\n dFieldOnGBigObject: Float!\n eFieldOnGBigObject: String!\n fFieldOnGBigObject: Int!\n gFieldOnGBigObject: Boolean!\n hFieldOnGBigObject: Float!\n iFieldOnGBigObject: String!\n jFieldOnGBigObject: Int!\n kFieldOnGBigObject: Boolean!\n lFieldOnGBigObject: Float!\n mFieldOnGBigObject: String!\n nFieldOnGBigObject: Int!\n oFieldOnGBigObject: Boolean!\n pFieldOnGBigObject: Float!\n qFieldOnGBigObject: String!\n rFieldOnGBigObject: Int!\n sFieldOnGBigObject: Boolean!\n tFieldOnGBigObject: Float!\n uFieldOnGBigObject: String!\n vFieldOnGBigObject: Int!\n wFieldOnGBigObject: Boolean!\n xFieldOnGBigObject: Float!\n yFieldOnGBigObject: String!\n zFieldOnGBigObject: Int!\n}\n\ntype HBigObject {\n aFieldOnHBigObject: String!\n bFieldOnHBigObject: Int!\n cFieldOnHBigObject: Boolean!\n dFieldOnHBigObject: Float!\n eFieldOnHBigObject: String!\n fFieldOnHBigObject: Int!\n gFieldOnHBigObject: Boolean!\n hFieldOnHBigObject: Float!\n iFieldOnHBigObject: String!\n jFieldOnHBigObject: Int!\n kFieldOnHBigObject: Boolean!\n lFieldOnHBigObject: Float!\n mFieldOnHBigObject: String!\n nFieldOnHBigObject: Int!\n oFieldOnHBigObject: Boolean!\n pFieldOnHBigObject: Float!\n qFieldOnHBigObject: String!\n rFieldOnHBigObject: Int!\n sFieldOnHBigObject: Boolean!\n tFieldOnHBigObject: Float!\n uFieldOnHBigObject: String!\n vFieldOnHBigObject: Int!\n wFieldOnHBigObject: Boolean!\n xFieldOnHBigObject: Float!\n yFieldOnHBigObject: String!\n zFieldOnHBigObject: Int!\n}\n\ntype IBigObject {\n aFieldOnIBigObject: String!\n bFieldOnIBigObject: Int!\n cFieldOnIBigObject: Boolean!\n dFieldOnIBigObject: Float!\n eFieldOnIBigObject: String!\n fFieldOnIBigObject: Int!\n gFieldOnIBigObject: Boolean!\n hFieldOnIBigObject: Float!\n iFieldOnIBigObject: String!\n jFieldOnIBigObject: Int!\n kFieldOnIBigObject: Boolean!\n lFieldOnIBigObject: Float!\n mFieldOnIBigObject: String!\n nFieldOnIBigObject: Int!\n oFieldOnIBigObject: Boolean!\n pFieldOnIBigObject: Float!\n qFieldOnIBigObject: String!\n rFieldOnIBigObject: Int!\n sFieldOnIBigObject: Boolean!\n tFieldOnIBigObject: Float!\n uFieldOnIBigObject: String!\n vFieldOnIBigObject: Int!\n wFieldOnIBigObject: Boolean!\n xFieldOnIBigObject: Float!\n yFieldOnIBigObject: String!\n zFieldOnIBigObject: Int!\n}\n\ntype JBigObject {\n aFieldOnJBigObject: String!\n bFieldOnJBigObject: Int!\n cFieldOnJBigObject: Boolean!\n dFieldOnJBigObject: Float!\n eFieldOnJBigObject: String!\n fFieldOnJBigObject: Int!\n gFieldOnJBigObject: Boolean!\n hFieldOnJBigObject: Float!\n iFieldOnJBigObject: String!\n jFieldOnJBigObject: Int!\n kFieldOnJBigObject: Boolean!\n lFieldOnJBigObject: Float!\n mFieldOnJBigObject: String!\n nFieldOnJBigObject: Int!\n oFieldOnJBigObject: Boolean!\n pFieldOnJBigObject: Float!\n qFieldOnJBigObject: String!\n rFieldOnJBigObject: Int!\n sFieldOnJBigObject: Boolean!\n tFieldOnJBigObject: Float!\n uFieldOnJBigObject: String!\n vFieldOnJBigObject: Int!\n wFieldOnJBigObject: Boolean!\n xFieldOnJBigObject: Float!\n yFieldOnJBigObject: String!\n zFieldOnJBigObject: Int!\n}\n\ntype KBigObject {\n aFieldOnKBigObject: String!\n bFieldOnKBigObject: Int!\n cFieldOnKBigObject: Boolean!\n dFieldOnKBigObject: Float!\n eFieldOnKBigObject: String!\n fFieldOnKBigObject: Int!\n gFieldOnKBigObject: Boolean!\n hFieldOnKBigObject: Float!\n iFieldOnKBigObject: String!\n jFieldOnKBigObject: Int!\n kFieldOnKBigObject: Boolean!\n lFieldOnKBigObject: Float!\n mFieldOnKBigObject: String!\n nFieldOnKBigObject: Int!\n oFieldOnKBigObject: Boolean!\n pFieldOnKBigObject: Float!\n qFieldOnKBigObject: String!\n rFieldOnKBigObject: Int!\n sFieldOnKBigObject: Boolean!\n tFieldOnKBigObject: Float!\n uFieldOnKBigObject: String!\n vFieldOnKBigObject: Int!\n wFieldOnKBigObject: Boolean!\n xFieldOnKBigObject: Float!\n yFieldOnKBigObject: String!\n zFieldOnKBigObject: Int!\n}\n\ntype LBigObject {\n aFieldOnLBigObject: String!\n bFieldOnLBigObject: Int!\n cFieldOnLBigObject: Boolean!\n dFieldOnLBigObject: Float!\n eFieldOnLBigObject: String!\n fFieldOnLBigObject: Int!\n gFieldOnLBigObject: Boolean!\n hFieldOnLBigObject: Float!\n iFieldOnLBigObject: String!\n jFieldOnLBigObject: Int!\n kFieldOnLBigObject: Boolean!\n lFieldOnLBigObject: Float!\n mFieldOnLBigObject: String!\n nFieldOnLBigObject: Int!\n oFieldOnLBigObject: Boolean!\n pFieldOnLBigObject: Float!\n qFieldOnLBigObject: String!\n rFieldOnLBigObject: Int!\n sFieldOnLBigObject: Boolean!\n tFieldOnLBigObject: Float!\n uFieldOnLBigObject: String!\n vFieldOnLBigObject: Int!\n wFieldOnLBigObject: Boolean!\n xFieldOnLBigObject: Float!\n yFieldOnLBigObject: String!\n zFieldOnLBigObject: Int!\n}\n\ntype MBigObject {\n aFieldOnMBigObject: String!\n bFieldOnMBigObject: Int!\n cFieldOnMBigObject: Boolean!\n dFieldOnMBigObject: Float!\n eFieldOnMBigObject: String!\n fFieldOnMBigObject: Int!\n gFieldOnMBigObject: Boolean!\n hFieldOnMBigObject: Float!\n iFieldOnMBigObject: String!\n jFieldOnMBigObject: Int!\n kFieldOnMBigObject: Boolean!\n lFieldOnMBigObject: Float!\n mFieldOnMBigObject: String!\n nFieldOnMBigObject: Int!\n oFieldOnMBigObject: Boolean!\n pFieldOnMBigObject: Float!\n qFieldOnMBigObject: String!\n rFieldOnMBigObject: Int!\n sFieldOnMBigObject: Boolean!\n tFieldOnMBigObject: Float!\n uFieldOnMBigObject: String!\n vFieldOnMBigObject: Int!\n wFieldOnMBigObject: Boolean!\n xFieldOnMBigObject: Float!\n yFieldOnMBigObject: String!\n zFieldOnMBigObject: Int!\n}\n\ntype NBigObject {\n aFieldOnNBigObject: String!\n bFieldOnNBigObject: Int!\n cFieldOnNBigObject: Boolean!\n dFieldOnNBigObject: Float!\n eFieldOnNBigObject: String!\n fFieldOnNBigObject: Int!\n gFieldOnNBigObject: Boolean!\n hFieldOnNBigObject: Float!\n iFieldOnNBigObject: String!\n jFieldOnNBigObject: Int!\n kFieldOnNBigObject: Boolean!\n lFieldOnNBigObject: Float!\n mFieldOnNBigObject: String!\n nFieldOnNBigObject: Int!\n oFieldOnNBigObject: Boolean!\n pFieldOnNBigObject: Float!\n qFieldOnNBigObject: String!\n rFieldOnNBigObject: Int!\n sFieldOnNBigObject: Boolean!\n tFieldOnNBigObject: Float!\n uFieldOnNBigObject: String!\n vFieldOnNBigObject: Int!\n wFieldOnNBigObject: Boolean!\n xFieldOnNBigObject: Float!\n yFieldOnNBigObject: String!\n zFieldOnNBigObject: Int!\n}\n\ntype OBigObject {\n aFieldOnOBigObject: String!\n bFieldOnOBigObject: Int!\n cFieldOnOBigObject: Boolean!\n dFieldOnOBigObject: Float!\n eFieldOnOBigObject: String!\n fFieldOnOBigObject: Int!\n gFieldOnOBigObject: Boolean!\n hFieldOnOBigObject: Float!\n iFieldOnOBigObject: String!\n jFieldOnOBigObject: Int!\n kFieldOnOBigObject: Boolean!\n lFieldOnOBigObject: Float!\n mFieldOnOBigObject: String!\n nFieldOnOBigObject: Int!\n oFieldOnOBigObject: Boolean!\n pFieldOnOBigObject: Float!\n qFieldOnOBigObject: String!\n rFieldOnOBigObject: Int!\n sFieldOnOBigObject: Boolean!\n tFieldOnOBigObject: Float!\n uFieldOnOBigObject: String!\n vFieldOnOBigObject: Int!\n wFieldOnOBigObject: Boolean!\n xFieldOnOBigObject: Float!\n yFieldOnOBigObject: String!\n zFieldOnOBigObject: Int!\n}\n\ntype PBigObject {\n aFieldOnPBigObject: String!\n bFieldOnPBigObject: Int!\n cFieldOnPBigObject: Boolean!\n dFieldOnPBigObject: Float!\n eFieldOnPBigObject: String!\n fFieldOnPBigObject: Int!\n gFieldOnPBigObject: Boolean!\n hFieldOnPBigObject: Float!\n iFieldOnPBigObject: String!\n jFieldOnPBigObject: Int!\n kFieldOnPBigObject: Boolean!\n lFieldOnPBigObject: Float!\n mFieldOnPBigObject: String!\n nFieldOnPBigObject: Int!\n oFieldOnPBigObject: Boolean!\n pFieldOnPBigObject: Float!\n qFieldOnPBigObject: String!\n rFieldOnPBigObject: Int!\n sFieldOnPBigObject: Boolean!\n tFieldOnPBigObject: Float!\n uFieldOnPBigObject: String!\n vFieldOnPBigObject: Int!\n wFieldOnPBigObject: Boolean!\n xFieldOnPBigObject: Float!\n yFieldOnPBigObject: String!\n zFieldOnPBigObject: Int!\n}\n\ntype QBigObject {\n aFieldOnQBigObject: String!\n bFieldOnQBigObject: Int!\n cFieldOnQBigObject: Boolean!\n dFieldOnQBigObject: Float!\n eFieldOnQBigObject: String!\n fFieldOnQBigObject: Int!\n gFieldOnQBigObject: Boolean!\n hFieldOnQBigObject: Float!\n iFieldOnQBigObject: String!\n jFieldOnQBigObject: Int!\n kFieldOnQBigObject: Boolean!\n lFieldOnQBigObject: Float!\n mFieldOnQBigObject: String!\n nFieldOnQBigObject: Int!\n oFieldOnQBigObject: Boolean!\n pFieldOnQBigObject: Float!\n qFieldOnQBigObject: String!\n rFieldOnQBigObject: Int!\n sFieldOnQBigObject: Boolean!\n tFieldOnQBigObject: Float!\n uFieldOnQBigObject: String!\n vFieldOnQBigObject: Int!\n wFieldOnQBigObject: Boolean!\n xFieldOnQBigObject: Float!\n yFieldOnQBigObject: String!\n zFieldOnQBigObject: Int!\n}\n\ntype RBigObject {\n aFieldOnRBigObject: String!\n bFieldOnRBigObject: Int!\n cFieldOnRBigObject: Boolean!\n dFieldOnRBigObject: Float!\n eFieldOnRBigObject: String!\n fFieldOnRBigObject: Int!\n gFieldOnRBigObject: Boolean!\n hFieldOnRBigObject: Float!\n iFieldOnRBigObject: String!\n jFieldOnRBigObject: Int!\n kFieldOnRBigObject: Boolean!\n lFieldOnRBigObject: Float!\n mFieldOnRBigObject: String!\n nFieldOnRBigObject: Int!\n oFieldOnRBigObject: Boolean!\n pFieldOnRBigObject: Float!\n qFieldOnRBigObject: String!\n rFieldOnRBigObject: Int!\n sFieldOnRBigObject: Boolean!\n tFieldOnRBigObject: Float!\n uFieldOnRBigObject: String!\n vFieldOnRBigObject: Int!\n wFieldOnRBigObject: Boolean!\n xFieldOnRBigObject: Float!\n yFieldOnRBigObject: String!\n zFieldOnRBigObject: Int!\n}\n\ntype SBigObject {\n aFieldOnSBigObject: String!\n bFieldOnSBigObject: Int!\n cFieldOnSBigObject: Boolean!\n dFieldOnSBigObject: Float!\n eFieldOnSBigObject: String!\n fFieldOnSBigObject: Int!\n gFieldOnSBigObject: Boolean!\n hFieldOnSBigObject: Float!\n iFieldOnSBigObject: String!\n jFieldOnSBigObject: Int!\n kFieldOnSBigObject: Boolean!\n lFieldOnSBigObject: Float!\n mFieldOnSBigObject: String!\n nFieldOnSBigObject: Int!\n oFieldOnSBigObject: Boolean!\n pFieldOnSBigObject: Float!\n qFieldOnSBigObject: String!\n rFieldOnSBigObject: Int!\n sFieldOnSBigObject: Boolean!\n tFieldOnSBigObject: Float!\n uFieldOnSBigObject: String!\n vFieldOnSBigObject: Int!\n wFieldOnSBigObject: Boolean!\n xFieldOnSBigObject: Float!\n yFieldOnSBigObject: String!\n zFieldOnSBigObject: Int!\n}\n\ntype TBigObject {\n aFieldOnTBigObject: String!\n bFieldOnTBigObject: Int!\n cFieldOnTBigObject: Boolean!\n dFieldOnTBigObject: Float!\n eFieldOnTBigObject: String!\n fFieldOnTBigObject: Int!\n gFieldOnTBigObject: Boolean!\n hFieldOnTBigObject: Float!\n iFieldOnTBigObject: String!\n jFieldOnTBigObject: Int!\n kFieldOnTBigObject: Boolean!\n lFieldOnTBigObject: Float!\n mFieldOnTBigObject: String!\n nFieldOnTBigObject: Int!\n oFieldOnTBigObject: Boolean!\n pFieldOnTBigObject: Float!\n qFieldOnTBigObject: String!\n rFieldOnTBigObject: Int!\n sFieldOnTBigObject: Boolean!\n tFieldOnTBigObject: Float!\n uFieldOnTBigObject: String!\n vFieldOnTBigObject: Int!\n wFieldOnTBigObject: Boolean!\n xFieldOnTBigObject: Float!\n yFieldOnTBigObject: String!\n zFieldOnTBigObject: Int!\n}\n\ntype UBigObject {\n aFieldOnUBigObject: String!\n bFieldOnUBigObject: Int!\n cFieldOnUBigObject: Boolean!\n dFieldOnUBigObject: Float!\n eFieldOnUBigObject: String!\n fFieldOnUBigObject: Int!\n gFieldOnUBigObject: Boolean!\n hFieldOnUBigObject: Float!\n iFieldOnUBigObject: String!\n jFieldOnUBigObject: Int!\n kFieldOnUBigObject: Boolean!\n lFieldOnUBigObject: Float!\n mFieldOnUBigObject: String!\n nFieldOnUBigObject: Int!\n oFieldOnUBigObject: Boolean!\n pFieldOnUBigObject: Float!\n qFieldOnUBigObject: String!\n rFieldOnUBigObject: Int!\n sFieldOnUBigObject: Boolean!\n tFieldOnUBigObject: Float!\n uFieldOnUBigObject: String!\n vFieldOnUBigObject: Int!\n wFieldOnUBigObject: Boolean!\n xFieldOnUBigObject: Float!\n yFieldOnUBigObject: String!\n zFieldOnUBigObject: Int!\n}\n\ntype VBigObject {\n aFieldOnVBigObject: String!\n bFieldOnVBigObject: Int!\n cFieldOnVBigObject: Boolean!\n dFieldOnVBigObject: Float!\n eFieldOnVBigObject: String!\n fFieldOnVBigObject: Int!\n gFieldOnVBigObject: Boolean!\n hFieldOnVBigObject: Float!\n iFieldOnVBigObject: String!\n jFieldOnVBigObject: Int!\n kFieldOnVBigObject: Boolean!\n lFieldOnVBigObject: Float!\n mFieldOnVBigObject: String!\n nFieldOnVBigObject: Int!\n oFieldOnVBigObject: Boolean!\n pFieldOnVBigObject: Float!\n qFieldOnVBigObject: String!\n rFieldOnVBigObject: Int!\n sFieldOnVBigObject: Boolean!\n tFieldOnVBigObject: Float!\n uFieldOnVBigObject: String!\n vFieldOnVBigObject: Int!\n wFieldOnVBigObject: Boolean!\n xFieldOnVBigObject: Float!\n yFieldOnVBigObject: String!\n zFieldOnVBigObject: Int!\n}\n\ntype WBigObject {\n aFieldOnWBigObject: String!\n bFieldOnWBigObject: Int!\n cFieldOnWBigObject: Boolean!\n dFieldOnWBigObject: Float!\n eFieldOnWBigObject: String!\n fFieldOnWBigObject: Int!\n gFieldOnWBigObject: Boolean!\n hFieldOnWBigObject: Float!\n iFieldOnWBigObject: String!\n jFieldOnWBigObject: Int!\n kFieldOnWBigObject: Boolean!\n lFieldOnWBigObject: Float!\n mFieldOnWBigObject: String!\n nFieldOnWBigObject: Int!\n oFieldOnWBigObject: Boolean!\n pFieldOnWBigObject: Float!\n qFieldOnWBigObject: String!\n rFieldOnWBigObject: Int!\n sFieldOnWBigObject: Boolean!\n tFieldOnWBigObject: Float!\n uFieldOnWBigObject: String!\n vFieldOnWBigObject: Int!\n wFieldOnWBigObject: Boolean!\n xFieldOnWBigObject: Float!\n yFieldOnWBigObject: String!\n zFieldOnWBigObject: Int!\n}\n\ntype XBigObject {\n aFieldOnXBigObject: String!\n bFieldOnXBigObject: Int!\n cFieldOnXBigObject: Boolean!\n dFieldOnXBigObject: Float!\n eFieldOnXBigObject: String!\n fFieldOnXBigObject: Int!\n gFieldOnXBigObject: Boolean!\n hFieldOnXBigObject: Float!\n iFieldOnXBigObject: String!\n jFieldOnXBigObject: Int!\n kFieldOnXBigObject: Boolean!\n lFieldOnXBigObject: Float!\n mFieldOnXBigObject: String!\n nFieldOnXBigObject: Int!\n oFieldOnXBigObject: Boolean!\n pFieldOnXBigObject: Float!\n qFieldOnXBigObject: String!\n rFieldOnXBigObject: Int!\n sFieldOnXBigObject: Boolean!\n tFieldOnXBigObject: Float!\n uFieldOnXBigObject: String!\n vFieldOnXBigObject: Int!\n wFieldOnXBigObject: Boolean!\n xFieldOnXBigObject: Float!\n yFieldOnXBigObject: String!\n zFieldOnXBigObject: Int!\n}\n\ntype YBigObject {\n aFieldOnYBigObject: String!\n bFieldOnYBigObject: Int!\n cFieldOnYBigObject: Boolean!\n dFieldOnYBigObject: Float!\n eFieldOnYBigObject: String!\n fFieldOnYBigObject: Int!\n gFieldOnYBigObject: Boolean!\n hFieldOnYBigObject: Float!\n iFieldOnYBigObject: String!\n jFieldOnYBigObject: Int!\n kFieldOnYBigObject: Boolean!\n lFieldOnYBigObject: Float!\n mFieldOnYBigObject: String!\n nFieldOnYBigObject: Int!\n oFieldOnYBigObject: Boolean!\n pFieldOnYBigObject: Float!\n qFieldOnYBigObject: String!\n rFieldOnYBigObject: Int!\n sFieldOnYBigObject: Boolean!\n tFieldOnYBigObject: Float!\n uFieldOnYBigObject: String!\n vFieldOnYBigObject: Int!\n wFieldOnYBigObject: Boolean!\n xFieldOnYBigObject: Float!\n yFieldOnYBigObject: String!\n zFieldOnYBigObject: Int!\n}\n\ntype ZBigObject {\n aFieldOnZBigObject: String!\n bFieldOnZBigObject: Int!\n cFieldOnZBigObject: Boolean!\n dFieldOnZBigObject: Float!\n eFieldOnZBigObject: String!\n fFieldOnZBigObject: Int!\n gFieldOnZBigObject: Boolean!\n hFieldOnZBigObject: Float!\n iFieldOnZBigObject: String!\n jFieldOnZBigObject: Int!\n kFieldOnZBigObject: Boolean!\n lFieldOnZBigObject: Float!\n mFieldOnZBigObject: String!\n nFieldOnZBigObject: Int!\n oFieldOnZBigObject: Boolean!\n pFieldOnZBigObject: Float!\n qFieldOnZBigObject: String!\n rFieldOnZBigObject: Int!\n sFieldOnZBigObject: Boolean!\n tFieldOnZBigObject: Float!\n uFieldOnZBigObject: String!\n vFieldOnZBigObject: Int!\n wFieldOnZBigObject: Boolean!\n xFieldOnZBigObject: Float!\n yFieldOnZBigObject: String!\n zFieldOnZBigObject: Int!\n}"
+ "serviceSdl": "extend schema\n@link(url: \"https://specs.apollo.dev/federation/v2.5\", import: [\"@authenticated\", \"@composeDirective\", \"@external\", \"@extends\", \"@inaccessible\", \"@interfaceObject\", \"@override\", \"@provides\", \"@key\", \"@requires\", \"@requiresScopes\", \"@shareable\", \"@tag\"])\n\ntype Query {\n \"Returns the value of the received HTTP header.\"\n headerValue(name: String!): String!\n \"Returns the value of the given key in the WS initial payload.\"\n initPayloadValue(key: String!): String!\n initialPayload: Map\n \"Returns response after the given delay\"\n delay(response: String!, ms: Int!): String!\n\n bigResponse(\n artificialDelay: Int! = 0\n bigObjects: Int! = 100\n nestedObjects: Int! = 100\n deeplyNestedObjects: Int! = 100\n ): [BigObject!]!\n\n longResponse(artificialDelay: Int! = 0, bytes: Int!): String\n\n bigAbstractResponse: BigAbstractResponse\n\n rootFieldWithListArg(arg: [String!]!): [String!]!\n rootFieldWithNestedListArg(arg: [[String!]!]!): [[String!]!]!\n rootFieldWithListOfInputArg(arg: [InputType!]!): [InputResponse!]!\n rootFieldWithListOfEnumArg(arg: [EnumType!]!): [EnumType!]!\n rootFieldWithInput(arg: InputArg!): String!\n\n floatField(arg: Float): Float\n\n sharedThings(numOfA: Int! numOfB: Int!): [Thing!]! @shareable\n\n secret: Secret @requiresScopes(scopes: [[\"read:secret\"]])\n}\n\ntype Secret {\n value: String\n}\n\ntype Thing @shareable {\n b: String!\n}\n\ninput InputArg {\n enums: [EnumType!]\n enum: EnumType\n string: String\n strings: [String!]\n}\n\nenum EnumType {\n A\n B\n C\n}\n\ninput InputType {\n arg: String!\n}\n\ntype InputResponse {\n arg: String!\n}\n\nscalar Map\n\ntype TimestampedString {\n \"The value of the string.\"\n value: String!\n \"The timestamp when the response was generated.\"\n unixTime: Int!\n \"Sequence number\"\n seq: Int!\n \"Total number of responses to be sent\"\n total: Int!\n initialPayload: Map\n extensions: Map\n}\n\ntype SubscribeMetadata {\n initialPayload: Map\n subscribeExtensions: Map\n}\n\ntype Subscription {\n \"Returns a stream with the value of the received HTTP header.\"\n headerValue(name: String!, repeat: Int): TimestampedString!\n \"Returns a stream with the value of value of the given key in the WS initial payload.\"\n initPayloadValue(key: String!, repeat: Int): TimestampedString!\n \"Returns a stream with the value of the WS initial payload.\"\n initialPayload(repeat: Int): Map\n returnsError: String!\n \"Returns a stream with the values of the WS initial payload and subscribe extensions\"\n metadata(repeat: Int! = 1): SubscribeMetadata!\n}\n\ntype Employee @key(fields: \"id\") {\n id: Int!\n fieldThrowsError: String\n}\n\ntype BigObject {\n nestedObjects: [NestedObject!]!\n}\n\ntype NestedObject {\n deeplyNestedObjects: [DeeplyNestedObject!]!\n}\n\ntype DeeplyNestedObject {\n aFieldOnDeeplyNestedObject: String!\n bFieldOnDeeplyNestedObject: Int!\n cFieldOnDeeplyNestedObject: Boolean!\n dFieldOnDeeplyNestedObject: Float!\n eFieldOnDeeplyNestedObject: String!\n fFieldOnDeeplyNestedObject: Int!\n gFieldOnDeeplyNestedObject: Boolean!\n hFieldOnDeeplyNestedObject: Float!\n iFieldOnDeeplyNestedObject: String!\n jFieldOnDeeplyNestedObject: Int!\n kFieldOnDeeplyNestedObject: Boolean!\n lFieldOnDeeplyNestedObject: Float!\n mFieldOnDeeplyNestedObject: String!\n nFieldOnDeeplyNestedObject: Int!\n oFieldOnDeeplyNestedObject: Boolean!\n pFieldOnDeeplyNestedObject: Float!\n qFieldOnDeeplyNestedObject: String!\n rFieldOnDeeplyNestedObject: Int!\n sFieldOnDeeplyNestedObject: Boolean!\n tFieldOnDeeplyNestedObject: Float!\n uFieldOnDeeplyNestedObject: String!\n vFieldOnDeeplyNestedObject: Int!\n wFieldOnDeeplyNestedObject: Boolean!\n xFieldOnDeeplyNestedObject: Float!\n yFieldOnDeeplyNestedObject: String!\n zFieldOnDeeplyNestedObject: Int!\n}\n\nunion BigAbstractResponse = ABigObject | BBigObject | CBigObject | DBigObject | EBigObject | FBigObject | GBigObject | HBigObject | IBigObject | JBigObject | KBigObject | LBigObject | MBigObject | NBigObject | OBigObject | PBigObject | QBigObject | RBigObject | SBigObject | TBigObject | UBigObject | VBigObject | WBigObject | XBigObject | YBigObject | ZBigObject\n\ntype ABigObject {\n aFieldOnABigObject: String!\n bFieldOnABigObject: Int!\n cFieldOnABigObject: Boolean!\n dFieldOnABigObject: Float!\n eFieldOnABigObject: String!\n fFieldOnABigObject: Int!\n gFieldOnABigObject: Boolean!\n hFieldOnABigObject: Float!\n iFieldOnABigObject: String!\n jFieldOnABigObject: Int!\n kFieldOnABigObject: Boolean!\n lFieldOnABigObject: Float!\n mFieldOnABigObject: String!\n nFieldOnABigObject: Int!\n oFieldOnABigObject: Boolean!\n pFieldOnABigObject: Float!\n qFieldOnABigObject: String!\n rFieldOnABigObject: Int!\n sFieldOnABigObject: Boolean!\n tFieldOnABigObject: Float!\n uFieldOnABigObject: String!\n vFieldOnABigObject: Int!\n wFieldOnABigObject: Boolean!\n xFieldOnABigObject: Float!\n yFieldOnABigObject: String!\n zFieldOnABigObject: Int!\n}\n\ntype BBigObject {\n aFieldOnBBigObject: String!\n bFieldOnBBigObject: Int!\n cFieldOnBBigObject: Boolean!\n dFieldOnBBigObject: Float!\n eFieldOnBBigObject: String!\n fFieldOnBBigObject: Int!\n gFieldOnBBigObject: Boolean!\n hFieldOnBBigObject: Float!\n iFieldOnBBigObject: String!\n jFieldOnBBigObject: Int!\n kFieldOnBBigObject: Boolean!\n lFieldOnBBigObject: Float!\n mFieldOnBBigObject: String!\n nFieldOnBBigObject: Int!\n oFieldOnBBigObject: Boolean!\n pFieldOnBBigObject: Float!\n qFieldOnBBigObject: String!\n rFieldOnBBigObject: Int!\n sFieldOnBBigObject: Boolean!\n tFieldOnBBigObject: Float!\n uFieldOnBBigObject: String!\n vFieldOnBBigObject: Int!\n wFieldOnBBigObject: Boolean!\n xFieldOnBBigObject: Float!\n yFieldOnBBigObject: String!\n zFieldOnBBigObject: Int!\n}\n\ntype CBigObject {\n aFieldOnCBigObject: String!\n bFieldOnCBigObject: Int!\n cFieldOnCBigObject: Boolean!\n dFieldOnCBigObject: Float!\n eFieldOnCBigObject: String!\n fFieldOnCBigObject: Int!\n gFieldOnCBigObject: Boolean!\n hFieldOnCBigObject: Float!\n iFieldOnCBigObject: String!\n jFieldOnCBigObject: Int!\n kFieldOnCBigObject: Boolean!\n lFieldOnCBigObject: Float!\n mFieldOnCBigObject: String!\n nFieldOnCBigObject: Int!\n oFieldOnCBigObject: Boolean!\n pFieldOnCBigObject: Float!\n qFieldOnCBigObject: String!\n rFieldOnCBigObject: Int!\n sFieldOnCBigObject: Boolean!\n tFieldOnCBigObject: Float!\n uFieldOnCBigObject: String!\n vFieldOnCBigObject: Int!\n wFieldOnCBigObject: Boolean!\n xFieldOnCBigObject: Float!\n yFieldOnCBigObject: String!\n zFieldOnCBigObject: Int!\n}\n\ntype DBigObject {\n aFieldOnDBigObject: String!\n bFieldOnDBigObject: Int!\n cFieldOnDBigObject: Boolean!\n dFieldOnDBigObject: Float!\n eFieldOnDBigObject: String!\n fFieldOnDBigObject: Int!\n gFieldOnDBigObject: Boolean!\n hFieldOnDBigObject: Float!\n iFieldOnDBigObject: String!\n jFieldOnDBigObject: Int!\n kFieldOnDBigObject: Boolean!\n lFieldOnDBigObject: Float!\n mFieldOnDBigObject: String!\n nFieldOnDBigObject: Int!\n oFieldOnDBigObject: Boolean!\n pFieldOnDBigObject: Float!\n qFieldOnDBigObject: String!\n rFieldOnDBigObject: Int!\n sFieldOnDBigObject: Boolean!\n tFieldOnDBigObject: Float!\n uFieldOnDBigObject: String!\n vFieldOnDBigObject: Int!\n wFieldOnDBigObject: Boolean!\n xFieldOnDBigObject: Float!\n yFieldOnDBigObject: String!\n zFieldOnDBigObject: Int!\n}\n\ntype EBigObject {\n aFieldOnEBigObject: String!\n bFieldOnEBigObject: Int!\n cFieldOnEBigObject: Boolean!\n dFieldOnEBigObject: Float!\n eFieldOnEBigObject: String!\n fFieldOnEBigObject: Int!\n gFieldOnEBigObject: Boolean!\n hFieldOnEBigObject: Float!\n iFieldOnEBigObject: String!\n jFieldOnEBigObject: Int!\n kFieldOnEBigObject: Boolean!\n lFieldOnEBigObject: Float!\n mFieldOnEBigObject: String!\n nFieldOnEBigObject: Int!\n oFieldOnEBigObject: Boolean!\n pFieldOnEBigObject: Float!\n qFieldOnEBigObject: String!\n rFieldOnEBigObject: Int!\n sFieldOnEBigObject: Boolean!\n tFieldOnEBigObject: Float!\n uFieldOnEBigObject: String!\n vFieldOnEBigObject: Int!\n wFieldOnEBigObject: Boolean!\n xFieldOnEBigObject: Float!\n yFieldOnEBigObject: String!\n zFieldOnEBigObject: Int!\n}\n\ntype FBigObject {\n aFieldOnFBigObject: String!\n bFieldOnFBigObject: Int!\n cFieldOnFBigObject: Boolean!\n dFieldOnFBigObject: Float!\n eFieldOnFBigObject: String!\n fFieldOnFBigObject: Int!\n gFieldOnFBigObject: Boolean!\n hFieldOnFBigObject: Float!\n iFieldOnFBigObject: String!\n jFieldOnFBigObject: Int!\n kFieldOnFBigObject: Boolean!\n lFieldOnFBigObject: Float!\n mFieldOnFBigObject: String!\n nFieldOnFBigObject: Int!\n oFieldOnFBigObject: Boolean!\n pFieldOnFBigObject: Float!\n qFieldOnFBigObject: String!\n rFieldOnFBigObject: Int!\n sFieldOnFBigObject: Boolean!\n tFieldOnFBigObject: Float!\n uFieldOnFBigObject: String!\n vFieldOnFBigObject: Int!\n wFieldOnFBigObject: Boolean!\n xFieldOnFBigObject: Float!\n yFieldOnFBigObject: String!\n zFieldOnFBigObject: Int!\n}\n\ntype GBigObject {\n aFieldOnGBigObject: String!\n bFieldOnGBigObject: Int!\n cFieldOnGBigObject: Boolean!\n dFieldOnGBigObject: Float!\n eFieldOnGBigObject: String!\n fFieldOnGBigObject: Int!\n gFieldOnGBigObject: Boolean!\n hFieldOnGBigObject: Float!\n iFieldOnGBigObject: String!\n jFieldOnGBigObject: Int!\n kFieldOnGBigObject: Boolean!\n lFieldOnGBigObject: Float!\n mFieldOnGBigObject: String!\n nFieldOnGBigObject: Int!\n oFieldOnGBigObject: Boolean!\n pFieldOnGBigObject: Float!\n qFieldOnGBigObject: String!\n rFieldOnGBigObject: Int!\n sFieldOnGBigObject: Boolean!\n tFieldOnGBigObject: Float!\n uFieldOnGBigObject: String!\n vFieldOnGBigObject: Int!\n wFieldOnGBigObject: Boolean!\n xFieldOnGBigObject: Float!\n yFieldOnGBigObject: String!\n zFieldOnGBigObject: Int!\n}\n\ntype HBigObject {\n aFieldOnHBigObject: String!\n bFieldOnHBigObject: Int!\n cFieldOnHBigObject: Boolean!\n dFieldOnHBigObject: Float!\n eFieldOnHBigObject: String!\n fFieldOnHBigObject: Int!\n gFieldOnHBigObject: Boolean!\n hFieldOnHBigObject: Float!\n iFieldOnHBigObject: String!\n jFieldOnHBigObject: Int!\n kFieldOnHBigObject: Boolean!\n lFieldOnHBigObject: Float!\n mFieldOnHBigObject: String!\n nFieldOnHBigObject: Int!\n oFieldOnHBigObject: Boolean!\n pFieldOnHBigObject: Float!\n qFieldOnHBigObject: String!\n rFieldOnHBigObject: Int!\n sFieldOnHBigObject: Boolean!\n tFieldOnHBigObject: Float!\n uFieldOnHBigObject: String!\n vFieldOnHBigObject: Int!\n wFieldOnHBigObject: Boolean!\n xFieldOnHBigObject: Float!\n yFieldOnHBigObject: String!\n zFieldOnHBigObject: Int!\n}\n\ntype IBigObject {\n aFieldOnIBigObject: String!\n bFieldOnIBigObject: Int!\n cFieldOnIBigObject: Boolean!\n dFieldOnIBigObject: Float!\n eFieldOnIBigObject: String!\n fFieldOnIBigObject: Int!\n gFieldOnIBigObject: Boolean!\n hFieldOnIBigObject: Float!\n iFieldOnIBigObject: String!\n jFieldOnIBigObject: Int!\n kFieldOnIBigObject: Boolean!\n lFieldOnIBigObject: Float!\n mFieldOnIBigObject: String!\n nFieldOnIBigObject: Int!\n oFieldOnIBigObject: Boolean!\n pFieldOnIBigObject: Float!\n qFieldOnIBigObject: String!\n rFieldOnIBigObject: Int!\n sFieldOnIBigObject: Boolean!\n tFieldOnIBigObject: Float!\n uFieldOnIBigObject: String!\n vFieldOnIBigObject: Int!\n wFieldOnIBigObject: Boolean!\n xFieldOnIBigObject: Float!\n yFieldOnIBigObject: String!\n zFieldOnIBigObject: Int!\n}\n\ntype JBigObject {\n aFieldOnJBigObject: String!\n bFieldOnJBigObject: Int!\n cFieldOnJBigObject: Boolean!\n dFieldOnJBigObject: Float!\n eFieldOnJBigObject: String!\n fFieldOnJBigObject: Int!\n gFieldOnJBigObject: Boolean!\n hFieldOnJBigObject: Float!\n iFieldOnJBigObject: String!\n jFieldOnJBigObject: Int!\n kFieldOnJBigObject: Boolean!\n lFieldOnJBigObject: Float!\n mFieldOnJBigObject: String!\n nFieldOnJBigObject: Int!\n oFieldOnJBigObject: Boolean!\n pFieldOnJBigObject: Float!\n qFieldOnJBigObject: String!\n rFieldOnJBigObject: Int!\n sFieldOnJBigObject: Boolean!\n tFieldOnJBigObject: Float!\n uFieldOnJBigObject: String!\n vFieldOnJBigObject: Int!\n wFieldOnJBigObject: Boolean!\n xFieldOnJBigObject: Float!\n yFieldOnJBigObject: String!\n zFieldOnJBigObject: Int!\n}\n\ntype KBigObject {\n aFieldOnKBigObject: String!\n bFieldOnKBigObject: Int!\n cFieldOnKBigObject: Boolean!\n dFieldOnKBigObject: Float!\n eFieldOnKBigObject: String!\n fFieldOnKBigObject: Int!\n gFieldOnKBigObject: Boolean!\n hFieldOnKBigObject: Float!\n iFieldOnKBigObject: String!\n jFieldOnKBigObject: Int!\n kFieldOnKBigObject: Boolean!\n lFieldOnKBigObject: Float!\n mFieldOnKBigObject: String!\n nFieldOnKBigObject: Int!\n oFieldOnKBigObject: Boolean!\n pFieldOnKBigObject: Float!\n qFieldOnKBigObject: String!\n rFieldOnKBigObject: Int!\n sFieldOnKBigObject: Boolean!\n tFieldOnKBigObject: Float!\n uFieldOnKBigObject: String!\n vFieldOnKBigObject: Int!\n wFieldOnKBigObject: Boolean!\n xFieldOnKBigObject: Float!\n yFieldOnKBigObject: String!\n zFieldOnKBigObject: Int!\n}\n\ntype LBigObject {\n aFieldOnLBigObject: String!\n bFieldOnLBigObject: Int!\n cFieldOnLBigObject: Boolean!\n dFieldOnLBigObject: Float!\n eFieldOnLBigObject: String!\n fFieldOnLBigObject: Int!\n gFieldOnLBigObject: Boolean!\n hFieldOnLBigObject: Float!\n iFieldOnLBigObject: String!\n jFieldOnLBigObject: Int!\n kFieldOnLBigObject: Boolean!\n lFieldOnLBigObject: Float!\n mFieldOnLBigObject: String!\n nFieldOnLBigObject: Int!\n oFieldOnLBigObject: Boolean!\n pFieldOnLBigObject: Float!\n qFieldOnLBigObject: String!\n rFieldOnLBigObject: Int!\n sFieldOnLBigObject: Boolean!\n tFieldOnLBigObject: Float!\n uFieldOnLBigObject: String!\n vFieldOnLBigObject: Int!\n wFieldOnLBigObject: Boolean!\n xFieldOnLBigObject: Float!\n yFieldOnLBigObject: String!\n zFieldOnLBigObject: Int!\n}\n\ntype MBigObject {\n aFieldOnMBigObject: String!\n bFieldOnMBigObject: Int!\n cFieldOnMBigObject: Boolean!\n dFieldOnMBigObject: Float!\n eFieldOnMBigObject: String!\n fFieldOnMBigObject: Int!\n gFieldOnMBigObject: Boolean!\n hFieldOnMBigObject: Float!\n iFieldOnMBigObject: String!\n jFieldOnMBigObject: Int!\n kFieldOnMBigObject: Boolean!\n lFieldOnMBigObject: Float!\n mFieldOnMBigObject: String!\n nFieldOnMBigObject: Int!\n oFieldOnMBigObject: Boolean!\n pFieldOnMBigObject: Float!\n qFieldOnMBigObject: String!\n rFieldOnMBigObject: Int!\n sFieldOnMBigObject: Boolean!\n tFieldOnMBigObject: Float!\n uFieldOnMBigObject: String!\n vFieldOnMBigObject: Int!\n wFieldOnMBigObject: Boolean!\n xFieldOnMBigObject: Float!\n yFieldOnMBigObject: String!\n zFieldOnMBigObject: Int!\n}\n\ntype NBigObject {\n aFieldOnNBigObject: String!\n bFieldOnNBigObject: Int!\n cFieldOnNBigObject: Boolean!\n dFieldOnNBigObject: Float!\n eFieldOnNBigObject: String!\n fFieldOnNBigObject: Int!\n gFieldOnNBigObject: Boolean!\n hFieldOnNBigObject: Float!\n iFieldOnNBigObject: String!\n jFieldOnNBigObject: Int!\n kFieldOnNBigObject: Boolean!\n lFieldOnNBigObject: Float!\n mFieldOnNBigObject: String!\n nFieldOnNBigObject: Int!\n oFieldOnNBigObject: Boolean!\n pFieldOnNBigObject: Float!\n qFieldOnNBigObject: String!\n rFieldOnNBigObject: Int!\n sFieldOnNBigObject: Boolean!\n tFieldOnNBigObject: Float!\n uFieldOnNBigObject: String!\n vFieldOnNBigObject: Int!\n wFieldOnNBigObject: Boolean!\n xFieldOnNBigObject: Float!\n yFieldOnNBigObject: String!\n zFieldOnNBigObject: Int!\n}\n\ntype OBigObject {\n aFieldOnOBigObject: String!\n bFieldOnOBigObject: Int!\n cFieldOnOBigObject: Boolean!\n dFieldOnOBigObject: Float!\n eFieldOnOBigObject: String!\n fFieldOnOBigObject: Int!\n gFieldOnOBigObject: Boolean!\n hFieldOnOBigObject: Float!\n iFieldOnOBigObject: String!\n jFieldOnOBigObject: Int!\n kFieldOnOBigObject: Boolean!\n lFieldOnOBigObject: Float!\n mFieldOnOBigObject: String!\n nFieldOnOBigObject: Int!\n oFieldOnOBigObject: Boolean!\n pFieldOnOBigObject: Float!\n qFieldOnOBigObject: String!\n rFieldOnOBigObject: Int!\n sFieldOnOBigObject: Boolean!\n tFieldOnOBigObject: Float!\n uFieldOnOBigObject: String!\n vFieldOnOBigObject: Int!\n wFieldOnOBigObject: Boolean!\n xFieldOnOBigObject: Float!\n yFieldOnOBigObject: String!\n zFieldOnOBigObject: Int!\n}\n\ntype PBigObject {\n aFieldOnPBigObject: String!\n bFieldOnPBigObject: Int!\n cFieldOnPBigObject: Boolean!\n dFieldOnPBigObject: Float!\n eFieldOnPBigObject: String!\n fFieldOnPBigObject: Int!\n gFieldOnPBigObject: Boolean!\n hFieldOnPBigObject: Float!\n iFieldOnPBigObject: String!\n jFieldOnPBigObject: Int!\n kFieldOnPBigObject: Boolean!\n lFieldOnPBigObject: Float!\n mFieldOnPBigObject: String!\n nFieldOnPBigObject: Int!\n oFieldOnPBigObject: Boolean!\n pFieldOnPBigObject: Float!\n qFieldOnPBigObject: String!\n rFieldOnPBigObject: Int!\n sFieldOnPBigObject: Boolean!\n tFieldOnPBigObject: Float!\n uFieldOnPBigObject: String!\n vFieldOnPBigObject: Int!\n wFieldOnPBigObject: Boolean!\n xFieldOnPBigObject: Float!\n yFieldOnPBigObject: String!\n zFieldOnPBigObject: Int!\n}\n\ntype QBigObject {\n aFieldOnQBigObject: String!\n bFieldOnQBigObject: Int!\n cFieldOnQBigObject: Boolean!\n dFieldOnQBigObject: Float!\n eFieldOnQBigObject: String!\n fFieldOnQBigObject: Int!\n gFieldOnQBigObject: Boolean!\n hFieldOnQBigObject: Float!\n iFieldOnQBigObject: String!\n jFieldOnQBigObject: Int!\n kFieldOnQBigObject: Boolean!\n lFieldOnQBigObject: Float!\n mFieldOnQBigObject: String!\n nFieldOnQBigObject: Int!\n oFieldOnQBigObject: Boolean!\n pFieldOnQBigObject: Float!\n qFieldOnQBigObject: String!\n rFieldOnQBigObject: Int!\n sFieldOnQBigObject: Boolean!\n tFieldOnQBigObject: Float!\n uFieldOnQBigObject: String!\n vFieldOnQBigObject: Int!\n wFieldOnQBigObject: Boolean!\n xFieldOnQBigObject: Float!\n yFieldOnQBigObject: String!\n zFieldOnQBigObject: Int!\n}\n\ntype RBigObject {\n aFieldOnRBigObject: String!\n bFieldOnRBigObject: Int!\n cFieldOnRBigObject: Boolean!\n dFieldOnRBigObject: Float!\n eFieldOnRBigObject: String!\n fFieldOnRBigObject: Int!\n gFieldOnRBigObject: Boolean!\n hFieldOnRBigObject: Float!\n iFieldOnRBigObject: String!\n jFieldOnRBigObject: Int!\n kFieldOnRBigObject: Boolean!\n lFieldOnRBigObject: Float!\n mFieldOnRBigObject: String!\n nFieldOnRBigObject: Int!\n oFieldOnRBigObject: Boolean!\n pFieldOnRBigObject: Float!\n qFieldOnRBigObject: String!\n rFieldOnRBigObject: Int!\n sFieldOnRBigObject: Boolean!\n tFieldOnRBigObject: Float!\n uFieldOnRBigObject: String!\n vFieldOnRBigObject: Int!\n wFieldOnRBigObject: Boolean!\n xFieldOnRBigObject: Float!\n yFieldOnRBigObject: String!\n zFieldOnRBigObject: Int!\n}\n\ntype SBigObject {\n aFieldOnSBigObject: String!\n bFieldOnSBigObject: Int!\n cFieldOnSBigObject: Boolean!\n dFieldOnSBigObject: Float!\n eFieldOnSBigObject: String!\n fFieldOnSBigObject: Int!\n gFieldOnSBigObject: Boolean!\n hFieldOnSBigObject: Float!\n iFieldOnSBigObject: String!\n jFieldOnSBigObject: Int!\n kFieldOnSBigObject: Boolean!\n lFieldOnSBigObject: Float!\n mFieldOnSBigObject: String!\n nFieldOnSBigObject: Int!\n oFieldOnSBigObject: Boolean!\n pFieldOnSBigObject: Float!\n qFieldOnSBigObject: String!\n rFieldOnSBigObject: Int!\n sFieldOnSBigObject: Boolean!\n tFieldOnSBigObject: Float!\n uFieldOnSBigObject: String!\n vFieldOnSBigObject: Int!\n wFieldOnSBigObject: Boolean!\n xFieldOnSBigObject: Float!\n yFieldOnSBigObject: String!\n zFieldOnSBigObject: Int!\n}\n\ntype TBigObject {\n aFieldOnTBigObject: String!\n bFieldOnTBigObject: Int!\n cFieldOnTBigObject: Boolean!\n dFieldOnTBigObject: Float!\n eFieldOnTBigObject: String!\n fFieldOnTBigObject: Int!\n gFieldOnTBigObject: Boolean!\n hFieldOnTBigObject: Float!\n iFieldOnTBigObject: String!\n jFieldOnTBigObject: Int!\n kFieldOnTBigObject: Boolean!\n lFieldOnTBigObject: Float!\n mFieldOnTBigObject: String!\n nFieldOnTBigObject: Int!\n oFieldOnTBigObject: Boolean!\n pFieldOnTBigObject: Float!\n qFieldOnTBigObject: String!\n rFieldOnTBigObject: Int!\n sFieldOnTBigObject: Boolean!\n tFieldOnTBigObject: Float!\n uFieldOnTBigObject: String!\n vFieldOnTBigObject: Int!\n wFieldOnTBigObject: Boolean!\n xFieldOnTBigObject: Float!\n yFieldOnTBigObject: String!\n zFieldOnTBigObject: Int!\n}\n\ntype UBigObject {\n aFieldOnUBigObject: String!\n bFieldOnUBigObject: Int!\n cFieldOnUBigObject: Boolean!\n dFieldOnUBigObject: Float!\n eFieldOnUBigObject: String!\n fFieldOnUBigObject: Int!\n gFieldOnUBigObject: Boolean!\n hFieldOnUBigObject: Float!\n iFieldOnUBigObject: String!\n jFieldOnUBigObject: Int!\n kFieldOnUBigObject: Boolean!\n lFieldOnUBigObject: Float!\n mFieldOnUBigObject: String!\n nFieldOnUBigObject: Int!\n oFieldOnUBigObject: Boolean!\n pFieldOnUBigObject: Float!\n qFieldOnUBigObject: String!\n rFieldOnUBigObject: Int!\n sFieldOnUBigObject: Boolean!\n tFieldOnUBigObject: Float!\n uFieldOnUBigObject: String!\n vFieldOnUBigObject: Int!\n wFieldOnUBigObject: Boolean!\n xFieldOnUBigObject: Float!\n yFieldOnUBigObject: String!\n zFieldOnUBigObject: Int!\n}\n\ntype VBigObject {\n aFieldOnVBigObject: String!\n bFieldOnVBigObject: Int!\n cFieldOnVBigObject: Boolean!\n dFieldOnVBigObject: Float!\n eFieldOnVBigObject: String!\n fFieldOnVBigObject: Int!\n gFieldOnVBigObject: Boolean!\n hFieldOnVBigObject: Float!\n iFieldOnVBigObject: String!\n jFieldOnVBigObject: Int!\n kFieldOnVBigObject: Boolean!\n lFieldOnVBigObject: Float!\n mFieldOnVBigObject: String!\n nFieldOnVBigObject: Int!\n oFieldOnVBigObject: Boolean!\n pFieldOnVBigObject: Float!\n qFieldOnVBigObject: String!\n rFieldOnVBigObject: Int!\n sFieldOnVBigObject: Boolean!\n tFieldOnVBigObject: Float!\n uFieldOnVBigObject: String!\n vFieldOnVBigObject: Int!\n wFieldOnVBigObject: Boolean!\n xFieldOnVBigObject: Float!\n yFieldOnVBigObject: String!\n zFieldOnVBigObject: Int!\n}\n\ntype WBigObject {\n aFieldOnWBigObject: String!\n bFieldOnWBigObject: Int!\n cFieldOnWBigObject: Boolean!\n dFieldOnWBigObject: Float!\n eFieldOnWBigObject: String!\n fFieldOnWBigObject: Int!\n gFieldOnWBigObject: Boolean!\n hFieldOnWBigObject: Float!\n iFieldOnWBigObject: String!\n jFieldOnWBigObject: Int!\n kFieldOnWBigObject: Boolean!\n lFieldOnWBigObject: Float!\n mFieldOnWBigObject: String!\n nFieldOnWBigObject: Int!\n oFieldOnWBigObject: Boolean!\n pFieldOnWBigObject: Float!\n qFieldOnWBigObject: String!\n rFieldOnWBigObject: Int!\n sFieldOnWBigObject: Boolean!\n tFieldOnWBigObject: Float!\n uFieldOnWBigObject: String!\n vFieldOnWBigObject: Int!\n wFieldOnWBigObject: Boolean!\n xFieldOnWBigObject: Float!\n yFieldOnWBigObject: String!\n zFieldOnWBigObject: Int!\n}\n\ntype XBigObject {\n aFieldOnXBigObject: String!\n bFieldOnXBigObject: Int!\n cFieldOnXBigObject: Boolean!\n dFieldOnXBigObject: Float!\n eFieldOnXBigObject: String!\n fFieldOnXBigObject: Int!\n gFieldOnXBigObject: Boolean!\n hFieldOnXBigObject: Float!\n iFieldOnXBigObject: String!\n jFieldOnXBigObject: Int!\n kFieldOnXBigObject: Boolean!\n lFieldOnXBigObject: Float!\n mFieldOnXBigObject: String!\n nFieldOnXBigObject: Int!\n oFieldOnXBigObject: Boolean!\n pFieldOnXBigObject: Float!\n qFieldOnXBigObject: String!\n rFieldOnXBigObject: Int!\n sFieldOnXBigObject: Boolean!\n tFieldOnXBigObject: Float!\n uFieldOnXBigObject: String!\n vFieldOnXBigObject: Int!\n wFieldOnXBigObject: Boolean!\n xFieldOnXBigObject: Float!\n yFieldOnXBigObject: String!\n zFieldOnXBigObject: Int!\n}\n\ntype YBigObject {\n aFieldOnYBigObject: String!\n bFieldOnYBigObject: Int!\n cFieldOnYBigObject: Boolean!\n dFieldOnYBigObject: Float!\n eFieldOnYBigObject: String!\n fFieldOnYBigObject: Int!\n gFieldOnYBigObject: Boolean!\n hFieldOnYBigObject: Float!\n iFieldOnYBigObject: String!\n jFieldOnYBigObject: Int!\n kFieldOnYBigObject: Boolean!\n lFieldOnYBigObject: Float!\n mFieldOnYBigObject: String!\n nFieldOnYBigObject: Int!\n oFieldOnYBigObject: Boolean!\n pFieldOnYBigObject: Float!\n qFieldOnYBigObject: String!\n rFieldOnYBigObject: Int!\n sFieldOnYBigObject: Boolean!\n tFieldOnYBigObject: Float!\n uFieldOnYBigObject: String!\n vFieldOnYBigObject: Int!\n wFieldOnYBigObject: Boolean!\n xFieldOnYBigObject: Float!\n yFieldOnYBigObject: String!\n zFieldOnYBigObject: Int!\n}\n\ntype ZBigObject {\n aFieldOnZBigObject: String!\n bFieldOnZBigObject: Int!\n cFieldOnZBigObject: Boolean!\n dFieldOnZBigObject: Float!\n eFieldOnZBigObject: String!\n fFieldOnZBigObject: Int!\n gFieldOnZBigObject: Boolean!\n hFieldOnZBigObject: Float!\n iFieldOnZBigObject: String!\n jFieldOnZBigObject: Int!\n kFieldOnZBigObject: Boolean!\n lFieldOnZBigObject: Float!\n mFieldOnZBigObject: String!\n nFieldOnZBigObject: Int!\n oFieldOnZBigObject: Boolean!\n pFieldOnZBigObject: Float!\n qFieldOnZBigObject: String!\n rFieldOnZBigObject: Int!\n sFieldOnZBigObject: Boolean!\n tFieldOnZBigObject: Float!\n uFieldOnZBigObject: String!\n vFieldOnZBigObject: Int!\n wFieldOnZBigObject: Boolean!\n xFieldOnZBigObject: Float!\n yFieldOnZBigObject: String!\n zFieldOnZBigObject: Int!\n}\n"
},
"upstreamSchema": {
- "key": "5c5a237ac1f0c1d67ae52534584ee8116d4cc474"
+ "key": "c8d8fe56b658fa642dbb31c0fc3d6f024f4aff10"
}
},
"requestTimeoutSeconds": "10",
@@ -2351,6 +2360,16 @@
}
]
},
+ {
+ "typeName": "Subscription",
+ "fieldName": "metadata",
+ "argumentsConfiguration": [
+ {
+ "name": "repeat",
+ "sourceType": "FIELD_ARGUMENT"
+ }
+ ]
+ },
{
"typeName": "Documentation",
"fieldName": "url",
@@ -2620,18 +2639,18 @@
}
}
],
- "graphqlSchema": "schema {\n query: Query\n mutation: Mutation\n subscription: Subscription\n}\n\ndirective @tag(name: String!) repeatable on ARGUMENT_DEFINITION | ENUM | ENUM_VALUE | FIELD_DEFINITION | INPUT_FIELD_DEFINITION | INPUT_OBJECT | INTERFACE | OBJECT | SCALAR | UNION\n\ndirective @requiresScopes(scopes: [[openfed__Scope!]!]!) on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR\n\ndirective @authenticated on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR\n\ndirective @inaccessible on ARGUMENT_DEFINITION | ENUM | ENUM_VALUE | FIELD_DEFINITION | INPUT_FIELD_DEFINITION | INPUT_OBJECT | INTERFACE | OBJECT | SCALAR | UNION\n\nscalar openfed__Scope\n\ntype Query {\n employee(id: Int!): Employee\n employeeAsList(id: Int!): [Employee]\n employees: [Employee]\n products: [Products!]!\n teammates(team: Department!): [Employee!]!\n firstEmployee: Employee! @tag(name: \"internal\")\n findEmployeesBy(criteria: FindEmployeeCriteria!): [Employee!]!\n \"\"\" This is a GraphQL query that retrieves a list of employees.\"\"\"\n findEmployees(criteria: SearchInput): [Employee!]!\n productTypes: [Products!]!\n topSecretFederationFacts: [TopSecretFact!]! @requiresScopes(scopes: [[\"read:fact\"], [\"read:all\"]])\n factTypes: [TopSecretFactType!]\n sharedThings(numOfA: Int!, numOfB: Int!): [Thing!]!\n slicedThings(first: Int, last: Int): [Thing]\n \"\"\"Returns the value of the received HTTP header.\"\"\"\n headerValue(name: String!): String!\n \"\"\"Returns the value of the given key in the WS initial payload.\"\"\"\n initPayloadValue(key: String!): String!\n initialPayload: Map\n \"\"\"Returns response after the given delay\"\"\"\n delay(response: String!, ms: Int!): String!\n bigResponse(artificialDelay: Int! = 0, bigObjects: Int! = 100, nestedObjects: Int! = 100, deeplyNestedObjects: Int! = 100): [BigObject!]!\n longResponse(artificialDelay: Int! = 0, bytes: Int!): String\n bigAbstractResponse: BigAbstractResponse\n rootFieldWithListArg(arg: [String!]!): [String!]!\n rootFieldWithNestedListArg(arg: [[String!]!]!): [[String!]!]!\n rootFieldWithListOfInputArg(arg: [InputType!]!): [InputResponse!]!\n rootFieldWithListOfEnumArg(arg: [EnumType!]!): [EnumType!]!\n rootFieldWithInput(arg: InputArg!): String!\n floatField(arg: Float): Float\n secret: Secret @requiresScopes(scopes: [[\"read:secret\"]])\n}\n\nscalar Upload\n\ntype Mutation {\n updateEmployeeTag(id: Int!, tag: String!): Employee\n singleUpload(file: Upload!): Boolean!\n singleUploadWithInput(arg: FileUpload!): Boolean!\n multipleUpload(files: [Upload!]!): Boolean!\n addFact(fact: TopSecretFactInput!): TopSecretFact! @requiresScopes(scopes: [[\"write:fact\"], [\"write:all\"]])\n \"\"\" This mutation updates the availability status of an employee in the system.\n \"\"\"\n updateAvailability(employeeID: Int!, isAvailable: Boolean!): Employee!\n \"\"\" This mutation update the mood of an employee. \"\"\"\n updateMood(employeeID: Int!, mood: Mood!): Employee!\n}\n\ninput FileUpload {\n nested: DeeplyNestedFileUpload\n nestedList: [Upload!]\n}\n\ninput DeeplyNestedFileUpload {\n file: Upload!\n}\n\ntype Subscription {\n \"\"\"`currentTime` will return a stream of `Time` objects.\"\"\"\n currentTime: Time!\n countEmp(max: Int!, intervalMilliseconds: Int!): Int!\n countEmp2(max: Int!, intervalMilliseconds: Int!): Int!\n countFor(count: Int!): Int!\n countHob(max: Int!, intervalMilliseconds: Int!): Int!\n \"\"\"Returns a stream with the value of the received HTTP header.\"\"\"\n headerValue(name: String!, repeat: Int): TimestampedString!\n \"\"\"\n Returns a stream with the value of value of the given key in the WS initial payload.\n \"\"\"\n initPayloadValue(key: String!, repeat: Int): TimestampedString!\n \"\"\"Returns a stream with the value of the WS initial payload.\"\"\"\n initialPayload(repeat: Int): Map\n returnsError: String\n}\n\nenum Department {\n ENGINEERING\n MARKETING\n OPERATIONS\n}\n\ninterface RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n}\n\nenum EngineerType {\n BACKEND\n FRONTEND\n FULLSTACK\n}\n\ninterface Identifiable {\n id: Int!\n}\n\nenum OperationType {\n FINANCE\n HUMAN_RESOURCES\n}\n\ntype Details {\n forename: String!\n location: Country!\n surname: String!\n pastLocations: [City!]!\n middlename: String @deprecated(reason: \"No longer supported\")\n hasChildren: Boolean!\n maritalStatus: MaritalStatus\n nationality: Nationality!\n pets: [Pet]\n}\n\ntype City {\n type: String!\n name: String!\n country: Country\n}\n\ntype Country {\n key: CountryKey!\n language: String\n}\n\ntype CountryKey {\n name: String!\n}\n\nenum Mood {\n HAPPY\n SAD\n APATHETIC @inaccessible\n}\n\ntype ErrorWrapper {\n okField: String\n errorField: String\n}\n\ntype Time {\n unixTime: Int!\n timeStamp: String!\n}\n\nunion Products = Consultancy | Cosmo | SDK | Documentation\n\ninterface IProduct {\n upc: ID!\n engineers: [Employee!]!\n}\n\ntype Consultancy {\n upc: ID!\n lead: Employee!\n isLeadAvailable: Boolean\n name: ProductName!\n}\n\ninterface EmployeeWorkItem {\n name: String!\n priority: Int!\n}\n\ntype WorkItemHandler {\n name: String!\n assignedItem: EmployeeWorkItem!\n}\n\ntype TechnicalSpecs {\n name: String!\n complexity: Float!\n metrics: WorkMetrics!\n}\n\ntype ManagementSpecs {\n name: String!\n scope: Float!\n metrics: WorkMetrics!\n}\n\ntype WorkMetrics {\n score: Float!\n efficiency: Float!\n}\n\nunion WorkReviewResult = WorkApproval | WorkRejection\n\ntype WorkApproval {\n comment: String!\n approvedAt: String!\n}\n\ntype WorkRejection {\n reason: String!\n rejectionCode: String!\n}\n\ntype WorkSetup {\n priority: String!\n primaryItem: EmployeeWorkItem!\n}\n\ninput FindEmployeeCriteria @oneOf {\n id: Int\n department: Department\n title: String\n}\n\nenum Class {\n FISH\n MAMMAL\n REPTILE\n}\n\nenum Gender {\n FEMALE\n MALE\n UNKNOWN\n}\n\ninterface Animal {\n class: Class!\n gender: Gender!\n}\n\nenum CatType {\n HOME\n STREET\n}\n\nenum DogBreed {\n GOLDEN_RETRIEVER\n POODLE\n ROTTWEILER\n YORKSHIRE_TERRIER\n}\n\nenum MaritalStatus {\n ENGAGED\n MARRIED\n}\n\nenum Nationality {\n AMERICAN\n DUTCH\n ENGLISH\n GERMAN\n INDIAN\n SPANISH\n UKRAINIAN\n}\n\n\"\"\" Allows to filter employees by their details. \"\"\"\ninput SearchInput {\n hasPets: Boolean\n nationality: Nationality\n nested: NestedSearchInput\n}\n\ninput NestedSearchInput {\n maritalStatus: MaritalStatus\n hasChildren: Boolean\n}\n\nenum ExerciseType {\n CALISTHENICS\n HIKING\n SPORT\n STRENGTH_TRAINING\n}\n\ninterface Experience {\n yearsOfExperience: Float!\n}\n\nenum GameGenre {\n ADVENTURE\n BOARD\n FPS\n CARD\n RPG\n ROGUELITE\n SIMULATION\n STRATEGY\n}\n\nenum ProgrammingLanguage {\n CSHARP\n GO\n RUST\n TYPESCRIPT\n}\n\ninterface Hobby {\n employees: [Employee!]!\n}\n\ntype Thing {\n a: String!\n b: String!\n}\n\ninput TopSecretFactInput {\n title: String!\n description: FactContent!\n factType: TopSecretFactType!\n}\n\nenum TopSecretFactType @authenticated {\n DIRECTIVE\n ENTITY\n MISCELLANEOUS\n}\n\ninterface TopSecretFact @authenticated {\n description: FactContent!\n factType: TopSecretFactType\n}\n\nscalar FactContent @requiresScopes(scopes: [[\"read:scalar\"], [\"read:all\"]])\n\nenum ProductName {\n CONSULTANCY\n COSMO\n ENGINE\n FINANCE\n HUMAN_RESOURCES\n MARKETING\n SDK\n}\n\ntype Documentation {\n url(product: ProductName!): String!\n urls(products: [ProductName!]!): [String!]!\n}\n\ntype Secret {\n value: String\n}\n\ninput InputArg {\n enums: [EnumType!]\n enum: EnumType\n string: String\n strings: [String!]\n}\n\nenum EnumType {\n A\n B\n C\n}\n\ninput InputType {\n arg: String!\n}\n\ntype InputResponse {\n arg: String!\n}\n\nscalar Map\n\ntype TimestampedString {\n \"\"\"The value of the string.\"\"\"\n value: String!\n \"\"\"The timestamp when the response was generated.\"\"\"\n unixTime: Int!\n \"\"\"Sequence number\"\"\"\n seq: Int!\n \"\"\"Total number of responses to be sent\"\"\"\n total: Int!\n initialPayload: Map\n}\n\ntype BigObject {\n nestedObjects: [NestedObject!]!\n}\n\ntype NestedObject {\n deeplyNestedObjects: [DeeplyNestedObject!]!\n}\n\ntype DeeplyNestedObject {\n aFieldOnDeeplyNestedObject: String!\n bFieldOnDeeplyNestedObject: Int!\n cFieldOnDeeplyNestedObject: Boolean!\n dFieldOnDeeplyNestedObject: Float!\n eFieldOnDeeplyNestedObject: String!\n fFieldOnDeeplyNestedObject: Int!\n gFieldOnDeeplyNestedObject: Boolean!\n hFieldOnDeeplyNestedObject: Float!\n iFieldOnDeeplyNestedObject: String!\n jFieldOnDeeplyNestedObject: Int!\n kFieldOnDeeplyNestedObject: Boolean!\n lFieldOnDeeplyNestedObject: Float!\n mFieldOnDeeplyNestedObject: String!\n nFieldOnDeeplyNestedObject: Int!\n oFieldOnDeeplyNestedObject: Boolean!\n pFieldOnDeeplyNestedObject: Float!\n qFieldOnDeeplyNestedObject: String!\n rFieldOnDeeplyNestedObject: Int!\n sFieldOnDeeplyNestedObject: Boolean!\n tFieldOnDeeplyNestedObject: Float!\n uFieldOnDeeplyNestedObject: String!\n vFieldOnDeeplyNestedObject: Int!\n wFieldOnDeeplyNestedObject: Boolean!\n xFieldOnDeeplyNestedObject: Float!\n yFieldOnDeeplyNestedObject: String!\n zFieldOnDeeplyNestedObject: Int!\n}\n\nunion BigAbstractResponse = ABigObject | BBigObject | CBigObject | DBigObject | EBigObject | FBigObject | GBigObject | HBigObject | IBigObject | JBigObject | KBigObject | LBigObject | MBigObject | NBigObject | OBigObject | PBigObject | QBigObject | RBigObject | SBigObject | TBigObject | UBigObject | VBigObject | WBigObject | XBigObject | YBigObject | ZBigObject\n\ntype ABigObject {\n aFieldOnABigObject: String!\n bFieldOnABigObject: Int!\n cFieldOnABigObject: Boolean!\n dFieldOnABigObject: Float!\n eFieldOnABigObject: String!\n fFieldOnABigObject: Int!\n gFieldOnABigObject: Boolean!\n hFieldOnABigObject: Float!\n iFieldOnABigObject: String!\n jFieldOnABigObject: Int!\n kFieldOnABigObject: Boolean!\n lFieldOnABigObject: Float!\n mFieldOnABigObject: String!\n nFieldOnABigObject: Int!\n oFieldOnABigObject: Boolean!\n pFieldOnABigObject: Float!\n qFieldOnABigObject: String!\n rFieldOnABigObject: Int!\n sFieldOnABigObject: Boolean!\n tFieldOnABigObject: Float!\n uFieldOnABigObject: String!\n vFieldOnABigObject: Int!\n wFieldOnABigObject: Boolean!\n xFieldOnABigObject: Float!\n yFieldOnABigObject: String!\n zFieldOnABigObject: Int!\n}\n\ntype BBigObject {\n aFieldOnBBigObject: String!\n bFieldOnBBigObject: Int!\n cFieldOnBBigObject: Boolean!\n dFieldOnBBigObject: Float!\n eFieldOnBBigObject: String!\n fFieldOnBBigObject: Int!\n gFieldOnBBigObject: Boolean!\n hFieldOnBBigObject: Float!\n iFieldOnBBigObject: String!\n jFieldOnBBigObject: Int!\n kFieldOnBBigObject: Boolean!\n lFieldOnBBigObject: Float!\n mFieldOnBBigObject: String!\n nFieldOnBBigObject: Int!\n oFieldOnBBigObject: Boolean!\n pFieldOnBBigObject: Float!\n qFieldOnBBigObject: String!\n rFieldOnBBigObject: Int!\n sFieldOnBBigObject: Boolean!\n tFieldOnBBigObject: Float!\n uFieldOnBBigObject: String!\n vFieldOnBBigObject: Int!\n wFieldOnBBigObject: Boolean!\n xFieldOnBBigObject: Float!\n yFieldOnBBigObject: String!\n zFieldOnBBigObject: Int!\n}\n\ntype CBigObject {\n aFieldOnCBigObject: String!\n bFieldOnCBigObject: Int!\n cFieldOnCBigObject: Boolean!\n dFieldOnCBigObject: Float!\n eFieldOnCBigObject: String!\n fFieldOnCBigObject: Int!\n gFieldOnCBigObject: Boolean!\n hFieldOnCBigObject: Float!\n iFieldOnCBigObject: String!\n jFieldOnCBigObject: Int!\n kFieldOnCBigObject: Boolean!\n lFieldOnCBigObject: Float!\n mFieldOnCBigObject: String!\n nFieldOnCBigObject: Int!\n oFieldOnCBigObject: Boolean!\n pFieldOnCBigObject: Float!\n qFieldOnCBigObject: String!\n rFieldOnCBigObject: Int!\n sFieldOnCBigObject: Boolean!\n tFieldOnCBigObject: Float!\n uFieldOnCBigObject: String!\n vFieldOnCBigObject: Int!\n wFieldOnCBigObject: Boolean!\n xFieldOnCBigObject: Float!\n yFieldOnCBigObject: String!\n zFieldOnCBigObject: Int!\n}\n\ntype DBigObject {\n aFieldOnDBigObject: String!\n bFieldOnDBigObject: Int!\n cFieldOnDBigObject: Boolean!\n dFieldOnDBigObject: Float!\n eFieldOnDBigObject: String!\n fFieldOnDBigObject: Int!\n gFieldOnDBigObject: Boolean!\n hFieldOnDBigObject: Float!\n iFieldOnDBigObject: String!\n jFieldOnDBigObject: Int!\n kFieldOnDBigObject: Boolean!\n lFieldOnDBigObject: Float!\n mFieldOnDBigObject: String!\n nFieldOnDBigObject: Int!\n oFieldOnDBigObject: Boolean!\n pFieldOnDBigObject: Float!\n qFieldOnDBigObject: String!\n rFieldOnDBigObject: Int!\n sFieldOnDBigObject: Boolean!\n tFieldOnDBigObject: Float!\n uFieldOnDBigObject: String!\n vFieldOnDBigObject: Int!\n wFieldOnDBigObject: Boolean!\n xFieldOnDBigObject: Float!\n yFieldOnDBigObject: String!\n zFieldOnDBigObject: Int!\n}\n\ntype EBigObject {\n aFieldOnEBigObject: String!\n bFieldOnEBigObject: Int!\n cFieldOnEBigObject: Boolean!\n dFieldOnEBigObject: Float!\n eFieldOnEBigObject: String!\n fFieldOnEBigObject: Int!\n gFieldOnEBigObject: Boolean!\n hFieldOnEBigObject: Float!\n iFieldOnEBigObject: String!\n jFieldOnEBigObject: Int!\n kFieldOnEBigObject: Boolean!\n lFieldOnEBigObject: Float!\n mFieldOnEBigObject: String!\n nFieldOnEBigObject: Int!\n oFieldOnEBigObject: Boolean!\n pFieldOnEBigObject: Float!\n qFieldOnEBigObject: String!\n rFieldOnEBigObject: Int!\n sFieldOnEBigObject: Boolean!\n tFieldOnEBigObject: Float!\n uFieldOnEBigObject: String!\n vFieldOnEBigObject: Int!\n wFieldOnEBigObject: Boolean!\n xFieldOnEBigObject: Float!\n yFieldOnEBigObject: String!\n zFieldOnEBigObject: Int!\n}\n\ntype FBigObject {\n aFieldOnFBigObject: String!\n bFieldOnFBigObject: Int!\n cFieldOnFBigObject: Boolean!\n dFieldOnFBigObject: Float!\n eFieldOnFBigObject: String!\n fFieldOnFBigObject: Int!\n gFieldOnFBigObject: Boolean!\n hFieldOnFBigObject: Float!\n iFieldOnFBigObject: String!\n jFieldOnFBigObject: Int!\n kFieldOnFBigObject: Boolean!\n lFieldOnFBigObject: Float!\n mFieldOnFBigObject: String!\n nFieldOnFBigObject: Int!\n oFieldOnFBigObject: Boolean!\n pFieldOnFBigObject: Float!\n qFieldOnFBigObject: String!\n rFieldOnFBigObject: Int!\n sFieldOnFBigObject: Boolean!\n tFieldOnFBigObject: Float!\n uFieldOnFBigObject: String!\n vFieldOnFBigObject: Int!\n wFieldOnFBigObject: Boolean!\n xFieldOnFBigObject: Float!\n yFieldOnFBigObject: String!\n zFieldOnFBigObject: Int!\n}\n\ntype GBigObject {\n aFieldOnGBigObject: String!\n bFieldOnGBigObject: Int!\n cFieldOnGBigObject: Boolean!\n dFieldOnGBigObject: Float!\n eFieldOnGBigObject: String!\n fFieldOnGBigObject: Int!\n gFieldOnGBigObject: Boolean!\n hFieldOnGBigObject: Float!\n iFieldOnGBigObject: String!\n jFieldOnGBigObject: Int!\n kFieldOnGBigObject: Boolean!\n lFieldOnGBigObject: Float!\n mFieldOnGBigObject: String!\n nFieldOnGBigObject: Int!\n oFieldOnGBigObject: Boolean!\n pFieldOnGBigObject: Float!\n qFieldOnGBigObject: String!\n rFieldOnGBigObject: Int!\n sFieldOnGBigObject: Boolean!\n tFieldOnGBigObject: Float!\n uFieldOnGBigObject: String!\n vFieldOnGBigObject: Int!\n wFieldOnGBigObject: Boolean!\n xFieldOnGBigObject: Float!\n yFieldOnGBigObject: String!\n zFieldOnGBigObject: Int!\n}\n\ntype HBigObject {\n aFieldOnHBigObject: String!\n bFieldOnHBigObject: Int!\n cFieldOnHBigObject: Boolean!\n dFieldOnHBigObject: Float!\n eFieldOnHBigObject: String!\n fFieldOnHBigObject: Int!\n gFieldOnHBigObject: Boolean!\n hFieldOnHBigObject: Float!\n iFieldOnHBigObject: String!\n jFieldOnHBigObject: Int!\n kFieldOnHBigObject: Boolean!\n lFieldOnHBigObject: Float!\n mFieldOnHBigObject: String!\n nFieldOnHBigObject: Int!\n oFieldOnHBigObject: Boolean!\n pFieldOnHBigObject: Float!\n qFieldOnHBigObject: String!\n rFieldOnHBigObject: Int!\n sFieldOnHBigObject: Boolean!\n tFieldOnHBigObject: Float!\n uFieldOnHBigObject: String!\n vFieldOnHBigObject: Int!\n wFieldOnHBigObject: Boolean!\n xFieldOnHBigObject: Float!\n yFieldOnHBigObject: String!\n zFieldOnHBigObject: Int!\n}\n\ntype IBigObject {\n aFieldOnIBigObject: String!\n bFieldOnIBigObject: Int!\n cFieldOnIBigObject: Boolean!\n dFieldOnIBigObject: Float!\n eFieldOnIBigObject: String!\n fFieldOnIBigObject: Int!\n gFieldOnIBigObject: Boolean!\n hFieldOnIBigObject: Float!\n iFieldOnIBigObject: String!\n jFieldOnIBigObject: Int!\n kFieldOnIBigObject: Boolean!\n lFieldOnIBigObject: Float!\n mFieldOnIBigObject: String!\n nFieldOnIBigObject: Int!\n oFieldOnIBigObject: Boolean!\n pFieldOnIBigObject: Float!\n qFieldOnIBigObject: String!\n rFieldOnIBigObject: Int!\n sFieldOnIBigObject: Boolean!\n tFieldOnIBigObject: Float!\n uFieldOnIBigObject: String!\n vFieldOnIBigObject: Int!\n wFieldOnIBigObject: Boolean!\n xFieldOnIBigObject: Float!\n yFieldOnIBigObject: String!\n zFieldOnIBigObject: Int!\n}\n\ntype JBigObject {\n aFieldOnJBigObject: String!\n bFieldOnJBigObject: Int!\n cFieldOnJBigObject: Boolean!\n dFieldOnJBigObject: Float!\n eFieldOnJBigObject: String!\n fFieldOnJBigObject: Int!\n gFieldOnJBigObject: Boolean!\n hFieldOnJBigObject: Float!\n iFieldOnJBigObject: String!\n jFieldOnJBigObject: Int!\n kFieldOnJBigObject: Boolean!\n lFieldOnJBigObject: Float!\n mFieldOnJBigObject: String!\n nFieldOnJBigObject: Int!\n oFieldOnJBigObject: Boolean!\n pFieldOnJBigObject: Float!\n qFieldOnJBigObject: String!\n rFieldOnJBigObject: Int!\n sFieldOnJBigObject: Boolean!\n tFieldOnJBigObject: Float!\n uFieldOnJBigObject: String!\n vFieldOnJBigObject: Int!\n wFieldOnJBigObject: Boolean!\n xFieldOnJBigObject: Float!\n yFieldOnJBigObject: String!\n zFieldOnJBigObject: Int!\n}\n\ntype KBigObject {\n aFieldOnKBigObject: String!\n bFieldOnKBigObject: Int!\n cFieldOnKBigObject: Boolean!\n dFieldOnKBigObject: Float!\n eFieldOnKBigObject: String!\n fFieldOnKBigObject: Int!\n gFieldOnKBigObject: Boolean!\n hFieldOnKBigObject: Float!\n iFieldOnKBigObject: String!\n jFieldOnKBigObject: Int!\n kFieldOnKBigObject: Boolean!\n lFieldOnKBigObject: Float!\n mFieldOnKBigObject: String!\n nFieldOnKBigObject: Int!\n oFieldOnKBigObject: Boolean!\n pFieldOnKBigObject: Float!\n qFieldOnKBigObject: String!\n rFieldOnKBigObject: Int!\n sFieldOnKBigObject: Boolean!\n tFieldOnKBigObject: Float!\n uFieldOnKBigObject: String!\n vFieldOnKBigObject: Int!\n wFieldOnKBigObject: Boolean!\n xFieldOnKBigObject: Float!\n yFieldOnKBigObject: String!\n zFieldOnKBigObject: Int!\n}\n\ntype LBigObject {\n aFieldOnLBigObject: String!\n bFieldOnLBigObject: Int!\n cFieldOnLBigObject: Boolean!\n dFieldOnLBigObject: Float!\n eFieldOnLBigObject: String!\n fFieldOnLBigObject: Int!\n gFieldOnLBigObject: Boolean!\n hFieldOnLBigObject: Float!\n iFieldOnLBigObject: String!\n jFieldOnLBigObject: Int!\n kFieldOnLBigObject: Boolean!\n lFieldOnLBigObject: Float!\n mFieldOnLBigObject: String!\n nFieldOnLBigObject: Int!\n oFieldOnLBigObject: Boolean!\n pFieldOnLBigObject: Float!\n qFieldOnLBigObject: String!\n rFieldOnLBigObject: Int!\n sFieldOnLBigObject: Boolean!\n tFieldOnLBigObject: Float!\n uFieldOnLBigObject: String!\n vFieldOnLBigObject: Int!\n wFieldOnLBigObject: Boolean!\n xFieldOnLBigObject: Float!\n yFieldOnLBigObject: String!\n zFieldOnLBigObject: Int!\n}\n\ntype MBigObject {\n aFieldOnMBigObject: String!\n bFieldOnMBigObject: Int!\n cFieldOnMBigObject: Boolean!\n dFieldOnMBigObject: Float!\n eFieldOnMBigObject: String!\n fFieldOnMBigObject: Int!\n gFieldOnMBigObject: Boolean!\n hFieldOnMBigObject: Float!\n iFieldOnMBigObject: String!\n jFieldOnMBigObject: Int!\n kFieldOnMBigObject: Boolean!\n lFieldOnMBigObject: Float!\n mFieldOnMBigObject: String!\n nFieldOnMBigObject: Int!\n oFieldOnMBigObject: Boolean!\n pFieldOnMBigObject: Float!\n qFieldOnMBigObject: String!\n rFieldOnMBigObject: Int!\n sFieldOnMBigObject: Boolean!\n tFieldOnMBigObject: Float!\n uFieldOnMBigObject: String!\n vFieldOnMBigObject: Int!\n wFieldOnMBigObject: Boolean!\n xFieldOnMBigObject: Float!\n yFieldOnMBigObject: String!\n zFieldOnMBigObject: Int!\n}\n\ntype NBigObject {\n aFieldOnNBigObject: String!\n bFieldOnNBigObject: Int!\n cFieldOnNBigObject: Boolean!\n dFieldOnNBigObject: Float!\n eFieldOnNBigObject: String!\n fFieldOnNBigObject: Int!\n gFieldOnNBigObject: Boolean!\n hFieldOnNBigObject: Float!\n iFieldOnNBigObject: String!\n jFieldOnNBigObject: Int!\n kFieldOnNBigObject: Boolean!\n lFieldOnNBigObject: Float!\n mFieldOnNBigObject: String!\n nFieldOnNBigObject: Int!\n oFieldOnNBigObject: Boolean!\n pFieldOnNBigObject: Float!\n qFieldOnNBigObject: String!\n rFieldOnNBigObject: Int!\n sFieldOnNBigObject: Boolean!\n tFieldOnNBigObject: Float!\n uFieldOnNBigObject: String!\n vFieldOnNBigObject: Int!\n wFieldOnNBigObject: Boolean!\n xFieldOnNBigObject: Float!\n yFieldOnNBigObject: String!\n zFieldOnNBigObject: Int!\n}\n\ntype OBigObject {\n aFieldOnOBigObject: String!\n bFieldOnOBigObject: Int!\n cFieldOnOBigObject: Boolean!\n dFieldOnOBigObject: Float!\n eFieldOnOBigObject: String!\n fFieldOnOBigObject: Int!\n gFieldOnOBigObject: Boolean!\n hFieldOnOBigObject: Float!\n iFieldOnOBigObject: String!\n jFieldOnOBigObject: Int!\n kFieldOnOBigObject: Boolean!\n lFieldOnOBigObject: Float!\n mFieldOnOBigObject: String!\n nFieldOnOBigObject: Int!\n oFieldOnOBigObject: Boolean!\n pFieldOnOBigObject: Float!\n qFieldOnOBigObject: String!\n rFieldOnOBigObject: Int!\n sFieldOnOBigObject: Boolean!\n tFieldOnOBigObject: Float!\n uFieldOnOBigObject: String!\n vFieldOnOBigObject: Int!\n wFieldOnOBigObject: Boolean!\n xFieldOnOBigObject: Float!\n yFieldOnOBigObject: String!\n zFieldOnOBigObject: Int!\n}\n\ntype PBigObject {\n aFieldOnPBigObject: String!\n bFieldOnPBigObject: Int!\n cFieldOnPBigObject: Boolean!\n dFieldOnPBigObject: Float!\n eFieldOnPBigObject: String!\n fFieldOnPBigObject: Int!\n gFieldOnPBigObject: Boolean!\n hFieldOnPBigObject: Float!\n iFieldOnPBigObject: String!\n jFieldOnPBigObject: Int!\n kFieldOnPBigObject: Boolean!\n lFieldOnPBigObject: Float!\n mFieldOnPBigObject: String!\n nFieldOnPBigObject: Int!\n oFieldOnPBigObject: Boolean!\n pFieldOnPBigObject: Float!\n qFieldOnPBigObject: String!\n rFieldOnPBigObject: Int!\n sFieldOnPBigObject: Boolean!\n tFieldOnPBigObject: Float!\n uFieldOnPBigObject: String!\n vFieldOnPBigObject: Int!\n wFieldOnPBigObject: Boolean!\n xFieldOnPBigObject: Float!\n yFieldOnPBigObject: String!\n zFieldOnPBigObject: Int!\n}\n\ntype QBigObject {\n aFieldOnQBigObject: String!\n bFieldOnQBigObject: Int!\n cFieldOnQBigObject: Boolean!\n dFieldOnQBigObject: Float!\n eFieldOnQBigObject: String!\n fFieldOnQBigObject: Int!\n gFieldOnQBigObject: Boolean!\n hFieldOnQBigObject: Float!\n iFieldOnQBigObject: String!\n jFieldOnQBigObject: Int!\n kFieldOnQBigObject: Boolean!\n lFieldOnQBigObject: Float!\n mFieldOnQBigObject: String!\n nFieldOnQBigObject: Int!\n oFieldOnQBigObject: Boolean!\n pFieldOnQBigObject: Float!\n qFieldOnQBigObject: String!\n rFieldOnQBigObject: Int!\n sFieldOnQBigObject: Boolean!\n tFieldOnQBigObject: Float!\n uFieldOnQBigObject: String!\n vFieldOnQBigObject: Int!\n wFieldOnQBigObject: Boolean!\n xFieldOnQBigObject: Float!\n yFieldOnQBigObject: String!\n zFieldOnQBigObject: Int!\n}\n\ntype RBigObject {\n aFieldOnRBigObject: String!\n bFieldOnRBigObject: Int!\n cFieldOnRBigObject: Boolean!\n dFieldOnRBigObject: Float!\n eFieldOnRBigObject: String!\n fFieldOnRBigObject: Int!\n gFieldOnRBigObject: Boolean!\n hFieldOnRBigObject: Float!\n iFieldOnRBigObject: String!\n jFieldOnRBigObject: Int!\n kFieldOnRBigObject: Boolean!\n lFieldOnRBigObject: Float!\n mFieldOnRBigObject: String!\n nFieldOnRBigObject: Int!\n oFieldOnRBigObject: Boolean!\n pFieldOnRBigObject: Float!\n qFieldOnRBigObject: String!\n rFieldOnRBigObject: Int!\n sFieldOnRBigObject: Boolean!\n tFieldOnRBigObject: Float!\n uFieldOnRBigObject: String!\n vFieldOnRBigObject: Int!\n wFieldOnRBigObject: Boolean!\n xFieldOnRBigObject: Float!\n yFieldOnRBigObject: String!\n zFieldOnRBigObject: Int!\n}\n\ntype SBigObject {\n aFieldOnSBigObject: String!\n bFieldOnSBigObject: Int!\n cFieldOnSBigObject: Boolean!\n dFieldOnSBigObject: Float!\n eFieldOnSBigObject: String!\n fFieldOnSBigObject: Int!\n gFieldOnSBigObject: Boolean!\n hFieldOnSBigObject: Float!\n iFieldOnSBigObject: String!\n jFieldOnSBigObject: Int!\n kFieldOnSBigObject: Boolean!\n lFieldOnSBigObject: Float!\n mFieldOnSBigObject: String!\n nFieldOnSBigObject: Int!\n oFieldOnSBigObject: Boolean!\n pFieldOnSBigObject: Float!\n qFieldOnSBigObject: String!\n rFieldOnSBigObject: Int!\n sFieldOnSBigObject: Boolean!\n tFieldOnSBigObject: Float!\n uFieldOnSBigObject: String!\n vFieldOnSBigObject: Int!\n wFieldOnSBigObject: Boolean!\n xFieldOnSBigObject: Float!\n yFieldOnSBigObject: String!\n zFieldOnSBigObject: Int!\n}\n\ntype TBigObject {\n aFieldOnTBigObject: String!\n bFieldOnTBigObject: Int!\n cFieldOnTBigObject: Boolean!\n dFieldOnTBigObject: Float!\n eFieldOnTBigObject: String!\n fFieldOnTBigObject: Int!\n gFieldOnTBigObject: Boolean!\n hFieldOnTBigObject: Float!\n iFieldOnTBigObject: String!\n jFieldOnTBigObject: Int!\n kFieldOnTBigObject: Boolean!\n lFieldOnTBigObject: Float!\n mFieldOnTBigObject: String!\n nFieldOnTBigObject: Int!\n oFieldOnTBigObject: Boolean!\n pFieldOnTBigObject: Float!\n qFieldOnTBigObject: String!\n rFieldOnTBigObject: Int!\n sFieldOnTBigObject: Boolean!\n tFieldOnTBigObject: Float!\n uFieldOnTBigObject: String!\n vFieldOnTBigObject: Int!\n wFieldOnTBigObject: Boolean!\n xFieldOnTBigObject: Float!\n yFieldOnTBigObject: String!\n zFieldOnTBigObject: Int!\n}\n\ntype UBigObject {\n aFieldOnUBigObject: String!\n bFieldOnUBigObject: Int!\n cFieldOnUBigObject: Boolean!\n dFieldOnUBigObject: Float!\n eFieldOnUBigObject: String!\n fFieldOnUBigObject: Int!\n gFieldOnUBigObject: Boolean!\n hFieldOnUBigObject: Float!\n iFieldOnUBigObject: String!\n jFieldOnUBigObject: Int!\n kFieldOnUBigObject: Boolean!\n lFieldOnUBigObject: Float!\n mFieldOnUBigObject: String!\n nFieldOnUBigObject: Int!\n oFieldOnUBigObject: Boolean!\n pFieldOnUBigObject: Float!\n qFieldOnUBigObject: String!\n rFieldOnUBigObject: Int!\n sFieldOnUBigObject: Boolean!\n tFieldOnUBigObject: Float!\n uFieldOnUBigObject: String!\n vFieldOnUBigObject: Int!\n wFieldOnUBigObject: Boolean!\n xFieldOnUBigObject: Float!\n yFieldOnUBigObject: String!\n zFieldOnUBigObject: Int!\n}\n\ntype VBigObject {\n aFieldOnVBigObject: String!\n bFieldOnVBigObject: Int!\n cFieldOnVBigObject: Boolean!\n dFieldOnVBigObject: Float!\n eFieldOnVBigObject: String!\n fFieldOnVBigObject: Int!\n gFieldOnVBigObject: Boolean!\n hFieldOnVBigObject: Float!\n iFieldOnVBigObject: String!\n jFieldOnVBigObject: Int!\n kFieldOnVBigObject: Boolean!\n lFieldOnVBigObject: Float!\n mFieldOnVBigObject: String!\n nFieldOnVBigObject: Int!\n oFieldOnVBigObject: Boolean!\n pFieldOnVBigObject: Float!\n qFieldOnVBigObject: String!\n rFieldOnVBigObject: Int!\n sFieldOnVBigObject: Boolean!\n tFieldOnVBigObject: Float!\n uFieldOnVBigObject: String!\n vFieldOnVBigObject: Int!\n wFieldOnVBigObject: Boolean!\n xFieldOnVBigObject: Float!\n yFieldOnVBigObject: String!\n zFieldOnVBigObject: Int!\n}\n\ntype WBigObject {\n aFieldOnWBigObject: String!\n bFieldOnWBigObject: Int!\n cFieldOnWBigObject: Boolean!\n dFieldOnWBigObject: Float!\n eFieldOnWBigObject: String!\n fFieldOnWBigObject: Int!\n gFieldOnWBigObject: Boolean!\n hFieldOnWBigObject: Float!\n iFieldOnWBigObject: String!\n jFieldOnWBigObject: Int!\n kFieldOnWBigObject: Boolean!\n lFieldOnWBigObject: Float!\n mFieldOnWBigObject: String!\n nFieldOnWBigObject: Int!\n oFieldOnWBigObject: Boolean!\n pFieldOnWBigObject: Float!\n qFieldOnWBigObject: String!\n rFieldOnWBigObject: Int!\n sFieldOnWBigObject: Boolean!\n tFieldOnWBigObject: Float!\n uFieldOnWBigObject: String!\n vFieldOnWBigObject: Int!\n wFieldOnWBigObject: Boolean!\n xFieldOnWBigObject: Float!\n yFieldOnWBigObject: String!\n zFieldOnWBigObject: Int!\n}\n\ntype XBigObject {\n aFieldOnXBigObject: String!\n bFieldOnXBigObject: Int!\n cFieldOnXBigObject: Boolean!\n dFieldOnXBigObject: Float!\n eFieldOnXBigObject: String!\n fFieldOnXBigObject: Int!\n gFieldOnXBigObject: Boolean!\n hFieldOnXBigObject: Float!\n iFieldOnXBigObject: String!\n jFieldOnXBigObject: Int!\n kFieldOnXBigObject: Boolean!\n lFieldOnXBigObject: Float!\n mFieldOnXBigObject: String!\n nFieldOnXBigObject: Int!\n oFieldOnXBigObject: Boolean!\n pFieldOnXBigObject: Float!\n qFieldOnXBigObject: String!\n rFieldOnXBigObject: Int!\n sFieldOnXBigObject: Boolean!\n tFieldOnXBigObject: Float!\n uFieldOnXBigObject: String!\n vFieldOnXBigObject: Int!\n wFieldOnXBigObject: Boolean!\n xFieldOnXBigObject: Float!\n yFieldOnXBigObject: String!\n zFieldOnXBigObject: Int!\n}\n\ntype YBigObject {\n aFieldOnYBigObject: String!\n bFieldOnYBigObject: Int!\n cFieldOnYBigObject: Boolean!\n dFieldOnYBigObject: Float!\n eFieldOnYBigObject: String!\n fFieldOnYBigObject: Int!\n gFieldOnYBigObject: Boolean!\n hFieldOnYBigObject: Float!\n iFieldOnYBigObject: String!\n jFieldOnYBigObject: Int!\n kFieldOnYBigObject: Boolean!\n lFieldOnYBigObject: Float!\n mFieldOnYBigObject: String!\n nFieldOnYBigObject: Int!\n oFieldOnYBigObject: Boolean!\n pFieldOnYBigObject: Float!\n qFieldOnYBigObject: String!\n rFieldOnYBigObject: Int!\n sFieldOnYBigObject: Boolean!\n tFieldOnYBigObject: Float!\n uFieldOnYBigObject: String!\n vFieldOnYBigObject: Int!\n wFieldOnYBigObject: Boolean!\n xFieldOnYBigObject: Float!\n yFieldOnYBigObject: String!\n zFieldOnYBigObject: Int!\n}\n\ntype ZBigObject {\n aFieldOnZBigObject: String!\n bFieldOnZBigObject: Int!\n cFieldOnZBigObject: Boolean!\n dFieldOnZBigObject: Float!\n eFieldOnZBigObject: String!\n fFieldOnZBigObject: Int!\n gFieldOnZBigObject: Boolean!\n hFieldOnZBigObject: Float!\n iFieldOnZBigObject: String!\n jFieldOnZBigObject: Int!\n kFieldOnZBigObject: Boolean!\n lFieldOnZBigObject: Float!\n mFieldOnZBigObject: String!\n nFieldOnZBigObject: Int!\n oFieldOnZBigObject: Boolean!\n pFieldOnZBigObject: Float!\n qFieldOnZBigObject: String!\n rFieldOnZBigObject: Int!\n sFieldOnZBigObject: Boolean!\n tFieldOnZBigObject: Float!\n uFieldOnZBigObject: String!\n vFieldOnZBigObject: Int!\n wFieldOnZBigObject: Boolean!\n xFieldOnZBigObject: Float!\n yFieldOnZBigObject: String!\n zFieldOnZBigObject: Int!\n}\n\ntype Engineer implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n engineerType: EngineerType!\n}\n\ntype Marketer implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n}\n\ntype Operator implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n operatorType: [OperationType!]!\n}\n\ntype Employee implements Identifiable {\n details: Details\n id: Int!\n tag: String!\n expertise: String!\n role: RoleType!\n notes: String\n updatedAt: String!\n startDate: String! @requiresScopes(scopes: [[\"read:employee\", \"read:private\"], [\"read:all\"]])\n currentMood: Mood!\n derivedMood: Mood!\n isAvailable: Boolean\n rootFieldThrowsError: String\n rootFieldErrorWrapper: ErrorWrapper\n primaryWorkItem: EmployeeWorkItem\n lastWorkReview: WorkReviewResult\n workSetup: WorkSetup\n hobbies: [Hobby!]\n products: [ProductName!]!\n fieldThrowsError: String\n}\n\ntype Cosmo implements IProduct {\n upc: ID!\n engineers: [Employee!]!\n lead: Employee!\n isLeadAvailable: Boolean\n name: ProductName!\n repositoryURL: String!\n}\n\ntype SDK implements IProduct {\n upc: ID!\n engineers: [Employee!]!\n owner: Employee!\n unicode: String!\n clientLanguages: [ProgrammingLanguage!]!\n}\n\ntype TechnicalWorkItem implements EmployeeWorkItem {\n name: String!\n priority: Int!\n codeCount: Int!\n handler: WorkItemHandler!\n specs: TechnicalSpecs!\n}\n\ntype ManagementWorkItem implements EmployeeWorkItem {\n name: String!\n priority: Int!\n teamSize: String!\n handler: WorkItemHandler!\n specs: ManagementSpecs!\n}\n\ninterface Pet implements Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Alligator implements Pet & Animal {\n class: Class!\n dangerous: String!\n gender: Gender!\n name: String!\n}\n\ntype Cat implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n type: CatType!\n}\n\ntype Dog implements Pet & Animal {\n breed: DogBreed!\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Mouse implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Pony implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Exercise implements Hobby {\n employees: [Employee!]!\n category: ExerciseType!\n}\n\ntype Flying implements Experience & Hobby {\n employees: [Employee!]!\n planeModels: [String!]!\n yearsOfExperience: Float!\n}\n\ntype Gaming implements Experience & Hobby {\n employees: [Employee!]!\n genres: [GameGenre!]!\n name: String!\n yearsOfExperience: Float!\n}\n\ntype Other implements Hobby {\n employees: [Employee!]!\n name: String!\n}\n\ntype Programming implements Hobby {\n employees: [Employee!]!\n languages: [ProgrammingLanguage!]!\n}\n\ntype Travelling implements Hobby {\n employees: [Employee!]!\n countriesLived: [Country!]!\n}\n\ntype DirectiveFact implements TopSecretFact @authenticated {\n title: String!\n description: FactContent!\n factType: TopSecretFactType\n}\n\ntype EntityFact implements TopSecretFact @requiresScopes(scopes: [[\"read:entity\"]]) {\n title: String!\n description: FactContent!\n factType: TopSecretFactType\n}\n\ntype MiscellaneousFact implements TopSecretFact {\n title: String!\n description: FactContent! @requiresScopes(scopes: [[\"read:miscellaneous\"]])\n factType: TopSecretFactType\n}",
+ "graphqlSchema": "schema {\n query: Query\n mutation: Mutation\n subscription: Subscription\n}\n\ndirective @tag(name: String!) repeatable on ARGUMENT_DEFINITION | ENUM | ENUM_VALUE | FIELD_DEFINITION | INPUT_FIELD_DEFINITION | INPUT_OBJECT | INTERFACE | OBJECT | SCALAR | UNION\n\ndirective @requiresScopes(scopes: [[openfed__Scope!]!]!) on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR\n\ndirective @authenticated on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR\n\ndirective @inaccessible on ARGUMENT_DEFINITION | ENUM | ENUM_VALUE | FIELD_DEFINITION | INPUT_FIELD_DEFINITION | INPUT_OBJECT | INTERFACE | OBJECT | SCALAR | UNION\n\nscalar openfed__Scope\n\ntype Query {\n employee(id: Int!): Employee\n employeeAsList(id: Int!): [Employee]\n employees: [Employee]\n products: [Products!]!\n teammates(team: Department!): [Employee!]!\n firstEmployee: Employee! @tag(name: \"internal\")\n findEmployeesBy(criteria: FindEmployeeCriteria!): [Employee!]!\n \"\"\" This is a GraphQL query that retrieves a list of employees.\"\"\"\n findEmployees(criteria: SearchInput): [Employee!]!\n productTypes: [Products!]!\n topSecretFederationFacts: [TopSecretFact!]! @requiresScopes(scopes: [[\"read:fact\"], [\"read:all\"]])\n factTypes: [TopSecretFactType!]\n sharedThings(numOfA: Int!, numOfB: Int!): [Thing!]!\n slicedThings(first: Int, last: Int): [Thing]\n \"\"\"Returns the value of the received HTTP header.\"\"\"\n headerValue(name: String!): String!\n \"\"\"Returns the value of the given key in the WS initial payload.\"\"\"\n initPayloadValue(key: String!): String!\n initialPayload: Map\n \"\"\"Returns response after the given delay\"\"\"\n delay(response: String!, ms: Int!): String!\n bigResponse(artificialDelay: Int! = 0, bigObjects: Int! = 100, nestedObjects: Int! = 100, deeplyNestedObjects: Int! = 100): [BigObject!]!\n longResponse(artificialDelay: Int! = 0, bytes: Int!): String\n bigAbstractResponse: BigAbstractResponse\n rootFieldWithListArg(arg: [String!]!): [String!]!\n rootFieldWithNestedListArg(arg: [[String!]!]!): [[String!]!]!\n rootFieldWithListOfInputArg(arg: [InputType!]!): [InputResponse!]!\n rootFieldWithListOfEnumArg(arg: [EnumType!]!): [EnumType!]!\n rootFieldWithInput(arg: InputArg!): String!\n floatField(arg: Float): Float\n secret: Secret @requiresScopes(scopes: [[\"read:secret\"]])\n}\n\nscalar Upload\n\ntype Mutation {\n updateEmployeeTag(id: Int!, tag: String!): Employee\n singleUpload(file: Upload!): Boolean!\n singleUploadWithInput(arg: FileUpload!): Boolean!\n multipleUpload(files: [Upload!]!): Boolean!\n addFact(fact: TopSecretFactInput!): TopSecretFact! @requiresScopes(scopes: [[\"write:fact\"], [\"write:all\"]])\n \"\"\" This mutation updates the availability status of an employee in the system.\n \"\"\"\n updateAvailability(employeeID: Int!, isAvailable: Boolean!): Employee!\n \"\"\" This mutation update the mood of an employee. \"\"\"\n updateMood(employeeID: Int!, mood: Mood!): Employee!\n}\n\ninput FileUpload {\n nested: DeeplyNestedFileUpload\n nestedList: [Upload!]\n}\n\ninput DeeplyNestedFileUpload {\n file: Upload!\n}\n\ntype Subscription {\n \"\"\"`currentTime` will return a stream of `Time` objects.\"\"\"\n currentTime: Time!\n countEmp(max: Int!, intervalMilliseconds: Int!): Int!\n countEmp2(max: Int!, intervalMilliseconds: Int!): Int!\n countFor(count: Int!): Int!\n countHob(max: Int!, intervalMilliseconds: Int!): Int!\n \"\"\"Returns a stream with the value of the received HTTP header.\"\"\"\n headerValue(name: String!, repeat: Int): TimestampedString!\n \"\"\"\n Returns a stream with the value of value of the given key in the WS initial payload.\n \"\"\"\n initPayloadValue(key: String!, repeat: Int): TimestampedString!\n \"\"\"Returns a stream with the value of the WS initial payload.\"\"\"\n initialPayload(repeat: Int): Map\n returnsError: String!\n \"\"\"\n Returns a stream with the values of the WS initial payload and subscribe extensions\n \"\"\"\n metadata(repeat: Int! = 1): SubscribeMetadata!\n}\n\nenum Department {\n ENGINEERING\n MARKETING\n OPERATIONS\n}\n\ninterface RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n}\n\nenum EngineerType {\n BACKEND\n FRONTEND\n FULLSTACK\n}\n\ninterface Identifiable {\n id: Int!\n}\n\nenum OperationType {\n FINANCE\n HUMAN_RESOURCES\n}\n\ntype Details {\n forename: String!\n location: Country!\n surname: String!\n pastLocations: [City!]!\n middlename: String @deprecated(reason: \"No longer supported\")\n hasChildren: Boolean!\n maritalStatus: MaritalStatus\n nationality: Nationality!\n pets: [Pet]\n}\n\ntype City {\n type: String!\n name: String!\n country: Country\n}\n\ntype Country {\n key: CountryKey!\n language: String\n}\n\ntype CountryKey {\n name: String!\n}\n\nenum Mood {\n HAPPY\n SAD\n APATHETIC @inaccessible\n}\n\ntype ErrorWrapper {\n okField: String\n errorField: String\n}\n\ntype Time {\n unixTime: Int!\n timeStamp: String!\n}\n\nunion Products = Consultancy | Cosmo | SDK | Documentation\n\ninterface IProduct {\n upc: ID!\n engineers: [Employee!]!\n}\n\ntype Consultancy {\n upc: ID!\n lead: Employee!\n isLeadAvailable: Boolean\n name: ProductName!\n}\n\ninterface EmployeeWorkItem {\n name: String!\n priority: Int!\n}\n\ntype WorkItemHandler {\n name: String!\n assignedItem: EmployeeWorkItem!\n}\n\ntype TechnicalSpecs {\n name: String!\n complexity: Float!\n metrics: WorkMetrics!\n}\n\ntype ManagementSpecs {\n name: String!\n scope: Float!\n metrics: WorkMetrics!\n}\n\ntype WorkMetrics {\n score: Float!\n efficiency: Float!\n}\n\nunion WorkReviewResult = WorkApproval | WorkRejection\n\ntype WorkApproval {\n comment: String!\n approvedAt: String!\n}\n\ntype WorkRejection {\n reason: String!\n rejectionCode: String!\n}\n\ntype WorkSetup {\n priority: String!\n primaryItem: EmployeeWorkItem!\n}\n\ninput FindEmployeeCriteria @oneOf {\n id: Int\n department: Department\n title: String\n}\n\nenum Class {\n FISH\n MAMMAL\n REPTILE\n}\n\nenum Gender {\n FEMALE\n MALE\n UNKNOWN\n}\n\ninterface Animal {\n class: Class!\n gender: Gender!\n}\n\nenum CatType {\n HOME\n STREET\n}\n\nenum DogBreed {\n GOLDEN_RETRIEVER\n POODLE\n ROTTWEILER\n YORKSHIRE_TERRIER\n}\n\nenum MaritalStatus {\n ENGAGED\n MARRIED\n}\n\nenum Nationality {\n AMERICAN\n DUTCH\n ENGLISH\n GERMAN\n INDIAN\n SPANISH\n UKRAINIAN\n}\n\n\"\"\" Allows to filter employees by their details. \"\"\"\ninput SearchInput {\n hasPets: Boolean\n nationality: Nationality\n nested: NestedSearchInput\n}\n\ninput NestedSearchInput {\n maritalStatus: MaritalStatus\n hasChildren: Boolean\n}\n\nenum ExerciseType {\n CALISTHENICS\n HIKING\n SPORT\n STRENGTH_TRAINING\n}\n\ninterface Experience {\n yearsOfExperience: Float!\n}\n\nenum GameGenre {\n ADVENTURE\n BOARD\n FPS\n CARD\n RPG\n ROGUELITE\n SIMULATION\n STRATEGY\n}\n\nenum ProgrammingLanguage {\n CSHARP\n GO\n RUST\n TYPESCRIPT\n}\n\ninterface Hobby {\n employees: [Employee!]!\n}\n\ntype Thing {\n a: String!\n b: String!\n}\n\ninput TopSecretFactInput {\n title: String!\n description: FactContent!\n factType: TopSecretFactType!\n}\n\nenum TopSecretFactType @authenticated {\n DIRECTIVE\n ENTITY\n MISCELLANEOUS\n}\n\ninterface TopSecretFact @authenticated {\n description: FactContent!\n factType: TopSecretFactType\n}\n\nscalar FactContent @requiresScopes(scopes: [[\"read:scalar\"], [\"read:all\"]])\n\nenum ProductName {\n CONSULTANCY\n COSMO\n ENGINE\n FINANCE\n HUMAN_RESOURCES\n MARKETING\n SDK\n}\n\ntype Documentation {\n url(product: ProductName!): String!\n urls(products: [ProductName!]!): [String!]!\n}\n\ntype Secret {\n value: String\n}\n\ninput InputArg {\n enums: [EnumType!]\n enum: EnumType\n string: String\n strings: [String!]\n}\n\nenum EnumType {\n A\n B\n C\n}\n\ninput InputType {\n arg: String!\n}\n\ntype InputResponse {\n arg: String!\n}\n\nscalar Map\n\ntype TimestampedString {\n \"\"\"The value of the string.\"\"\"\n value: String!\n \"\"\"The timestamp when the response was generated.\"\"\"\n unixTime: Int!\n \"\"\"Sequence number\"\"\"\n seq: Int!\n \"\"\"Total number of responses to be sent\"\"\"\n total: Int!\n initialPayload: Map\n extensions: Map\n}\n\ntype SubscribeMetadata {\n initialPayload: Map\n subscribeExtensions: Map\n}\n\ntype BigObject {\n nestedObjects: [NestedObject!]!\n}\n\ntype NestedObject {\n deeplyNestedObjects: [DeeplyNestedObject!]!\n}\n\ntype DeeplyNestedObject {\n aFieldOnDeeplyNestedObject: String!\n bFieldOnDeeplyNestedObject: Int!\n cFieldOnDeeplyNestedObject: Boolean!\n dFieldOnDeeplyNestedObject: Float!\n eFieldOnDeeplyNestedObject: String!\n fFieldOnDeeplyNestedObject: Int!\n gFieldOnDeeplyNestedObject: Boolean!\n hFieldOnDeeplyNestedObject: Float!\n iFieldOnDeeplyNestedObject: String!\n jFieldOnDeeplyNestedObject: Int!\n kFieldOnDeeplyNestedObject: Boolean!\n lFieldOnDeeplyNestedObject: Float!\n mFieldOnDeeplyNestedObject: String!\n nFieldOnDeeplyNestedObject: Int!\n oFieldOnDeeplyNestedObject: Boolean!\n pFieldOnDeeplyNestedObject: Float!\n qFieldOnDeeplyNestedObject: String!\n rFieldOnDeeplyNestedObject: Int!\n sFieldOnDeeplyNestedObject: Boolean!\n tFieldOnDeeplyNestedObject: Float!\n uFieldOnDeeplyNestedObject: String!\n vFieldOnDeeplyNestedObject: Int!\n wFieldOnDeeplyNestedObject: Boolean!\n xFieldOnDeeplyNestedObject: Float!\n yFieldOnDeeplyNestedObject: String!\n zFieldOnDeeplyNestedObject: Int!\n}\n\nunion BigAbstractResponse = ABigObject | BBigObject | CBigObject | DBigObject | EBigObject | FBigObject | GBigObject | HBigObject | IBigObject | JBigObject | KBigObject | LBigObject | MBigObject | NBigObject | OBigObject | PBigObject | QBigObject | RBigObject | SBigObject | TBigObject | UBigObject | VBigObject | WBigObject | XBigObject | YBigObject | ZBigObject\n\ntype ABigObject {\n aFieldOnABigObject: String!\n bFieldOnABigObject: Int!\n cFieldOnABigObject: Boolean!\n dFieldOnABigObject: Float!\n eFieldOnABigObject: String!\n fFieldOnABigObject: Int!\n gFieldOnABigObject: Boolean!\n hFieldOnABigObject: Float!\n iFieldOnABigObject: String!\n jFieldOnABigObject: Int!\n kFieldOnABigObject: Boolean!\n lFieldOnABigObject: Float!\n mFieldOnABigObject: String!\n nFieldOnABigObject: Int!\n oFieldOnABigObject: Boolean!\n pFieldOnABigObject: Float!\n qFieldOnABigObject: String!\n rFieldOnABigObject: Int!\n sFieldOnABigObject: Boolean!\n tFieldOnABigObject: Float!\n uFieldOnABigObject: String!\n vFieldOnABigObject: Int!\n wFieldOnABigObject: Boolean!\n xFieldOnABigObject: Float!\n yFieldOnABigObject: String!\n zFieldOnABigObject: Int!\n}\n\ntype BBigObject {\n aFieldOnBBigObject: String!\n bFieldOnBBigObject: Int!\n cFieldOnBBigObject: Boolean!\n dFieldOnBBigObject: Float!\n eFieldOnBBigObject: String!\n fFieldOnBBigObject: Int!\n gFieldOnBBigObject: Boolean!\n hFieldOnBBigObject: Float!\n iFieldOnBBigObject: String!\n jFieldOnBBigObject: Int!\n kFieldOnBBigObject: Boolean!\n lFieldOnBBigObject: Float!\n mFieldOnBBigObject: String!\n nFieldOnBBigObject: Int!\n oFieldOnBBigObject: Boolean!\n pFieldOnBBigObject: Float!\n qFieldOnBBigObject: String!\n rFieldOnBBigObject: Int!\n sFieldOnBBigObject: Boolean!\n tFieldOnBBigObject: Float!\n uFieldOnBBigObject: String!\n vFieldOnBBigObject: Int!\n wFieldOnBBigObject: Boolean!\n xFieldOnBBigObject: Float!\n yFieldOnBBigObject: String!\n zFieldOnBBigObject: Int!\n}\n\ntype CBigObject {\n aFieldOnCBigObject: String!\n bFieldOnCBigObject: Int!\n cFieldOnCBigObject: Boolean!\n dFieldOnCBigObject: Float!\n eFieldOnCBigObject: String!\n fFieldOnCBigObject: Int!\n gFieldOnCBigObject: Boolean!\n hFieldOnCBigObject: Float!\n iFieldOnCBigObject: String!\n jFieldOnCBigObject: Int!\n kFieldOnCBigObject: Boolean!\n lFieldOnCBigObject: Float!\n mFieldOnCBigObject: String!\n nFieldOnCBigObject: Int!\n oFieldOnCBigObject: Boolean!\n pFieldOnCBigObject: Float!\n qFieldOnCBigObject: String!\n rFieldOnCBigObject: Int!\n sFieldOnCBigObject: Boolean!\n tFieldOnCBigObject: Float!\n uFieldOnCBigObject: String!\n vFieldOnCBigObject: Int!\n wFieldOnCBigObject: Boolean!\n xFieldOnCBigObject: Float!\n yFieldOnCBigObject: String!\n zFieldOnCBigObject: Int!\n}\n\ntype DBigObject {\n aFieldOnDBigObject: String!\n bFieldOnDBigObject: Int!\n cFieldOnDBigObject: Boolean!\n dFieldOnDBigObject: Float!\n eFieldOnDBigObject: String!\n fFieldOnDBigObject: Int!\n gFieldOnDBigObject: Boolean!\n hFieldOnDBigObject: Float!\n iFieldOnDBigObject: String!\n jFieldOnDBigObject: Int!\n kFieldOnDBigObject: Boolean!\n lFieldOnDBigObject: Float!\n mFieldOnDBigObject: String!\n nFieldOnDBigObject: Int!\n oFieldOnDBigObject: Boolean!\n pFieldOnDBigObject: Float!\n qFieldOnDBigObject: String!\n rFieldOnDBigObject: Int!\n sFieldOnDBigObject: Boolean!\n tFieldOnDBigObject: Float!\n uFieldOnDBigObject: String!\n vFieldOnDBigObject: Int!\n wFieldOnDBigObject: Boolean!\n xFieldOnDBigObject: Float!\n yFieldOnDBigObject: String!\n zFieldOnDBigObject: Int!\n}\n\ntype EBigObject {\n aFieldOnEBigObject: String!\n bFieldOnEBigObject: Int!\n cFieldOnEBigObject: Boolean!\n dFieldOnEBigObject: Float!\n eFieldOnEBigObject: String!\n fFieldOnEBigObject: Int!\n gFieldOnEBigObject: Boolean!\n hFieldOnEBigObject: Float!\n iFieldOnEBigObject: String!\n jFieldOnEBigObject: Int!\n kFieldOnEBigObject: Boolean!\n lFieldOnEBigObject: Float!\n mFieldOnEBigObject: String!\n nFieldOnEBigObject: Int!\n oFieldOnEBigObject: Boolean!\n pFieldOnEBigObject: Float!\n qFieldOnEBigObject: String!\n rFieldOnEBigObject: Int!\n sFieldOnEBigObject: Boolean!\n tFieldOnEBigObject: Float!\n uFieldOnEBigObject: String!\n vFieldOnEBigObject: Int!\n wFieldOnEBigObject: Boolean!\n xFieldOnEBigObject: Float!\n yFieldOnEBigObject: String!\n zFieldOnEBigObject: Int!\n}\n\ntype FBigObject {\n aFieldOnFBigObject: String!\n bFieldOnFBigObject: Int!\n cFieldOnFBigObject: Boolean!\n dFieldOnFBigObject: Float!\n eFieldOnFBigObject: String!\n fFieldOnFBigObject: Int!\n gFieldOnFBigObject: Boolean!\n hFieldOnFBigObject: Float!\n iFieldOnFBigObject: String!\n jFieldOnFBigObject: Int!\n kFieldOnFBigObject: Boolean!\n lFieldOnFBigObject: Float!\n mFieldOnFBigObject: String!\n nFieldOnFBigObject: Int!\n oFieldOnFBigObject: Boolean!\n pFieldOnFBigObject: Float!\n qFieldOnFBigObject: String!\n rFieldOnFBigObject: Int!\n sFieldOnFBigObject: Boolean!\n tFieldOnFBigObject: Float!\n uFieldOnFBigObject: String!\n vFieldOnFBigObject: Int!\n wFieldOnFBigObject: Boolean!\n xFieldOnFBigObject: Float!\n yFieldOnFBigObject: String!\n zFieldOnFBigObject: Int!\n}\n\ntype GBigObject {\n aFieldOnGBigObject: String!\n bFieldOnGBigObject: Int!\n cFieldOnGBigObject: Boolean!\n dFieldOnGBigObject: Float!\n eFieldOnGBigObject: String!\n fFieldOnGBigObject: Int!\n gFieldOnGBigObject: Boolean!\n hFieldOnGBigObject: Float!\n iFieldOnGBigObject: String!\n jFieldOnGBigObject: Int!\n kFieldOnGBigObject: Boolean!\n lFieldOnGBigObject: Float!\n mFieldOnGBigObject: String!\n nFieldOnGBigObject: Int!\n oFieldOnGBigObject: Boolean!\n pFieldOnGBigObject: Float!\n qFieldOnGBigObject: String!\n rFieldOnGBigObject: Int!\n sFieldOnGBigObject: Boolean!\n tFieldOnGBigObject: Float!\n uFieldOnGBigObject: String!\n vFieldOnGBigObject: Int!\n wFieldOnGBigObject: Boolean!\n xFieldOnGBigObject: Float!\n yFieldOnGBigObject: String!\n zFieldOnGBigObject: Int!\n}\n\ntype HBigObject {\n aFieldOnHBigObject: String!\n bFieldOnHBigObject: Int!\n cFieldOnHBigObject: Boolean!\n dFieldOnHBigObject: Float!\n eFieldOnHBigObject: String!\n fFieldOnHBigObject: Int!\n gFieldOnHBigObject: Boolean!\n hFieldOnHBigObject: Float!\n iFieldOnHBigObject: String!\n jFieldOnHBigObject: Int!\n kFieldOnHBigObject: Boolean!\n lFieldOnHBigObject: Float!\n mFieldOnHBigObject: String!\n nFieldOnHBigObject: Int!\n oFieldOnHBigObject: Boolean!\n pFieldOnHBigObject: Float!\n qFieldOnHBigObject: String!\n rFieldOnHBigObject: Int!\n sFieldOnHBigObject: Boolean!\n tFieldOnHBigObject: Float!\n uFieldOnHBigObject: String!\n vFieldOnHBigObject: Int!\n wFieldOnHBigObject: Boolean!\n xFieldOnHBigObject: Float!\n yFieldOnHBigObject: String!\n zFieldOnHBigObject: Int!\n}\n\ntype IBigObject {\n aFieldOnIBigObject: String!\n bFieldOnIBigObject: Int!\n cFieldOnIBigObject: Boolean!\n dFieldOnIBigObject: Float!\n eFieldOnIBigObject: String!\n fFieldOnIBigObject: Int!\n gFieldOnIBigObject: Boolean!\n hFieldOnIBigObject: Float!\n iFieldOnIBigObject: String!\n jFieldOnIBigObject: Int!\n kFieldOnIBigObject: Boolean!\n lFieldOnIBigObject: Float!\n mFieldOnIBigObject: String!\n nFieldOnIBigObject: Int!\n oFieldOnIBigObject: Boolean!\n pFieldOnIBigObject: Float!\n qFieldOnIBigObject: String!\n rFieldOnIBigObject: Int!\n sFieldOnIBigObject: Boolean!\n tFieldOnIBigObject: Float!\n uFieldOnIBigObject: String!\n vFieldOnIBigObject: Int!\n wFieldOnIBigObject: Boolean!\n xFieldOnIBigObject: Float!\n yFieldOnIBigObject: String!\n zFieldOnIBigObject: Int!\n}\n\ntype JBigObject {\n aFieldOnJBigObject: String!\n bFieldOnJBigObject: Int!\n cFieldOnJBigObject: Boolean!\n dFieldOnJBigObject: Float!\n eFieldOnJBigObject: String!\n fFieldOnJBigObject: Int!\n gFieldOnJBigObject: Boolean!\n hFieldOnJBigObject: Float!\n iFieldOnJBigObject: String!\n jFieldOnJBigObject: Int!\n kFieldOnJBigObject: Boolean!\n lFieldOnJBigObject: Float!\n mFieldOnJBigObject: String!\n nFieldOnJBigObject: Int!\n oFieldOnJBigObject: Boolean!\n pFieldOnJBigObject: Float!\n qFieldOnJBigObject: String!\n rFieldOnJBigObject: Int!\n sFieldOnJBigObject: Boolean!\n tFieldOnJBigObject: Float!\n uFieldOnJBigObject: String!\n vFieldOnJBigObject: Int!\n wFieldOnJBigObject: Boolean!\n xFieldOnJBigObject: Float!\n yFieldOnJBigObject: String!\n zFieldOnJBigObject: Int!\n}\n\ntype KBigObject {\n aFieldOnKBigObject: String!\n bFieldOnKBigObject: Int!\n cFieldOnKBigObject: Boolean!\n dFieldOnKBigObject: Float!\n eFieldOnKBigObject: String!\n fFieldOnKBigObject: Int!\n gFieldOnKBigObject: Boolean!\n hFieldOnKBigObject: Float!\n iFieldOnKBigObject: String!\n jFieldOnKBigObject: Int!\n kFieldOnKBigObject: Boolean!\n lFieldOnKBigObject: Float!\n mFieldOnKBigObject: String!\n nFieldOnKBigObject: Int!\n oFieldOnKBigObject: Boolean!\n pFieldOnKBigObject: Float!\n qFieldOnKBigObject: String!\n rFieldOnKBigObject: Int!\n sFieldOnKBigObject: Boolean!\n tFieldOnKBigObject: Float!\n uFieldOnKBigObject: String!\n vFieldOnKBigObject: Int!\n wFieldOnKBigObject: Boolean!\n xFieldOnKBigObject: Float!\n yFieldOnKBigObject: String!\n zFieldOnKBigObject: Int!\n}\n\ntype LBigObject {\n aFieldOnLBigObject: String!\n bFieldOnLBigObject: Int!\n cFieldOnLBigObject: Boolean!\n dFieldOnLBigObject: Float!\n eFieldOnLBigObject: String!\n fFieldOnLBigObject: Int!\n gFieldOnLBigObject: Boolean!\n hFieldOnLBigObject: Float!\n iFieldOnLBigObject: String!\n jFieldOnLBigObject: Int!\n kFieldOnLBigObject: Boolean!\n lFieldOnLBigObject: Float!\n mFieldOnLBigObject: String!\n nFieldOnLBigObject: Int!\n oFieldOnLBigObject: Boolean!\n pFieldOnLBigObject: Float!\n qFieldOnLBigObject: String!\n rFieldOnLBigObject: Int!\n sFieldOnLBigObject: Boolean!\n tFieldOnLBigObject: Float!\n uFieldOnLBigObject: String!\n vFieldOnLBigObject: Int!\n wFieldOnLBigObject: Boolean!\n xFieldOnLBigObject: Float!\n yFieldOnLBigObject: String!\n zFieldOnLBigObject: Int!\n}\n\ntype MBigObject {\n aFieldOnMBigObject: String!\n bFieldOnMBigObject: Int!\n cFieldOnMBigObject: Boolean!\n dFieldOnMBigObject: Float!\n eFieldOnMBigObject: String!\n fFieldOnMBigObject: Int!\n gFieldOnMBigObject: Boolean!\n hFieldOnMBigObject: Float!\n iFieldOnMBigObject: String!\n jFieldOnMBigObject: Int!\n kFieldOnMBigObject: Boolean!\n lFieldOnMBigObject: Float!\n mFieldOnMBigObject: String!\n nFieldOnMBigObject: Int!\n oFieldOnMBigObject: Boolean!\n pFieldOnMBigObject: Float!\n qFieldOnMBigObject: String!\n rFieldOnMBigObject: Int!\n sFieldOnMBigObject: Boolean!\n tFieldOnMBigObject: Float!\n uFieldOnMBigObject: String!\n vFieldOnMBigObject: Int!\n wFieldOnMBigObject: Boolean!\n xFieldOnMBigObject: Float!\n yFieldOnMBigObject: String!\n zFieldOnMBigObject: Int!\n}\n\ntype NBigObject {\n aFieldOnNBigObject: String!\n bFieldOnNBigObject: Int!\n cFieldOnNBigObject: Boolean!\n dFieldOnNBigObject: Float!\n eFieldOnNBigObject: String!\n fFieldOnNBigObject: Int!\n gFieldOnNBigObject: Boolean!\n hFieldOnNBigObject: Float!\n iFieldOnNBigObject: String!\n jFieldOnNBigObject: Int!\n kFieldOnNBigObject: Boolean!\n lFieldOnNBigObject: Float!\n mFieldOnNBigObject: String!\n nFieldOnNBigObject: Int!\n oFieldOnNBigObject: Boolean!\n pFieldOnNBigObject: Float!\n qFieldOnNBigObject: String!\n rFieldOnNBigObject: Int!\n sFieldOnNBigObject: Boolean!\n tFieldOnNBigObject: Float!\n uFieldOnNBigObject: String!\n vFieldOnNBigObject: Int!\n wFieldOnNBigObject: Boolean!\n xFieldOnNBigObject: Float!\n yFieldOnNBigObject: String!\n zFieldOnNBigObject: Int!\n}\n\ntype OBigObject {\n aFieldOnOBigObject: String!\n bFieldOnOBigObject: Int!\n cFieldOnOBigObject: Boolean!\n dFieldOnOBigObject: Float!\n eFieldOnOBigObject: String!\n fFieldOnOBigObject: Int!\n gFieldOnOBigObject: Boolean!\n hFieldOnOBigObject: Float!\n iFieldOnOBigObject: String!\n jFieldOnOBigObject: Int!\n kFieldOnOBigObject: Boolean!\n lFieldOnOBigObject: Float!\n mFieldOnOBigObject: String!\n nFieldOnOBigObject: Int!\n oFieldOnOBigObject: Boolean!\n pFieldOnOBigObject: Float!\n qFieldOnOBigObject: String!\n rFieldOnOBigObject: Int!\n sFieldOnOBigObject: Boolean!\n tFieldOnOBigObject: Float!\n uFieldOnOBigObject: String!\n vFieldOnOBigObject: Int!\n wFieldOnOBigObject: Boolean!\n xFieldOnOBigObject: Float!\n yFieldOnOBigObject: String!\n zFieldOnOBigObject: Int!\n}\n\ntype PBigObject {\n aFieldOnPBigObject: String!\n bFieldOnPBigObject: Int!\n cFieldOnPBigObject: Boolean!\n dFieldOnPBigObject: Float!\n eFieldOnPBigObject: String!\n fFieldOnPBigObject: Int!\n gFieldOnPBigObject: Boolean!\n hFieldOnPBigObject: Float!\n iFieldOnPBigObject: String!\n jFieldOnPBigObject: Int!\n kFieldOnPBigObject: Boolean!\n lFieldOnPBigObject: Float!\n mFieldOnPBigObject: String!\n nFieldOnPBigObject: Int!\n oFieldOnPBigObject: Boolean!\n pFieldOnPBigObject: Float!\n qFieldOnPBigObject: String!\n rFieldOnPBigObject: Int!\n sFieldOnPBigObject: Boolean!\n tFieldOnPBigObject: Float!\n uFieldOnPBigObject: String!\n vFieldOnPBigObject: Int!\n wFieldOnPBigObject: Boolean!\n xFieldOnPBigObject: Float!\n yFieldOnPBigObject: String!\n zFieldOnPBigObject: Int!\n}\n\ntype QBigObject {\n aFieldOnQBigObject: String!\n bFieldOnQBigObject: Int!\n cFieldOnQBigObject: Boolean!\n dFieldOnQBigObject: Float!\n eFieldOnQBigObject: String!\n fFieldOnQBigObject: Int!\n gFieldOnQBigObject: Boolean!\n hFieldOnQBigObject: Float!\n iFieldOnQBigObject: String!\n jFieldOnQBigObject: Int!\n kFieldOnQBigObject: Boolean!\n lFieldOnQBigObject: Float!\n mFieldOnQBigObject: String!\n nFieldOnQBigObject: Int!\n oFieldOnQBigObject: Boolean!\n pFieldOnQBigObject: Float!\n qFieldOnQBigObject: String!\n rFieldOnQBigObject: Int!\n sFieldOnQBigObject: Boolean!\n tFieldOnQBigObject: Float!\n uFieldOnQBigObject: String!\n vFieldOnQBigObject: Int!\n wFieldOnQBigObject: Boolean!\n xFieldOnQBigObject: Float!\n yFieldOnQBigObject: String!\n zFieldOnQBigObject: Int!\n}\n\ntype RBigObject {\n aFieldOnRBigObject: String!\n bFieldOnRBigObject: Int!\n cFieldOnRBigObject: Boolean!\n dFieldOnRBigObject: Float!\n eFieldOnRBigObject: String!\n fFieldOnRBigObject: Int!\n gFieldOnRBigObject: Boolean!\n hFieldOnRBigObject: Float!\n iFieldOnRBigObject: String!\n jFieldOnRBigObject: Int!\n kFieldOnRBigObject: Boolean!\n lFieldOnRBigObject: Float!\n mFieldOnRBigObject: String!\n nFieldOnRBigObject: Int!\n oFieldOnRBigObject: Boolean!\n pFieldOnRBigObject: Float!\n qFieldOnRBigObject: String!\n rFieldOnRBigObject: Int!\n sFieldOnRBigObject: Boolean!\n tFieldOnRBigObject: Float!\n uFieldOnRBigObject: String!\n vFieldOnRBigObject: Int!\n wFieldOnRBigObject: Boolean!\n xFieldOnRBigObject: Float!\n yFieldOnRBigObject: String!\n zFieldOnRBigObject: Int!\n}\n\ntype SBigObject {\n aFieldOnSBigObject: String!\n bFieldOnSBigObject: Int!\n cFieldOnSBigObject: Boolean!\n dFieldOnSBigObject: Float!\n eFieldOnSBigObject: String!\n fFieldOnSBigObject: Int!\n gFieldOnSBigObject: Boolean!\n hFieldOnSBigObject: Float!\n iFieldOnSBigObject: String!\n jFieldOnSBigObject: Int!\n kFieldOnSBigObject: Boolean!\n lFieldOnSBigObject: Float!\n mFieldOnSBigObject: String!\n nFieldOnSBigObject: Int!\n oFieldOnSBigObject: Boolean!\n pFieldOnSBigObject: Float!\n qFieldOnSBigObject: String!\n rFieldOnSBigObject: Int!\n sFieldOnSBigObject: Boolean!\n tFieldOnSBigObject: Float!\n uFieldOnSBigObject: String!\n vFieldOnSBigObject: Int!\n wFieldOnSBigObject: Boolean!\n xFieldOnSBigObject: Float!\n yFieldOnSBigObject: String!\n zFieldOnSBigObject: Int!\n}\n\ntype TBigObject {\n aFieldOnTBigObject: String!\n bFieldOnTBigObject: Int!\n cFieldOnTBigObject: Boolean!\n dFieldOnTBigObject: Float!\n eFieldOnTBigObject: String!\n fFieldOnTBigObject: Int!\n gFieldOnTBigObject: Boolean!\n hFieldOnTBigObject: Float!\n iFieldOnTBigObject: String!\n jFieldOnTBigObject: Int!\n kFieldOnTBigObject: Boolean!\n lFieldOnTBigObject: Float!\n mFieldOnTBigObject: String!\n nFieldOnTBigObject: Int!\n oFieldOnTBigObject: Boolean!\n pFieldOnTBigObject: Float!\n qFieldOnTBigObject: String!\n rFieldOnTBigObject: Int!\n sFieldOnTBigObject: Boolean!\n tFieldOnTBigObject: Float!\n uFieldOnTBigObject: String!\n vFieldOnTBigObject: Int!\n wFieldOnTBigObject: Boolean!\n xFieldOnTBigObject: Float!\n yFieldOnTBigObject: String!\n zFieldOnTBigObject: Int!\n}\n\ntype UBigObject {\n aFieldOnUBigObject: String!\n bFieldOnUBigObject: Int!\n cFieldOnUBigObject: Boolean!\n dFieldOnUBigObject: Float!\n eFieldOnUBigObject: String!\n fFieldOnUBigObject: Int!\n gFieldOnUBigObject: Boolean!\n hFieldOnUBigObject: Float!\n iFieldOnUBigObject: String!\n jFieldOnUBigObject: Int!\n kFieldOnUBigObject: Boolean!\n lFieldOnUBigObject: Float!\n mFieldOnUBigObject: String!\n nFieldOnUBigObject: Int!\n oFieldOnUBigObject: Boolean!\n pFieldOnUBigObject: Float!\n qFieldOnUBigObject: String!\n rFieldOnUBigObject: Int!\n sFieldOnUBigObject: Boolean!\n tFieldOnUBigObject: Float!\n uFieldOnUBigObject: String!\n vFieldOnUBigObject: Int!\n wFieldOnUBigObject: Boolean!\n xFieldOnUBigObject: Float!\n yFieldOnUBigObject: String!\n zFieldOnUBigObject: Int!\n}\n\ntype VBigObject {\n aFieldOnVBigObject: String!\n bFieldOnVBigObject: Int!\n cFieldOnVBigObject: Boolean!\n dFieldOnVBigObject: Float!\n eFieldOnVBigObject: String!\n fFieldOnVBigObject: Int!\n gFieldOnVBigObject: Boolean!\n hFieldOnVBigObject: Float!\n iFieldOnVBigObject: String!\n jFieldOnVBigObject: Int!\n kFieldOnVBigObject: Boolean!\n lFieldOnVBigObject: Float!\n mFieldOnVBigObject: String!\n nFieldOnVBigObject: Int!\n oFieldOnVBigObject: Boolean!\n pFieldOnVBigObject: Float!\n qFieldOnVBigObject: String!\n rFieldOnVBigObject: Int!\n sFieldOnVBigObject: Boolean!\n tFieldOnVBigObject: Float!\n uFieldOnVBigObject: String!\n vFieldOnVBigObject: Int!\n wFieldOnVBigObject: Boolean!\n xFieldOnVBigObject: Float!\n yFieldOnVBigObject: String!\n zFieldOnVBigObject: Int!\n}\n\ntype WBigObject {\n aFieldOnWBigObject: String!\n bFieldOnWBigObject: Int!\n cFieldOnWBigObject: Boolean!\n dFieldOnWBigObject: Float!\n eFieldOnWBigObject: String!\n fFieldOnWBigObject: Int!\n gFieldOnWBigObject: Boolean!\n hFieldOnWBigObject: Float!\n iFieldOnWBigObject: String!\n jFieldOnWBigObject: Int!\n kFieldOnWBigObject: Boolean!\n lFieldOnWBigObject: Float!\n mFieldOnWBigObject: String!\n nFieldOnWBigObject: Int!\n oFieldOnWBigObject: Boolean!\n pFieldOnWBigObject: Float!\n qFieldOnWBigObject: String!\n rFieldOnWBigObject: Int!\n sFieldOnWBigObject: Boolean!\n tFieldOnWBigObject: Float!\n uFieldOnWBigObject: String!\n vFieldOnWBigObject: Int!\n wFieldOnWBigObject: Boolean!\n xFieldOnWBigObject: Float!\n yFieldOnWBigObject: String!\n zFieldOnWBigObject: Int!\n}\n\ntype XBigObject {\n aFieldOnXBigObject: String!\n bFieldOnXBigObject: Int!\n cFieldOnXBigObject: Boolean!\n dFieldOnXBigObject: Float!\n eFieldOnXBigObject: String!\n fFieldOnXBigObject: Int!\n gFieldOnXBigObject: Boolean!\n hFieldOnXBigObject: Float!\n iFieldOnXBigObject: String!\n jFieldOnXBigObject: Int!\n kFieldOnXBigObject: Boolean!\n lFieldOnXBigObject: Float!\n mFieldOnXBigObject: String!\n nFieldOnXBigObject: Int!\n oFieldOnXBigObject: Boolean!\n pFieldOnXBigObject: Float!\n qFieldOnXBigObject: String!\n rFieldOnXBigObject: Int!\n sFieldOnXBigObject: Boolean!\n tFieldOnXBigObject: Float!\n uFieldOnXBigObject: String!\n vFieldOnXBigObject: Int!\n wFieldOnXBigObject: Boolean!\n xFieldOnXBigObject: Float!\n yFieldOnXBigObject: String!\n zFieldOnXBigObject: Int!\n}\n\ntype YBigObject {\n aFieldOnYBigObject: String!\n bFieldOnYBigObject: Int!\n cFieldOnYBigObject: Boolean!\n dFieldOnYBigObject: Float!\n eFieldOnYBigObject: String!\n fFieldOnYBigObject: Int!\n gFieldOnYBigObject: Boolean!\n hFieldOnYBigObject: Float!\n iFieldOnYBigObject: String!\n jFieldOnYBigObject: Int!\n kFieldOnYBigObject: Boolean!\n lFieldOnYBigObject: Float!\n mFieldOnYBigObject: String!\n nFieldOnYBigObject: Int!\n oFieldOnYBigObject: Boolean!\n pFieldOnYBigObject: Float!\n qFieldOnYBigObject: String!\n rFieldOnYBigObject: Int!\n sFieldOnYBigObject: Boolean!\n tFieldOnYBigObject: Float!\n uFieldOnYBigObject: String!\n vFieldOnYBigObject: Int!\n wFieldOnYBigObject: Boolean!\n xFieldOnYBigObject: Float!\n yFieldOnYBigObject: String!\n zFieldOnYBigObject: Int!\n}\n\ntype ZBigObject {\n aFieldOnZBigObject: String!\n bFieldOnZBigObject: Int!\n cFieldOnZBigObject: Boolean!\n dFieldOnZBigObject: Float!\n eFieldOnZBigObject: String!\n fFieldOnZBigObject: Int!\n gFieldOnZBigObject: Boolean!\n hFieldOnZBigObject: Float!\n iFieldOnZBigObject: String!\n jFieldOnZBigObject: Int!\n kFieldOnZBigObject: Boolean!\n lFieldOnZBigObject: Float!\n mFieldOnZBigObject: String!\n nFieldOnZBigObject: Int!\n oFieldOnZBigObject: Boolean!\n pFieldOnZBigObject: Float!\n qFieldOnZBigObject: String!\n rFieldOnZBigObject: Int!\n sFieldOnZBigObject: Boolean!\n tFieldOnZBigObject: Float!\n uFieldOnZBigObject: String!\n vFieldOnZBigObject: Int!\n wFieldOnZBigObject: Boolean!\n xFieldOnZBigObject: Float!\n yFieldOnZBigObject: String!\n zFieldOnZBigObject: Int!\n}\n\ntype Engineer implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n engineerType: EngineerType!\n}\n\ntype Marketer implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n}\n\ntype Operator implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n operatorType: [OperationType!]!\n}\n\ntype Employee implements Identifiable {\n details: Details\n id: Int!\n tag: String!\n expertise: String!\n role: RoleType!\n notes: String\n updatedAt: String!\n startDate: String! @requiresScopes(scopes: [[\"read:employee\", \"read:private\"], [\"read:all\"]])\n currentMood: Mood!\n derivedMood: Mood!\n isAvailable: Boolean\n rootFieldThrowsError: String\n rootFieldErrorWrapper: ErrorWrapper\n primaryWorkItem: EmployeeWorkItem\n lastWorkReview: WorkReviewResult\n workSetup: WorkSetup\n hobbies: [Hobby!]\n products: [ProductName!]!\n fieldThrowsError: String\n}\n\ntype Cosmo implements IProduct {\n upc: ID!\n engineers: [Employee!]!\n lead: Employee!\n isLeadAvailable: Boolean\n name: ProductName!\n repositoryURL: String!\n}\n\ntype SDK implements IProduct {\n upc: ID!\n engineers: [Employee!]!\n owner: Employee!\n unicode: String!\n clientLanguages: [ProgrammingLanguage!]!\n}\n\ntype TechnicalWorkItem implements EmployeeWorkItem {\n name: String!\n priority: Int!\n codeCount: Int!\n handler: WorkItemHandler!\n specs: TechnicalSpecs!\n}\n\ntype ManagementWorkItem implements EmployeeWorkItem {\n name: String!\n priority: Int!\n teamSize: String!\n handler: WorkItemHandler!\n specs: ManagementSpecs!\n}\n\ninterface Pet implements Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Alligator implements Pet & Animal {\n class: Class!\n dangerous: String!\n gender: Gender!\n name: String!\n}\n\ntype Cat implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n type: CatType!\n}\n\ntype Dog implements Pet & Animal {\n breed: DogBreed!\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Mouse implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Pony implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Exercise implements Hobby {\n employees: [Employee!]!\n category: ExerciseType!\n}\n\ntype Flying implements Experience & Hobby {\n employees: [Employee!]!\n planeModels: [String!]!\n yearsOfExperience: Float!\n}\n\ntype Gaming implements Experience & Hobby {\n employees: [Employee!]!\n genres: [GameGenre!]!\n name: String!\n yearsOfExperience: Float!\n}\n\ntype Other implements Hobby {\n employees: [Employee!]!\n name: String!\n}\n\ntype Programming implements Hobby {\n employees: [Employee!]!\n languages: [ProgrammingLanguage!]!\n}\n\ntype Travelling implements Hobby {\n employees: [Employee!]!\n countriesLived: [Country!]!\n}\n\ntype DirectiveFact implements TopSecretFact @authenticated {\n title: String!\n description: FactContent!\n factType: TopSecretFactType\n}\n\ntype EntityFact implements TopSecretFact @requiresScopes(scopes: [[\"read:entity\"]]) {\n title: String!\n description: FactContent!\n factType: TopSecretFactType\n}\n\ntype MiscellaneousFact implements TopSecretFact {\n title: String!\n description: FactContent! @requiresScopes(scopes: [[\"read:miscellaneous\"]])\n factType: TopSecretFactType\n}",
"stringStorage": {
"221e61d62e6d082d089288aefc5a14bcd3719bb0": "schema {\n query: Query\n mutation: Mutation\n subscription: Subscription\n}\n\ndirective @cost(weight: Int!) on ARGUMENT_DEFINITION | ENUM | FIELD_DEFINITION | INPUT_FIELD_DEFINITION | OBJECT | SCALAR\n\ndirective @expensiveOp(coefficient: Int = 2 @cost(weight: 22)) on FIELD_DEFINITION\n\ndirective @external on FIELD_DEFINITION | OBJECT\n\ndirective @goField(forceResolver: Boolean, name: String, omittable: Boolean) on FIELD_DEFINITION | INPUT_FIELD_DEFINITION\n\ndirective @key(fields: openfed__FieldSet!, resolvable: Boolean = true) repeatable on INTERFACE | OBJECT\n\ndirective @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA\n\ndirective @listSize(assumedSize: Int, requireOneSlicingArgument: Boolean = true, sizedFields: [String!], slicingArguments: [String!]) on FIELD_DEFINITION\n\ndirective @openfed__requireFetchReasons repeatable on FIELD_DEFINITION | INTERFACE | OBJECT\n\ndirective @requires(fields: openfed__FieldSet!) on FIELD_DEFINITION\n\ndirective @requiresScopes(scopes: [[openfed__Scope!]!]!) on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR\n\ndirective @shareable repeatable on FIELD_DEFINITION | OBJECT\n\ndirective @tag(name: String!) repeatable on ARGUMENT_DEFINITION | ENUM | ENUM_VALUE | FIELD_DEFINITION | INPUT_FIELD_DEFINITION | INPUT_OBJECT | INTERFACE | OBJECT | SCALAR | UNION\n\ntype City {\n country: Country\n name: String!\n type: String!\n}\n\ntype Consultancy @key(fields: \"upc\") {\n isLeadAvailable: Boolean @requires(fields: \"lead { isAvailable }\")\n lead: Employee!\n upc: ID!\n}\n\ntype Cosmo implements IProduct @key(fields: \"upc\") @cost(weight: 5) {\n engineers: [Employee!]!\n isLeadAvailable: Boolean @requires(fields: \"lead { isAvailable }\")\n lead: Employee!\n upc: ID!\n}\n\ntype Country @key(fields: \"key { name }\", resolvable: false) {\n key: CountryKey!\n}\n\ntype CountryKey {\n name: String!\n}\n\ninput DeeplyNestedFileUpload {\n file: Upload!\n}\n\nenum Department @cost(weight: 1) {\n ENGINEERING\n MARKETING\n OPERATIONS\n}\n\ntype Details {\n forename: String! @shareable\n location: Country!\n pastLocations: [City!]!\n surname: String! @shareable\n}\n\ntype Employee implements Identifiable @key(fields: \"id\") {\n currentMood: Mood! @external\n derivedMood: Mood! @requires(fields: \"currentMood\")\n details: Details! @shareable\n expertise: String!\n id: Int!\n isAvailable: Boolean @external\n lastWorkReview: WorkReviewResult\n notes: String @shareable\n primaryWorkItem: EmployeeWorkItem\n role: RoleType! @listSize(assumedSize: 3, sizedFields: [\"departments\"])\n rootFieldErrorWrapper: ErrorWrapper @goField(forceResolver: true)\n rootFieldThrowsError: String @goField(forceResolver: true)\n startDate: String! @requiresScopes(scopes: [[\"read:employee\", \"read:private\"], [\"read:all\"]])\n tag: String!\n updatedAt: String!\n workSetup: WorkSetup\n}\n\ninterface EmployeeWorkItem {\n name: String!\n priority: Int!\n}\n\ntype Engineer implements RoleType {\n departments: [Department!]!\n employees: [Employee!]! @goField(forceResolver: true) @expensiveOp\n engineerType: EngineerType!\n title: [String!]!\n}\n\nenum EngineerType {\n BACKEND\n FRONTEND\n FULLSTACK\n}\n\ntype ErrorWrapper {\n errorField: String @goField(forceResolver: true)\n okField: String\n}\n\ninput FileUpload {\n nested: DeeplyNestedFileUpload\n nestedList: [Upload!]\n}\n\ninput FindEmployeeCriteria @oneOf {\n department: Department @cost(weight: 17)\n id: Int\n title: String @cost(weight: -3)\n}\n\ninterface IProduct {\n engineers: [Employee!]!\n upc: ID!\n}\n\ninterface Identifiable {\n id: Int! @openfed__requireFetchReasons\n}\n\ntype ManagementSpecs {\n metrics: WorkMetrics! @shareable\n name: String! @shareable\n scope: Float! @shareable\n}\n\ntype ManagementWorkItem implements EmployeeWorkItem {\n handler: WorkItemHandler! @shareable\n name: String! @shareable\n priority: Int! @shareable\n specs: ManagementSpecs! @shareable\n teamSize: String! @shareable\n}\n\ntype Marketer implements RoleType {\n departments: [Department!]!\n employees: [Employee!]! @goField(forceResolver: true) @expensiveOp\n title: [String!]!\n}\n\nenum Mood {\n HAPPY\n SAD\n}\n\ntype Mutation {\n multipleUpload(files: [Upload!]!): Boolean!\n singleUpload(file: Upload!): Boolean!\n singleUploadWithInput(arg: FileUpload!): Boolean!\n updateEmployeeTag(id: Int!, tag: String!): Employee\n}\n\nenum OperationType {\n FINANCE\n HUMAN_RESOURCES\n}\n\ntype Operator implements RoleType {\n departments: [Department!]!\n employees: [Employee!]! @goField(forceResolver: true) @expensiveOp\n operatorType: [OperationType!]!\n title: [String!]!\n}\n\nunion Products = Consultancy | Cosmo | SDK\n\ntype Query {\n employee(id: Int! @cost(weight: 2)): Employee @cost(weight: 5) @openfed__requireFetchReasons\n employeeAsList(id: Int!): [Employee]\n employees: [Employee] @listSize(assumedSize: 50)\n findEmployeesBy(criteria: FindEmployeeCriteria!): [Employee!]! @expensiveOp(coefficient: null)\n firstEmployee: Employee! @tag(name: \"internal\")\n products: [Products!]!\n teammates(team: Department!): [Employee!]!\n}\n\ninterface RoleType {\n departments: [Department!]!\n employees: [Employee!]! @goField(forceResolver: true)\n title: [String!]!\n}\n\ntype SDK implements IProduct @key(fields: \"upc\") {\n engineers: [Employee!]!\n owner: Employee!\n unicode: String!\n upc: ID!\n}\n\ntype Subscription {\n countEmp(intervalMilliseconds: Int!, max: Int!): Int!\n countEmp2(intervalMilliseconds: Int!, max: Int!): Int!\n countFor(count: Int!): Int!\n \"\"\"`currentTime` will return a stream of `Time` objects.\"\"\"\n currentTime: Time!\n}\n\ntype TechnicalSpecs {\n complexity: Float! @shareable\n metrics: WorkMetrics! @shareable\n name: String! @shareable\n}\n\ntype TechnicalWorkItem implements EmployeeWorkItem {\n codeCount: Int! @shareable\n handler: WorkItemHandler! @shareable\n name: String! @shareable\n priority: Int! @shareable\n specs: TechnicalSpecs! @shareable\n}\n\ntype Time {\n timeStamp: String!\n unixTime: Int!\n}\n\nscalar Upload\n\ntype WorkApproval {\n approvedAt: String! @shareable\n comment: String! @shareable\n}\n\ntype WorkItemHandler {\n assignedItem: EmployeeWorkItem! @shareable\n name: String! @shareable\n}\n\ntype WorkMetrics {\n efficiency: Float! @shareable\n score: Float! @shareable\n}\n\ntype WorkRejection {\n reason: String! @shareable\n rejectionCode: String! @shareable\n}\n\nunion WorkReviewResult = WorkApproval | WorkRejection\n\ntype WorkSetup {\n primaryItem: EmployeeWorkItem! @shareable\n priority: String! @shareable\n}\n\nscalar link__Import\n\nenum link__Purpose {\n EXECUTION\n SECURITY\n}\n\nscalar openfed__FieldSet\n\nscalar openfed__Scope",
"2265a44afac63dcf9da5f7ee5ff35c7a6dc8adff": "schema {\n query: Query\n}\n\ndirective @key(fields: openfed__FieldSet!, resolvable: Boolean = true) repeatable on INTERFACE | OBJECT\n\ndirective @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA\n\ndirective @shareable repeatable on FIELD_DEFINITION | OBJECT\n\ntype Alligator implements Animal & Pet {\n class: Class!\n dangerous: String!\n gender: Gender!\n name: String!\n}\n\ninterface Animal {\n class: Class!\n gender: Gender!\n}\n\ntype Cat implements Animal & Pet {\n class: Class!\n gender: Gender!\n name: String!\n type: CatType!\n}\n\nenum CatType {\n HOME\n STREET\n}\n\nenum Class {\n FISH\n MAMMAL\n REPTILE\n}\n\ntype Details {\n forename: String! @shareable\n hasChildren: Boolean!\n maritalStatus: MaritalStatus\n middlename: String @deprecated(reason: \"No longer supported\")\n nationality: Nationality!\n pets: [Pet]\n surname: String! @shareable\n}\n\ntype Dog implements Animal & Pet {\n breed: DogBreed!\n class: Class!\n gender: Gender!\n name: String!\n}\n\nenum DogBreed {\n GOLDEN_RETRIEVER\n POODLE\n ROTTWEILER\n YORKSHIRE_TERRIER\n}\n\ntype Employee @key(fields: \"id\") {\n details: Details @shareable\n id: Int!\n}\n\nenum Gender {\n FEMALE\n MALE\n UNKNOWN\n}\n\nenum MaritalStatus {\n ENGAGED\n MARRIED\n}\n\ntype Mouse implements Animal & Pet {\n class: Class!\n gender: Gender!\n name: String!\n}\n\nenum Nationality {\n AMERICAN\n DUTCH\n ENGLISH\n GERMAN\n INDIAN\n SPANISH\n UKRAINIAN\n}\n\ninput NestedSearchInput {\n hasChildren: Boolean\n maritalStatus: MaritalStatus\n}\n\ninterface Pet implements Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Pony implements Animal & Pet {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Query {\n \"\"\" This is a GraphQL query that retrieves a list of employees.\"\"\"\n findEmployees(criteria: SearchInput): [Employee!]!\n}\n\n\"\"\" Allows to filter employees by their details. \"\"\"\ninput SearchInput {\n hasPets: Boolean\n nationality: Nationality\n nested: NestedSearchInput\n}\n\nscalar link__Import\n\nenum link__Purpose {\n EXECUTION\n SECURITY\n}\n\nscalar openfed__FieldSet",
"6f2131dd12f912ee7f5a965938039527994be676": "schema {\n subscription: Subscription\n}\n\ndirective @goField(forceResolver: Boolean, name: String, omittable: Boolean) on FIELD_DEFINITION | INPUT_FIELD_DEFINITION\n\ndirective @key(fields: openfed__FieldSet!, resolvable: Boolean = true) repeatable on INTERFACE | OBJECT\n\ndirective @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA\n\ntype Country @key(fields: \"key { name }\", resolvable: false) {\n key: CountryKey!\n}\n\ntype CountryKey {\n name: String!\n}\n\ntype Employee @key(fields: \"id\") {\n hobbies: [Hobby!]\n id: Int!\n}\n\ntype Exercise implements Hobby {\n category: ExerciseType!\n employees: [Employee!]! @goField(forceResolver: true)\n}\n\nenum ExerciseType {\n CALISTHENICS\n HIKING\n SPORT\n STRENGTH_TRAINING\n}\n\ninterface Experience {\n yearsOfExperience: Float!\n}\n\ntype Flying implements Experience & Hobby {\n employees: [Employee!]! @goField(forceResolver: true)\n planeModels: [String!]!\n yearsOfExperience: Float!\n}\n\nenum GameGenre {\n ADVENTURE\n BOARD\n CARD\n FPS\n ROGUELITE\n RPG\n SIMULATION\n STRATEGY\n}\n\ntype Gaming implements Experience & Hobby {\n employees: [Employee!]! @goField(forceResolver: true)\n genres: [GameGenre!]!\n name: String!\n yearsOfExperience: Float!\n}\n\ninterface Hobby {\n employees: [Employee!]! @goField(forceResolver: true)\n}\n\ntype Other implements Hobby {\n employees: [Employee!]! @goField(forceResolver: true)\n name: String!\n}\n\ntype Programming implements Hobby {\n employees: [Employee!]! @goField(forceResolver: true)\n languages: [ProgrammingLanguage!]!\n}\n\nenum ProgrammingLanguage {\n CSHARP\n GO\n RUST\n TYPESCRIPT\n}\n\ntype SDK @key(fields: \"upc\") {\n clientLanguages: [ProgrammingLanguage!]!\n upc: ID!\n}\n\ntype Subscription {\n countHob(intervalMilliseconds: Int!, max: Int!): Int!\n}\n\ntype Travelling implements Hobby {\n countriesLived: [Country!]!\n employees: [Employee!]! @goField(forceResolver: true)\n}\n\nscalar link__Import\n\nenum link__Purpose {\n EXECUTION\n SECURITY\n}\n\nscalar openfed__FieldSet",
"a39ab2fac4467859dc24d7fbe2687f046a41ad44": "schema @link(url: \"https://specs.apollo.dev/federation/v2.5\", import: [\"@authenticated\", \"@composeDirective\", \"@external\", \"@extends\", \"@inaccessible\", \"@interfaceObject\", \"@override\", \"@provides\", \"@key\", \"@requires\", \"@requiresScopes\", \"@shareable\", \"@tag\"]) {\n query: Queries\n mutation: Mutation\n}\n\ndirective @authenticated on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR\n\ndirective @cost(weight: Int!) on ARGUMENT_DEFINITION | ENUM | FIELD_DEFINITION | INPUT_FIELD_DEFINITION | OBJECT | SCALAR\n\ndirective @key(fields: openfed__FieldSet!, resolvable: Boolean = true) repeatable on INTERFACE | OBJECT\n\ndirective @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA\n\ndirective @listSize(assumedSize: Int, requireOneSlicingArgument: Boolean = true, sizedFields: [String!], slicingArguments: [String!]) on FIELD_DEFINITION\n\ndirective @override(from: String!) on FIELD_DEFINITION\n\ndirective @requiresScopes(scopes: [[openfed__Scope!]!]!) on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR\n\ndirective @shareable repeatable on FIELD_DEFINITION | OBJECT\n\ntype Consultancy @key(fields: \"upc\") {\n name: ProductName!\n upc: ID!\n}\n\ntype Cosmo @key(fields: \"upc\") @cost(weight: 8) {\n name: ProductName!\n repositoryURL: String!\n upc: ID!\n}\n\ntype DirectiveFact implements TopSecretFact @authenticated {\n description: FactContent!\n factType: TopSecretFactType\n title: String!\n}\n\ntype Documentation {\n url(product: ProductName!): String!\n urls(products: [ProductName!]!): [String!]!\n}\n\ntype Employee @key(fields: \"id\") {\n id: Int!\n notes: String @override(from: \"employees\")\n products: [ProductName!]!\n}\n\ntype EntityFact implements TopSecretFact @requiresScopes(scopes: [[\"read:entity\"]]) {\n description: FactContent!\n factType: TopSecretFactType\n title: String!\n}\n\nscalar FactContent @cost(weight: 10) @requiresScopes(scopes: [[\"read:scalar\"], [\"read:all\"]])\n\ntype MiscellaneousFact implements TopSecretFact {\n description: FactContent! @requiresScopes(scopes: [[\"read:miscellaneous\"]])\n factType: TopSecretFactType\n title: String!\n}\n\ntype Mutation {\n addFact(fact: TopSecretFactInput!): TopSecretFact! @requiresScopes(scopes: [[\"write:fact\"], [\"write:all\"]])\n}\n\nenum ProductName {\n CONSULTANCY\n COSMO\n ENGINE\n FINANCE\n HUMAN_RESOURCES\n MARKETING\n SDK\n}\n\nunion Products = Consultancy | Cosmo | Documentation\n\ntype Queries {\n factTypes: [TopSecretFactType!]\n productTypes: [Products!]! @listSize(assumedSize: 50)\n sharedThings(numOfA: Int!, numOfB: Int!): [Thing!]! @listSize(slicingArguments: [\"numOfA\"]) @shareable\n slicedThings(first: Int, last: Int): [Thing] @listSize(slicingArguments: [\"first\", \"last\"])\n topSecretFederationFacts: [TopSecretFact!]! @requiresScopes(scopes: [[\"read:fact\"], [\"read:all\"]])\n}\n\ntype Thing {\n a: String! @shareable\n}\n\ninterface TopSecretFact @authenticated {\n description: FactContent!\n factType: TopSecretFactType\n}\n\ninput TopSecretFactInput {\n description: FactContent!\n factType: TopSecretFactType!\n title: String!\n}\n\nenum TopSecretFactType @authenticated {\n DIRECTIVE\n ENTITY\n MISCELLANEOUS\n}\n\nscalar link__Import\n\nenum link__Purpose {\n EXECUTION\n SECURITY\n}\n\nscalar openfed__FieldSet\n\nscalar openfed__Scope",
- "5c5a237ac1f0c1d67ae52534584ee8116d4cc474": "schema {\n query: Query\n subscription: Subscription\n}\n\ndirective @key(fields: openfed__FieldSet!, resolvable: Boolean = true) repeatable on INTERFACE | OBJECT\n\ndirective @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA\n\ndirective @requiresScopes(scopes: [[openfed__Scope!]!]!) on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR\n\ndirective @shareable repeatable on FIELD_DEFINITION | OBJECT\n\ntype ABigObject {\n aFieldOnABigObject: String!\n bFieldOnABigObject: Int!\n cFieldOnABigObject: Boolean!\n dFieldOnABigObject: Float!\n eFieldOnABigObject: String!\n fFieldOnABigObject: Int!\n gFieldOnABigObject: Boolean!\n hFieldOnABigObject: Float!\n iFieldOnABigObject: String!\n jFieldOnABigObject: Int!\n kFieldOnABigObject: Boolean!\n lFieldOnABigObject: Float!\n mFieldOnABigObject: String!\n nFieldOnABigObject: Int!\n oFieldOnABigObject: Boolean!\n pFieldOnABigObject: Float!\n qFieldOnABigObject: String!\n rFieldOnABigObject: Int!\n sFieldOnABigObject: Boolean!\n tFieldOnABigObject: Float!\n uFieldOnABigObject: String!\n vFieldOnABigObject: Int!\n wFieldOnABigObject: Boolean!\n xFieldOnABigObject: Float!\n yFieldOnABigObject: String!\n zFieldOnABigObject: Int!\n}\n\ntype BBigObject {\n aFieldOnBBigObject: String!\n bFieldOnBBigObject: Int!\n cFieldOnBBigObject: Boolean!\n dFieldOnBBigObject: Float!\n eFieldOnBBigObject: String!\n fFieldOnBBigObject: Int!\n gFieldOnBBigObject: Boolean!\n hFieldOnBBigObject: Float!\n iFieldOnBBigObject: String!\n jFieldOnBBigObject: Int!\n kFieldOnBBigObject: Boolean!\n lFieldOnBBigObject: Float!\n mFieldOnBBigObject: String!\n nFieldOnBBigObject: Int!\n oFieldOnBBigObject: Boolean!\n pFieldOnBBigObject: Float!\n qFieldOnBBigObject: String!\n rFieldOnBBigObject: Int!\n sFieldOnBBigObject: Boolean!\n tFieldOnBBigObject: Float!\n uFieldOnBBigObject: String!\n vFieldOnBBigObject: Int!\n wFieldOnBBigObject: Boolean!\n xFieldOnBBigObject: Float!\n yFieldOnBBigObject: String!\n zFieldOnBBigObject: Int!\n}\n\nunion BigAbstractResponse = ABigObject | BBigObject | CBigObject | DBigObject | EBigObject | FBigObject | GBigObject | HBigObject | IBigObject | JBigObject | KBigObject | LBigObject | MBigObject | NBigObject | OBigObject | PBigObject | QBigObject | RBigObject | SBigObject | TBigObject | UBigObject | VBigObject | WBigObject | XBigObject | YBigObject | ZBigObject\n\ntype BigObject {\n nestedObjects: [NestedObject!]!\n}\n\ntype CBigObject {\n aFieldOnCBigObject: String!\n bFieldOnCBigObject: Int!\n cFieldOnCBigObject: Boolean!\n dFieldOnCBigObject: Float!\n eFieldOnCBigObject: String!\n fFieldOnCBigObject: Int!\n gFieldOnCBigObject: Boolean!\n hFieldOnCBigObject: Float!\n iFieldOnCBigObject: String!\n jFieldOnCBigObject: Int!\n kFieldOnCBigObject: Boolean!\n lFieldOnCBigObject: Float!\n mFieldOnCBigObject: String!\n nFieldOnCBigObject: Int!\n oFieldOnCBigObject: Boolean!\n pFieldOnCBigObject: Float!\n qFieldOnCBigObject: String!\n rFieldOnCBigObject: Int!\n sFieldOnCBigObject: Boolean!\n tFieldOnCBigObject: Float!\n uFieldOnCBigObject: String!\n vFieldOnCBigObject: Int!\n wFieldOnCBigObject: Boolean!\n xFieldOnCBigObject: Float!\n yFieldOnCBigObject: String!\n zFieldOnCBigObject: Int!\n}\n\ntype DBigObject {\n aFieldOnDBigObject: String!\n bFieldOnDBigObject: Int!\n cFieldOnDBigObject: Boolean!\n dFieldOnDBigObject: Float!\n eFieldOnDBigObject: String!\n fFieldOnDBigObject: Int!\n gFieldOnDBigObject: Boolean!\n hFieldOnDBigObject: Float!\n iFieldOnDBigObject: String!\n jFieldOnDBigObject: Int!\n kFieldOnDBigObject: Boolean!\n lFieldOnDBigObject: Float!\n mFieldOnDBigObject: String!\n nFieldOnDBigObject: Int!\n oFieldOnDBigObject: Boolean!\n pFieldOnDBigObject: Float!\n qFieldOnDBigObject: String!\n rFieldOnDBigObject: Int!\n sFieldOnDBigObject: Boolean!\n tFieldOnDBigObject: Float!\n uFieldOnDBigObject: String!\n vFieldOnDBigObject: Int!\n wFieldOnDBigObject: Boolean!\n xFieldOnDBigObject: Float!\n yFieldOnDBigObject: String!\n zFieldOnDBigObject: Int!\n}\n\ntype DeeplyNestedObject {\n aFieldOnDeeplyNestedObject: String!\n bFieldOnDeeplyNestedObject: Int!\n cFieldOnDeeplyNestedObject: Boolean!\n dFieldOnDeeplyNestedObject: Float!\n eFieldOnDeeplyNestedObject: String!\n fFieldOnDeeplyNestedObject: Int!\n gFieldOnDeeplyNestedObject: Boolean!\n hFieldOnDeeplyNestedObject: Float!\n iFieldOnDeeplyNestedObject: String!\n jFieldOnDeeplyNestedObject: Int!\n kFieldOnDeeplyNestedObject: Boolean!\n lFieldOnDeeplyNestedObject: Float!\n mFieldOnDeeplyNestedObject: String!\n nFieldOnDeeplyNestedObject: Int!\n oFieldOnDeeplyNestedObject: Boolean!\n pFieldOnDeeplyNestedObject: Float!\n qFieldOnDeeplyNestedObject: String!\n rFieldOnDeeplyNestedObject: Int!\n sFieldOnDeeplyNestedObject: Boolean!\n tFieldOnDeeplyNestedObject: Float!\n uFieldOnDeeplyNestedObject: String!\n vFieldOnDeeplyNestedObject: Int!\n wFieldOnDeeplyNestedObject: Boolean!\n xFieldOnDeeplyNestedObject: Float!\n yFieldOnDeeplyNestedObject: String!\n zFieldOnDeeplyNestedObject: Int!\n}\n\ntype EBigObject {\n aFieldOnEBigObject: String!\n bFieldOnEBigObject: Int!\n cFieldOnEBigObject: Boolean!\n dFieldOnEBigObject: Float!\n eFieldOnEBigObject: String!\n fFieldOnEBigObject: Int!\n gFieldOnEBigObject: Boolean!\n hFieldOnEBigObject: Float!\n iFieldOnEBigObject: String!\n jFieldOnEBigObject: Int!\n kFieldOnEBigObject: Boolean!\n lFieldOnEBigObject: Float!\n mFieldOnEBigObject: String!\n nFieldOnEBigObject: Int!\n oFieldOnEBigObject: Boolean!\n pFieldOnEBigObject: Float!\n qFieldOnEBigObject: String!\n rFieldOnEBigObject: Int!\n sFieldOnEBigObject: Boolean!\n tFieldOnEBigObject: Float!\n uFieldOnEBigObject: String!\n vFieldOnEBigObject: Int!\n wFieldOnEBigObject: Boolean!\n xFieldOnEBigObject: Float!\n yFieldOnEBigObject: String!\n zFieldOnEBigObject: Int!\n}\n\ntype Employee @key(fields: \"id\") {\n fieldThrowsError: String\n id: Int!\n}\n\nenum EnumType {\n A\n B\n C\n}\n\ntype FBigObject {\n aFieldOnFBigObject: String!\n bFieldOnFBigObject: Int!\n cFieldOnFBigObject: Boolean!\n dFieldOnFBigObject: Float!\n eFieldOnFBigObject: String!\n fFieldOnFBigObject: Int!\n gFieldOnFBigObject: Boolean!\n hFieldOnFBigObject: Float!\n iFieldOnFBigObject: String!\n jFieldOnFBigObject: Int!\n kFieldOnFBigObject: Boolean!\n lFieldOnFBigObject: Float!\n mFieldOnFBigObject: String!\n nFieldOnFBigObject: Int!\n oFieldOnFBigObject: Boolean!\n pFieldOnFBigObject: Float!\n qFieldOnFBigObject: String!\n rFieldOnFBigObject: Int!\n sFieldOnFBigObject: Boolean!\n tFieldOnFBigObject: Float!\n uFieldOnFBigObject: String!\n vFieldOnFBigObject: Int!\n wFieldOnFBigObject: Boolean!\n xFieldOnFBigObject: Float!\n yFieldOnFBigObject: String!\n zFieldOnFBigObject: Int!\n}\n\ntype GBigObject {\n aFieldOnGBigObject: String!\n bFieldOnGBigObject: Int!\n cFieldOnGBigObject: Boolean!\n dFieldOnGBigObject: Float!\n eFieldOnGBigObject: String!\n fFieldOnGBigObject: Int!\n gFieldOnGBigObject: Boolean!\n hFieldOnGBigObject: Float!\n iFieldOnGBigObject: String!\n jFieldOnGBigObject: Int!\n kFieldOnGBigObject: Boolean!\n lFieldOnGBigObject: Float!\n mFieldOnGBigObject: String!\n nFieldOnGBigObject: Int!\n oFieldOnGBigObject: Boolean!\n pFieldOnGBigObject: Float!\n qFieldOnGBigObject: String!\n rFieldOnGBigObject: Int!\n sFieldOnGBigObject: Boolean!\n tFieldOnGBigObject: Float!\n uFieldOnGBigObject: String!\n vFieldOnGBigObject: Int!\n wFieldOnGBigObject: Boolean!\n xFieldOnGBigObject: Float!\n yFieldOnGBigObject: String!\n zFieldOnGBigObject: Int!\n}\n\ntype HBigObject {\n aFieldOnHBigObject: String!\n bFieldOnHBigObject: Int!\n cFieldOnHBigObject: Boolean!\n dFieldOnHBigObject: Float!\n eFieldOnHBigObject: String!\n fFieldOnHBigObject: Int!\n gFieldOnHBigObject: Boolean!\n hFieldOnHBigObject: Float!\n iFieldOnHBigObject: String!\n jFieldOnHBigObject: Int!\n kFieldOnHBigObject: Boolean!\n lFieldOnHBigObject: Float!\n mFieldOnHBigObject: String!\n nFieldOnHBigObject: Int!\n oFieldOnHBigObject: Boolean!\n pFieldOnHBigObject: Float!\n qFieldOnHBigObject: String!\n rFieldOnHBigObject: Int!\n sFieldOnHBigObject: Boolean!\n tFieldOnHBigObject: Float!\n uFieldOnHBigObject: String!\n vFieldOnHBigObject: Int!\n wFieldOnHBigObject: Boolean!\n xFieldOnHBigObject: Float!\n yFieldOnHBigObject: String!\n zFieldOnHBigObject: Int!\n}\n\ntype IBigObject {\n aFieldOnIBigObject: String!\n bFieldOnIBigObject: Int!\n cFieldOnIBigObject: Boolean!\n dFieldOnIBigObject: Float!\n eFieldOnIBigObject: String!\n fFieldOnIBigObject: Int!\n gFieldOnIBigObject: Boolean!\n hFieldOnIBigObject: Float!\n iFieldOnIBigObject: String!\n jFieldOnIBigObject: Int!\n kFieldOnIBigObject: Boolean!\n lFieldOnIBigObject: Float!\n mFieldOnIBigObject: String!\n nFieldOnIBigObject: Int!\n oFieldOnIBigObject: Boolean!\n pFieldOnIBigObject: Float!\n qFieldOnIBigObject: String!\n rFieldOnIBigObject: Int!\n sFieldOnIBigObject: Boolean!\n tFieldOnIBigObject: Float!\n uFieldOnIBigObject: String!\n vFieldOnIBigObject: Int!\n wFieldOnIBigObject: Boolean!\n xFieldOnIBigObject: Float!\n yFieldOnIBigObject: String!\n zFieldOnIBigObject: Int!\n}\n\ninput InputArg {\n enum: EnumType\n enums: [EnumType!]\n string: String\n strings: [String!]\n}\n\ntype InputResponse {\n arg: String!\n}\n\ninput InputType {\n arg: String!\n}\n\ntype JBigObject {\n aFieldOnJBigObject: String!\n bFieldOnJBigObject: Int!\n cFieldOnJBigObject: Boolean!\n dFieldOnJBigObject: Float!\n eFieldOnJBigObject: String!\n fFieldOnJBigObject: Int!\n gFieldOnJBigObject: Boolean!\n hFieldOnJBigObject: Float!\n iFieldOnJBigObject: String!\n jFieldOnJBigObject: Int!\n kFieldOnJBigObject: Boolean!\n lFieldOnJBigObject: Float!\n mFieldOnJBigObject: String!\n nFieldOnJBigObject: Int!\n oFieldOnJBigObject: Boolean!\n pFieldOnJBigObject: Float!\n qFieldOnJBigObject: String!\n rFieldOnJBigObject: Int!\n sFieldOnJBigObject: Boolean!\n tFieldOnJBigObject: Float!\n uFieldOnJBigObject: String!\n vFieldOnJBigObject: Int!\n wFieldOnJBigObject: Boolean!\n xFieldOnJBigObject: Float!\n yFieldOnJBigObject: String!\n zFieldOnJBigObject: Int!\n}\n\ntype KBigObject {\n aFieldOnKBigObject: String!\n bFieldOnKBigObject: Int!\n cFieldOnKBigObject: Boolean!\n dFieldOnKBigObject: Float!\n eFieldOnKBigObject: String!\n fFieldOnKBigObject: Int!\n gFieldOnKBigObject: Boolean!\n hFieldOnKBigObject: Float!\n iFieldOnKBigObject: String!\n jFieldOnKBigObject: Int!\n kFieldOnKBigObject: Boolean!\n lFieldOnKBigObject: Float!\n mFieldOnKBigObject: String!\n nFieldOnKBigObject: Int!\n oFieldOnKBigObject: Boolean!\n pFieldOnKBigObject: Float!\n qFieldOnKBigObject: String!\n rFieldOnKBigObject: Int!\n sFieldOnKBigObject: Boolean!\n tFieldOnKBigObject: Float!\n uFieldOnKBigObject: String!\n vFieldOnKBigObject: Int!\n wFieldOnKBigObject: Boolean!\n xFieldOnKBigObject: Float!\n yFieldOnKBigObject: String!\n zFieldOnKBigObject: Int!\n}\n\ntype LBigObject {\n aFieldOnLBigObject: String!\n bFieldOnLBigObject: Int!\n cFieldOnLBigObject: Boolean!\n dFieldOnLBigObject: Float!\n eFieldOnLBigObject: String!\n fFieldOnLBigObject: Int!\n gFieldOnLBigObject: Boolean!\n hFieldOnLBigObject: Float!\n iFieldOnLBigObject: String!\n jFieldOnLBigObject: Int!\n kFieldOnLBigObject: Boolean!\n lFieldOnLBigObject: Float!\n mFieldOnLBigObject: String!\n nFieldOnLBigObject: Int!\n oFieldOnLBigObject: Boolean!\n pFieldOnLBigObject: Float!\n qFieldOnLBigObject: String!\n rFieldOnLBigObject: Int!\n sFieldOnLBigObject: Boolean!\n tFieldOnLBigObject: Float!\n uFieldOnLBigObject: String!\n vFieldOnLBigObject: Int!\n wFieldOnLBigObject: Boolean!\n xFieldOnLBigObject: Float!\n yFieldOnLBigObject: String!\n zFieldOnLBigObject: Int!\n}\n\ntype MBigObject {\n aFieldOnMBigObject: String!\n bFieldOnMBigObject: Int!\n cFieldOnMBigObject: Boolean!\n dFieldOnMBigObject: Float!\n eFieldOnMBigObject: String!\n fFieldOnMBigObject: Int!\n gFieldOnMBigObject: Boolean!\n hFieldOnMBigObject: Float!\n iFieldOnMBigObject: String!\n jFieldOnMBigObject: Int!\n kFieldOnMBigObject: Boolean!\n lFieldOnMBigObject: Float!\n mFieldOnMBigObject: String!\n nFieldOnMBigObject: Int!\n oFieldOnMBigObject: Boolean!\n pFieldOnMBigObject: Float!\n qFieldOnMBigObject: String!\n rFieldOnMBigObject: Int!\n sFieldOnMBigObject: Boolean!\n tFieldOnMBigObject: Float!\n uFieldOnMBigObject: String!\n vFieldOnMBigObject: Int!\n wFieldOnMBigObject: Boolean!\n xFieldOnMBigObject: Float!\n yFieldOnMBigObject: String!\n zFieldOnMBigObject: Int!\n}\n\nscalar Map\n\ntype NBigObject {\n aFieldOnNBigObject: String!\n bFieldOnNBigObject: Int!\n cFieldOnNBigObject: Boolean!\n dFieldOnNBigObject: Float!\n eFieldOnNBigObject: String!\n fFieldOnNBigObject: Int!\n gFieldOnNBigObject: Boolean!\n hFieldOnNBigObject: Float!\n iFieldOnNBigObject: String!\n jFieldOnNBigObject: Int!\n kFieldOnNBigObject: Boolean!\n lFieldOnNBigObject: Float!\n mFieldOnNBigObject: String!\n nFieldOnNBigObject: Int!\n oFieldOnNBigObject: Boolean!\n pFieldOnNBigObject: Float!\n qFieldOnNBigObject: String!\n rFieldOnNBigObject: Int!\n sFieldOnNBigObject: Boolean!\n tFieldOnNBigObject: Float!\n uFieldOnNBigObject: String!\n vFieldOnNBigObject: Int!\n wFieldOnNBigObject: Boolean!\n xFieldOnNBigObject: Float!\n yFieldOnNBigObject: String!\n zFieldOnNBigObject: Int!\n}\n\ntype NestedObject {\n deeplyNestedObjects: [DeeplyNestedObject!]!\n}\n\ntype OBigObject {\n aFieldOnOBigObject: String!\n bFieldOnOBigObject: Int!\n cFieldOnOBigObject: Boolean!\n dFieldOnOBigObject: Float!\n eFieldOnOBigObject: String!\n fFieldOnOBigObject: Int!\n gFieldOnOBigObject: Boolean!\n hFieldOnOBigObject: Float!\n iFieldOnOBigObject: String!\n jFieldOnOBigObject: Int!\n kFieldOnOBigObject: Boolean!\n lFieldOnOBigObject: Float!\n mFieldOnOBigObject: String!\n nFieldOnOBigObject: Int!\n oFieldOnOBigObject: Boolean!\n pFieldOnOBigObject: Float!\n qFieldOnOBigObject: String!\n rFieldOnOBigObject: Int!\n sFieldOnOBigObject: Boolean!\n tFieldOnOBigObject: Float!\n uFieldOnOBigObject: String!\n vFieldOnOBigObject: Int!\n wFieldOnOBigObject: Boolean!\n xFieldOnOBigObject: Float!\n yFieldOnOBigObject: String!\n zFieldOnOBigObject: Int!\n}\n\ntype PBigObject {\n aFieldOnPBigObject: String!\n bFieldOnPBigObject: Int!\n cFieldOnPBigObject: Boolean!\n dFieldOnPBigObject: Float!\n eFieldOnPBigObject: String!\n fFieldOnPBigObject: Int!\n gFieldOnPBigObject: Boolean!\n hFieldOnPBigObject: Float!\n iFieldOnPBigObject: String!\n jFieldOnPBigObject: Int!\n kFieldOnPBigObject: Boolean!\n lFieldOnPBigObject: Float!\n mFieldOnPBigObject: String!\n nFieldOnPBigObject: Int!\n oFieldOnPBigObject: Boolean!\n pFieldOnPBigObject: Float!\n qFieldOnPBigObject: String!\n rFieldOnPBigObject: Int!\n sFieldOnPBigObject: Boolean!\n tFieldOnPBigObject: Float!\n uFieldOnPBigObject: String!\n vFieldOnPBigObject: Int!\n wFieldOnPBigObject: Boolean!\n xFieldOnPBigObject: Float!\n yFieldOnPBigObject: String!\n zFieldOnPBigObject: Int!\n}\n\ntype QBigObject {\n aFieldOnQBigObject: String!\n bFieldOnQBigObject: Int!\n cFieldOnQBigObject: Boolean!\n dFieldOnQBigObject: Float!\n eFieldOnQBigObject: String!\n fFieldOnQBigObject: Int!\n gFieldOnQBigObject: Boolean!\n hFieldOnQBigObject: Float!\n iFieldOnQBigObject: String!\n jFieldOnQBigObject: Int!\n kFieldOnQBigObject: Boolean!\n lFieldOnQBigObject: Float!\n mFieldOnQBigObject: String!\n nFieldOnQBigObject: Int!\n oFieldOnQBigObject: Boolean!\n pFieldOnQBigObject: Float!\n qFieldOnQBigObject: String!\n rFieldOnQBigObject: Int!\n sFieldOnQBigObject: Boolean!\n tFieldOnQBigObject: Float!\n uFieldOnQBigObject: String!\n vFieldOnQBigObject: Int!\n wFieldOnQBigObject: Boolean!\n xFieldOnQBigObject: Float!\n yFieldOnQBigObject: String!\n zFieldOnQBigObject: Int!\n}\n\ntype Query {\n bigAbstractResponse: BigAbstractResponse\n bigResponse(artificialDelay: Int! = 0, bigObjects: Int! = 100, deeplyNestedObjects: Int! = 100, nestedObjects: Int! = 100): [BigObject!]!\n \"\"\"Returns response after the given delay\"\"\"\n delay(ms: Int!, response: String!): String!\n floatField(arg: Float): Float\n \"\"\"Returns the value of the received HTTP header.\"\"\"\n headerValue(name: String!): String!\n \"\"\"Returns the value of the given key in the WS initial payload.\"\"\"\n initPayloadValue(key: String!): String!\n initialPayload: Map\n longResponse(artificialDelay: Int! = 0, bytes: Int!): String\n rootFieldWithInput(arg: InputArg!): String!\n rootFieldWithListArg(arg: [String!]!): [String!]!\n rootFieldWithListOfEnumArg(arg: [EnumType!]!): [EnumType!]!\n rootFieldWithListOfInputArg(arg: [InputType!]!): [InputResponse!]!\n rootFieldWithNestedListArg(arg: [[String!]!]!): [[String!]!]!\n secret: Secret @requiresScopes(scopes: [[\"read:secret\"]])\n sharedThings(numOfA: Int!, numOfB: Int!): [Thing!]! @shareable\n}\n\ntype RBigObject {\n aFieldOnRBigObject: String!\n bFieldOnRBigObject: Int!\n cFieldOnRBigObject: Boolean!\n dFieldOnRBigObject: Float!\n eFieldOnRBigObject: String!\n fFieldOnRBigObject: Int!\n gFieldOnRBigObject: Boolean!\n hFieldOnRBigObject: Float!\n iFieldOnRBigObject: String!\n jFieldOnRBigObject: Int!\n kFieldOnRBigObject: Boolean!\n lFieldOnRBigObject: Float!\n mFieldOnRBigObject: String!\n nFieldOnRBigObject: Int!\n oFieldOnRBigObject: Boolean!\n pFieldOnRBigObject: Float!\n qFieldOnRBigObject: String!\n rFieldOnRBigObject: Int!\n sFieldOnRBigObject: Boolean!\n tFieldOnRBigObject: Float!\n uFieldOnRBigObject: String!\n vFieldOnRBigObject: Int!\n wFieldOnRBigObject: Boolean!\n xFieldOnRBigObject: Float!\n yFieldOnRBigObject: String!\n zFieldOnRBigObject: Int!\n}\n\ntype SBigObject {\n aFieldOnSBigObject: String!\n bFieldOnSBigObject: Int!\n cFieldOnSBigObject: Boolean!\n dFieldOnSBigObject: Float!\n eFieldOnSBigObject: String!\n fFieldOnSBigObject: Int!\n gFieldOnSBigObject: Boolean!\n hFieldOnSBigObject: Float!\n iFieldOnSBigObject: String!\n jFieldOnSBigObject: Int!\n kFieldOnSBigObject: Boolean!\n lFieldOnSBigObject: Float!\n mFieldOnSBigObject: String!\n nFieldOnSBigObject: Int!\n oFieldOnSBigObject: Boolean!\n pFieldOnSBigObject: Float!\n qFieldOnSBigObject: String!\n rFieldOnSBigObject: Int!\n sFieldOnSBigObject: Boolean!\n tFieldOnSBigObject: Float!\n uFieldOnSBigObject: String!\n vFieldOnSBigObject: Int!\n wFieldOnSBigObject: Boolean!\n xFieldOnSBigObject: Float!\n yFieldOnSBigObject: String!\n zFieldOnSBigObject: Int!\n}\n\ntype Secret {\n value: String\n}\n\ntype Subscription {\n \"\"\"Returns a stream with the value of the received HTTP header.\"\"\"\n headerValue(name: String!, repeat: Int): TimestampedString!\n \"\"\"\n Returns a stream with the value of value of the given key in the WS initial payload.\n \"\"\"\n initPayloadValue(key: String!, repeat: Int): TimestampedString!\n \"\"\"Returns a stream with the value of the WS initial payload.\"\"\"\n initialPayload(repeat: Int): Map\n returnsError: String\n}\n\ntype TBigObject {\n aFieldOnTBigObject: String!\n bFieldOnTBigObject: Int!\n cFieldOnTBigObject: Boolean!\n dFieldOnTBigObject: Float!\n eFieldOnTBigObject: String!\n fFieldOnTBigObject: Int!\n gFieldOnTBigObject: Boolean!\n hFieldOnTBigObject: Float!\n iFieldOnTBigObject: String!\n jFieldOnTBigObject: Int!\n kFieldOnTBigObject: Boolean!\n lFieldOnTBigObject: Float!\n mFieldOnTBigObject: String!\n nFieldOnTBigObject: Int!\n oFieldOnTBigObject: Boolean!\n pFieldOnTBigObject: Float!\n qFieldOnTBigObject: String!\n rFieldOnTBigObject: Int!\n sFieldOnTBigObject: Boolean!\n tFieldOnTBigObject: Float!\n uFieldOnTBigObject: String!\n vFieldOnTBigObject: Int!\n wFieldOnTBigObject: Boolean!\n xFieldOnTBigObject: Float!\n yFieldOnTBigObject: String!\n zFieldOnTBigObject: Int!\n}\n\ntype Thing {\n b: String! @shareable\n}\n\ntype TimestampedString {\n initialPayload: Map\n \"\"\"Sequence number\"\"\"\n seq: Int!\n \"\"\"Total number of responses to be sent\"\"\"\n total: Int!\n \"\"\"The timestamp when the response was generated.\"\"\"\n unixTime: Int!\n \"\"\"The value of the string.\"\"\"\n value: String!\n}\n\ntype UBigObject {\n aFieldOnUBigObject: String!\n bFieldOnUBigObject: Int!\n cFieldOnUBigObject: Boolean!\n dFieldOnUBigObject: Float!\n eFieldOnUBigObject: String!\n fFieldOnUBigObject: Int!\n gFieldOnUBigObject: Boolean!\n hFieldOnUBigObject: Float!\n iFieldOnUBigObject: String!\n jFieldOnUBigObject: Int!\n kFieldOnUBigObject: Boolean!\n lFieldOnUBigObject: Float!\n mFieldOnUBigObject: String!\n nFieldOnUBigObject: Int!\n oFieldOnUBigObject: Boolean!\n pFieldOnUBigObject: Float!\n qFieldOnUBigObject: String!\n rFieldOnUBigObject: Int!\n sFieldOnUBigObject: Boolean!\n tFieldOnUBigObject: Float!\n uFieldOnUBigObject: String!\n vFieldOnUBigObject: Int!\n wFieldOnUBigObject: Boolean!\n xFieldOnUBigObject: Float!\n yFieldOnUBigObject: String!\n zFieldOnUBigObject: Int!\n}\n\ntype VBigObject {\n aFieldOnVBigObject: String!\n bFieldOnVBigObject: Int!\n cFieldOnVBigObject: Boolean!\n dFieldOnVBigObject: Float!\n eFieldOnVBigObject: String!\n fFieldOnVBigObject: Int!\n gFieldOnVBigObject: Boolean!\n hFieldOnVBigObject: Float!\n iFieldOnVBigObject: String!\n jFieldOnVBigObject: Int!\n kFieldOnVBigObject: Boolean!\n lFieldOnVBigObject: Float!\n mFieldOnVBigObject: String!\n nFieldOnVBigObject: Int!\n oFieldOnVBigObject: Boolean!\n pFieldOnVBigObject: Float!\n qFieldOnVBigObject: String!\n rFieldOnVBigObject: Int!\n sFieldOnVBigObject: Boolean!\n tFieldOnVBigObject: Float!\n uFieldOnVBigObject: String!\n vFieldOnVBigObject: Int!\n wFieldOnVBigObject: Boolean!\n xFieldOnVBigObject: Float!\n yFieldOnVBigObject: String!\n zFieldOnVBigObject: Int!\n}\n\ntype WBigObject {\n aFieldOnWBigObject: String!\n bFieldOnWBigObject: Int!\n cFieldOnWBigObject: Boolean!\n dFieldOnWBigObject: Float!\n eFieldOnWBigObject: String!\n fFieldOnWBigObject: Int!\n gFieldOnWBigObject: Boolean!\n hFieldOnWBigObject: Float!\n iFieldOnWBigObject: String!\n jFieldOnWBigObject: Int!\n kFieldOnWBigObject: Boolean!\n lFieldOnWBigObject: Float!\n mFieldOnWBigObject: String!\n nFieldOnWBigObject: Int!\n oFieldOnWBigObject: Boolean!\n pFieldOnWBigObject: Float!\n qFieldOnWBigObject: String!\n rFieldOnWBigObject: Int!\n sFieldOnWBigObject: Boolean!\n tFieldOnWBigObject: Float!\n uFieldOnWBigObject: String!\n vFieldOnWBigObject: Int!\n wFieldOnWBigObject: Boolean!\n xFieldOnWBigObject: Float!\n yFieldOnWBigObject: String!\n zFieldOnWBigObject: Int!\n}\n\ntype XBigObject {\n aFieldOnXBigObject: String!\n bFieldOnXBigObject: Int!\n cFieldOnXBigObject: Boolean!\n dFieldOnXBigObject: Float!\n eFieldOnXBigObject: String!\n fFieldOnXBigObject: Int!\n gFieldOnXBigObject: Boolean!\n hFieldOnXBigObject: Float!\n iFieldOnXBigObject: String!\n jFieldOnXBigObject: Int!\n kFieldOnXBigObject: Boolean!\n lFieldOnXBigObject: Float!\n mFieldOnXBigObject: String!\n nFieldOnXBigObject: Int!\n oFieldOnXBigObject: Boolean!\n pFieldOnXBigObject: Float!\n qFieldOnXBigObject: String!\n rFieldOnXBigObject: Int!\n sFieldOnXBigObject: Boolean!\n tFieldOnXBigObject: Float!\n uFieldOnXBigObject: String!\n vFieldOnXBigObject: Int!\n wFieldOnXBigObject: Boolean!\n xFieldOnXBigObject: Float!\n yFieldOnXBigObject: String!\n zFieldOnXBigObject: Int!\n}\n\ntype YBigObject {\n aFieldOnYBigObject: String!\n bFieldOnYBigObject: Int!\n cFieldOnYBigObject: Boolean!\n dFieldOnYBigObject: Float!\n eFieldOnYBigObject: String!\n fFieldOnYBigObject: Int!\n gFieldOnYBigObject: Boolean!\n hFieldOnYBigObject: Float!\n iFieldOnYBigObject: String!\n jFieldOnYBigObject: Int!\n kFieldOnYBigObject: Boolean!\n lFieldOnYBigObject: Float!\n mFieldOnYBigObject: String!\n nFieldOnYBigObject: Int!\n oFieldOnYBigObject: Boolean!\n pFieldOnYBigObject: Float!\n qFieldOnYBigObject: String!\n rFieldOnYBigObject: Int!\n sFieldOnYBigObject: Boolean!\n tFieldOnYBigObject: Float!\n uFieldOnYBigObject: String!\n vFieldOnYBigObject: Int!\n wFieldOnYBigObject: Boolean!\n xFieldOnYBigObject: Float!\n yFieldOnYBigObject: String!\n zFieldOnYBigObject: Int!\n}\n\ntype ZBigObject {\n aFieldOnZBigObject: String!\n bFieldOnZBigObject: Int!\n cFieldOnZBigObject: Boolean!\n dFieldOnZBigObject: Float!\n eFieldOnZBigObject: String!\n fFieldOnZBigObject: Int!\n gFieldOnZBigObject: Boolean!\n hFieldOnZBigObject: Float!\n iFieldOnZBigObject: String!\n jFieldOnZBigObject: Int!\n kFieldOnZBigObject: Boolean!\n lFieldOnZBigObject: Float!\n mFieldOnZBigObject: String!\n nFieldOnZBigObject: Int!\n oFieldOnZBigObject: Boolean!\n pFieldOnZBigObject: Float!\n qFieldOnZBigObject: String!\n rFieldOnZBigObject: Int!\n sFieldOnZBigObject: Boolean!\n tFieldOnZBigObject: Float!\n uFieldOnZBigObject: String!\n vFieldOnZBigObject: Int!\n wFieldOnZBigObject: Boolean!\n xFieldOnZBigObject: Float!\n yFieldOnZBigObject: String!\n zFieldOnZBigObject: Int!\n}\n\nscalar link__Import\n\nenum link__Purpose {\n EXECUTION\n SECURITY\n}\n\nscalar openfed__FieldSet\n\nscalar openfed__Scope",
+ "c8d8fe56b658fa642dbb31c0fc3d6f024f4aff10": "schema {\n query: Query\n subscription: Subscription\n}\n\ndirective @key(fields: openfed__FieldSet!, resolvable: Boolean = true) repeatable on INTERFACE | OBJECT\n\ndirective @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA\n\ndirective @requiresScopes(scopes: [[openfed__Scope!]!]!) on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR\n\ndirective @shareable repeatable on FIELD_DEFINITION | OBJECT\n\ntype ABigObject {\n aFieldOnABigObject: String!\n bFieldOnABigObject: Int!\n cFieldOnABigObject: Boolean!\n dFieldOnABigObject: Float!\n eFieldOnABigObject: String!\n fFieldOnABigObject: Int!\n gFieldOnABigObject: Boolean!\n hFieldOnABigObject: Float!\n iFieldOnABigObject: String!\n jFieldOnABigObject: Int!\n kFieldOnABigObject: Boolean!\n lFieldOnABigObject: Float!\n mFieldOnABigObject: String!\n nFieldOnABigObject: Int!\n oFieldOnABigObject: Boolean!\n pFieldOnABigObject: Float!\n qFieldOnABigObject: String!\n rFieldOnABigObject: Int!\n sFieldOnABigObject: Boolean!\n tFieldOnABigObject: Float!\n uFieldOnABigObject: String!\n vFieldOnABigObject: Int!\n wFieldOnABigObject: Boolean!\n xFieldOnABigObject: Float!\n yFieldOnABigObject: String!\n zFieldOnABigObject: Int!\n}\n\ntype BBigObject {\n aFieldOnBBigObject: String!\n bFieldOnBBigObject: Int!\n cFieldOnBBigObject: Boolean!\n dFieldOnBBigObject: Float!\n eFieldOnBBigObject: String!\n fFieldOnBBigObject: Int!\n gFieldOnBBigObject: Boolean!\n hFieldOnBBigObject: Float!\n iFieldOnBBigObject: String!\n jFieldOnBBigObject: Int!\n kFieldOnBBigObject: Boolean!\n lFieldOnBBigObject: Float!\n mFieldOnBBigObject: String!\n nFieldOnBBigObject: Int!\n oFieldOnBBigObject: Boolean!\n pFieldOnBBigObject: Float!\n qFieldOnBBigObject: String!\n rFieldOnBBigObject: Int!\n sFieldOnBBigObject: Boolean!\n tFieldOnBBigObject: Float!\n uFieldOnBBigObject: String!\n vFieldOnBBigObject: Int!\n wFieldOnBBigObject: Boolean!\n xFieldOnBBigObject: Float!\n yFieldOnBBigObject: String!\n zFieldOnBBigObject: Int!\n}\n\nunion BigAbstractResponse = ABigObject | BBigObject | CBigObject | DBigObject | EBigObject | FBigObject | GBigObject | HBigObject | IBigObject | JBigObject | KBigObject | LBigObject | MBigObject | NBigObject | OBigObject | PBigObject | QBigObject | RBigObject | SBigObject | TBigObject | UBigObject | VBigObject | WBigObject | XBigObject | YBigObject | ZBigObject\n\ntype BigObject {\n nestedObjects: [NestedObject!]!\n}\n\ntype CBigObject {\n aFieldOnCBigObject: String!\n bFieldOnCBigObject: Int!\n cFieldOnCBigObject: Boolean!\n dFieldOnCBigObject: Float!\n eFieldOnCBigObject: String!\n fFieldOnCBigObject: Int!\n gFieldOnCBigObject: Boolean!\n hFieldOnCBigObject: Float!\n iFieldOnCBigObject: String!\n jFieldOnCBigObject: Int!\n kFieldOnCBigObject: Boolean!\n lFieldOnCBigObject: Float!\n mFieldOnCBigObject: String!\n nFieldOnCBigObject: Int!\n oFieldOnCBigObject: Boolean!\n pFieldOnCBigObject: Float!\n qFieldOnCBigObject: String!\n rFieldOnCBigObject: Int!\n sFieldOnCBigObject: Boolean!\n tFieldOnCBigObject: Float!\n uFieldOnCBigObject: String!\n vFieldOnCBigObject: Int!\n wFieldOnCBigObject: Boolean!\n xFieldOnCBigObject: Float!\n yFieldOnCBigObject: String!\n zFieldOnCBigObject: Int!\n}\n\ntype DBigObject {\n aFieldOnDBigObject: String!\n bFieldOnDBigObject: Int!\n cFieldOnDBigObject: Boolean!\n dFieldOnDBigObject: Float!\n eFieldOnDBigObject: String!\n fFieldOnDBigObject: Int!\n gFieldOnDBigObject: Boolean!\n hFieldOnDBigObject: Float!\n iFieldOnDBigObject: String!\n jFieldOnDBigObject: Int!\n kFieldOnDBigObject: Boolean!\n lFieldOnDBigObject: Float!\n mFieldOnDBigObject: String!\n nFieldOnDBigObject: Int!\n oFieldOnDBigObject: Boolean!\n pFieldOnDBigObject: Float!\n qFieldOnDBigObject: String!\n rFieldOnDBigObject: Int!\n sFieldOnDBigObject: Boolean!\n tFieldOnDBigObject: Float!\n uFieldOnDBigObject: String!\n vFieldOnDBigObject: Int!\n wFieldOnDBigObject: Boolean!\n xFieldOnDBigObject: Float!\n yFieldOnDBigObject: String!\n zFieldOnDBigObject: Int!\n}\n\ntype DeeplyNestedObject {\n aFieldOnDeeplyNestedObject: String!\n bFieldOnDeeplyNestedObject: Int!\n cFieldOnDeeplyNestedObject: Boolean!\n dFieldOnDeeplyNestedObject: Float!\n eFieldOnDeeplyNestedObject: String!\n fFieldOnDeeplyNestedObject: Int!\n gFieldOnDeeplyNestedObject: Boolean!\n hFieldOnDeeplyNestedObject: Float!\n iFieldOnDeeplyNestedObject: String!\n jFieldOnDeeplyNestedObject: Int!\n kFieldOnDeeplyNestedObject: Boolean!\n lFieldOnDeeplyNestedObject: Float!\n mFieldOnDeeplyNestedObject: String!\n nFieldOnDeeplyNestedObject: Int!\n oFieldOnDeeplyNestedObject: Boolean!\n pFieldOnDeeplyNestedObject: Float!\n qFieldOnDeeplyNestedObject: String!\n rFieldOnDeeplyNestedObject: Int!\n sFieldOnDeeplyNestedObject: Boolean!\n tFieldOnDeeplyNestedObject: Float!\n uFieldOnDeeplyNestedObject: String!\n vFieldOnDeeplyNestedObject: Int!\n wFieldOnDeeplyNestedObject: Boolean!\n xFieldOnDeeplyNestedObject: Float!\n yFieldOnDeeplyNestedObject: String!\n zFieldOnDeeplyNestedObject: Int!\n}\n\ntype EBigObject {\n aFieldOnEBigObject: String!\n bFieldOnEBigObject: Int!\n cFieldOnEBigObject: Boolean!\n dFieldOnEBigObject: Float!\n eFieldOnEBigObject: String!\n fFieldOnEBigObject: Int!\n gFieldOnEBigObject: Boolean!\n hFieldOnEBigObject: Float!\n iFieldOnEBigObject: String!\n jFieldOnEBigObject: Int!\n kFieldOnEBigObject: Boolean!\n lFieldOnEBigObject: Float!\n mFieldOnEBigObject: String!\n nFieldOnEBigObject: Int!\n oFieldOnEBigObject: Boolean!\n pFieldOnEBigObject: Float!\n qFieldOnEBigObject: String!\n rFieldOnEBigObject: Int!\n sFieldOnEBigObject: Boolean!\n tFieldOnEBigObject: Float!\n uFieldOnEBigObject: String!\n vFieldOnEBigObject: Int!\n wFieldOnEBigObject: Boolean!\n xFieldOnEBigObject: Float!\n yFieldOnEBigObject: String!\n zFieldOnEBigObject: Int!\n}\n\ntype Employee @key(fields: \"id\") {\n fieldThrowsError: String\n id: Int!\n}\n\nenum EnumType {\n A\n B\n C\n}\n\ntype FBigObject {\n aFieldOnFBigObject: String!\n bFieldOnFBigObject: Int!\n cFieldOnFBigObject: Boolean!\n dFieldOnFBigObject: Float!\n eFieldOnFBigObject: String!\n fFieldOnFBigObject: Int!\n gFieldOnFBigObject: Boolean!\n hFieldOnFBigObject: Float!\n iFieldOnFBigObject: String!\n jFieldOnFBigObject: Int!\n kFieldOnFBigObject: Boolean!\n lFieldOnFBigObject: Float!\n mFieldOnFBigObject: String!\n nFieldOnFBigObject: Int!\n oFieldOnFBigObject: Boolean!\n pFieldOnFBigObject: Float!\n qFieldOnFBigObject: String!\n rFieldOnFBigObject: Int!\n sFieldOnFBigObject: Boolean!\n tFieldOnFBigObject: Float!\n uFieldOnFBigObject: String!\n vFieldOnFBigObject: Int!\n wFieldOnFBigObject: Boolean!\n xFieldOnFBigObject: Float!\n yFieldOnFBigObject: String!\n zFieldOnFBigObject: Int!\n}\n\ntype GBigObject {\n aFieldOnGBigObject: String!\n bFieldOnGBigObject: Int!\n cFieldOnGBigObject: Boolean!\n dFieldOnGBigObject: Float!\n eFieldOnGBigObject: String!\n fFieldOnGBigObject: Int!\n gFieldOnGBigObject: Boolean!\n hFieldOnGBigObject: Float!\n iFieldOnGBigObject: String!\n jFieldOnGBigObject: Int!\n kFieldOnGBigObject: Boolean!\n lFieldOnGBigObject: Float!\n mFieldOnGBigObject: String!\n nFieldOnGBigObject: Int!\n oFieldOnGBigObject: Boolean!\n pFieldOnGBigObject: Float!\n qFieldOnGBigObject: String!\n rFieldOnGBigObject: Int!\n sFieldOnGBigObject: Boolean!\n tFieldOnGBigObject: Float!\n uFieldOnGBigObject: String!\n vFieldOnGBigObject: Int!\n wFieldOnGBigObject: Boolean!\n xFieldOnGBigObject: Float!\n yFieldOnGBigObject: String!\n zFieldOnGBigObject: Int!\n}\n\ntype HBigObject {\n aFieldOnHBigObject: String!\n bFieldOnHBigObject: Int!\n cFieldOnHBigObject: Boolean!\n dFieldOnHBigObject: Float!\n eFieldOnHBigObject: String!\n fFieldOnHBigObject: Int!\n gFieldOnHBigObject: Boolean!\n hFieldOnHBigObject: Float!\n iFieldOnHBigObject: String!\n jFieldOnHBigObject: Int!\n kFieldOnHBigObject: Boolean!\n lFieldOnHBigObject: Float!\n mFieldOnHBigObject: String!\n nFieldOnHBigObject: Int!\n oFieldOnHBigObject: Boolean!\n pFieldOnHBigObject: Float!\n qFieldOnHBigObject: String!\n rFieldOnHBigObject: Int!\n sFieldOnHBigObject: Boolean!\n tFieldOnHBigObject: Float!\n uFieldOnHBigObject: String!\n vFieldOnHBigObject: Int!\n wFieldOnHBigObject: Boolean!\n xFieldOnHBigObject: Float!\n yFieldOnHBigObject: String!\n zFieldOnHBigObject: Int!\n}\n\ntype IBigObject {\n aFieldOnIBigObject: String!\n bFieldOnIBigObject: Int!\n cFieldOnIBigObject: Boolean!\n dFieldOnIBigObject: Float!\n eFieldOnIBigObject: String!\n fFieldOnIBigObject: Int!\n gFieldOnIBigObject: Boolean!\n hFieldOnIBigObject: Float!\n iFieldOnIBigObject: String!\n jFieldOnIBigObject: Int!\n kFieldOnIBigObject: Boolean!\n lFieldOnIBigObject: Float!\n mFieldOnIBigObject: String!\n nFieldOnIBigObject: Int!\n oFieldOnIBigObject: Boolean!\n pFieldOnIBigObject: Float!\n qFieldOnIBigObject: String!\n rFieldOnIBigObject: Int!\n sFieldOnIBigObject: Boolean!\n tFieldOnIBigObject: Float!\n uFieldOnIBigObject: String!\n vFieldOnIBigObject: Int!\n wFieldOnIBigObject: Boolean!\n xFieldOnIBigObject: Float!\n yFieldOnIBigObject: String!\n zFieldOnIBigObject: Int!\n}\n\ninput InputArg {\n enum: EnumType\n enums: [EnumType!]\n string: String\n strings: [String!]\n}\n\ntype InputResponse {\n arg: String!\n}\n\ninput InputType {\n arg: String!\n}\n\ntype JBigObject {\n aFieldOnJBigObject: String!\n bFieldOnJBigObject: Int!\n cFieldOnJBigObject: Boolean!\n dFieldOnJBigObject: Float!\n eFieldOnJBigObject: String!\n fFieldOnJBigObject: Int!\n gFieldOnJBigObject: Boolean!\n hFieldOnJBigObject: Float!\n iFieldOnJBigObject: String!\n jFieldOnJBigObject: Int!\n kFieldOnJBigObject: Boolean!\n lFieldOnJBigObject: Float!\n mFieldOnJBigObject: String!\n nFieldOnJBigObject: Int!\n oFieldOnJBigObject: Boolean!\n pFieldOnJBigObject: Float!\n qFieldOnJBigObject: String!\n rFieldOnJBigObject: Int!\n sFieldOnJBigObject: Boolean!\n tFieldOnJBigObject: Float!\n uFieldOnJBigObject: String!\n vFieldOnJBigObject: Int!\n wFieldOnJBigObject: Boolean!\n xFieldOnJBigObject: Float!\n yFieldOnJBigObject: String!\n zFieldOnJBigObject: Int!\n}\n\ntype KBigObject {\n aFieldOnKBigObject: String!\n bFieldOnKBigObject: Int!\n cFieldOnKBigObject: Boolean!\n dFieldOnKBigObject: Float!\n eFieldOnKBigObject: String!\n fFieldOnKBigObject: Int!\n gFieldOnKBigObject: Boolean!\n hFieldOnKBigObject: Float!\n iFieldOnKBigObject: String!\n jFieldOnKBigObject: Int!\n kFieldOnKBigObject: Boolean!\n lFieldOnKBigObject: Float!\n mFieldOnKBigObject: String!\n nFieldOnKBigObject: Int!\n oFieldOnKBigObject: Boolean!\n pFieldOnKBigObject: Float!\n qFieldOnKBigObject: String!\n rFieldOnKBigObject: Int!\n sFieldOnKBigObject: Boolean!\n tFieldOnKBigObject: Float!\n uFieldOnKBigObject: String!\n vFieldOnKBigObject: Int!\n wFieldOnKBigObject: Boolean!\n xFieldOnKBigObject: Float!\n yFieldOnKBigObject: String!\n zFieldOnKBigObject: Int!\n}\n\ntype LBigObject {\n aFieldOnLBigObject: String!\n bFieldOnLBigObject: Int!\n cFieldOnLBigObject: Boolean!\n dFieldOnLBigObject: Float!\n eFieldOnLBigObject: String!\n fFieldOnLBigObject: Int!\n gFieldOnLBigObject: Boolean!\n hFieldOnLBigObject: Float!\n iFieldOnLBigObject: String!\n jFieldOnLBigObject: Int!\n kFieldOnLBigObject: Boolean!\n lFieldOnLBigObject: Float!\n mFieldOnLBigObject: String!\n nFieldOnLBigObject: Int!\n oFieldOnLBigObject: Boolean!\n pFieldOnLBigObject: Float!\n qFieldOnLBigObject: String!\n rFieldOnLBigObject: Int!\n sFieldOnLBigObject: Boolean!\n tFieldOnLBigObject: Float!\n uFieldOnLBigObject: String!\n vFieldOnLBigObject: Int!\n wFieldOnLBigObject: Boolean!\n xFieldOnLBigObject: Float!\n yFieldOnLBigObject: String!\n zFieldOnLBigObject: Int!\n}\n\ntype MBigObject {\n aFieldOnMBigObject: String!\n bFieldOnMBigObject: Int!\n cFieldOnMBigObject: Boolean!\n dFieldOnMBigObject: Float!\n eFieldOnMBigObject: String!\n fFieldOnMBigObject: Int!\n gFieldOnMBigObject: Boolean!\n hFieldOnMBigObject: Float!\n iFieldOnMBigObject: String!\n jFieldOnMBigObject: Int!\n kFieldOnMBigObject: Boolean!\n lFieldOnMBigObject: Float!\n mFieldOnMBigObject: String!\n nFieldOnMBigObject: Int!\n oFieldOnMBigObject: Boolean!\n pFieldOnMBigObject: Float!\n qFieldOnMBigObject: String!\n rFieldOnMBigObject: Int!\n sFieldOnMBigObject: Boolean!\n tFieldOnMBigObject: Float!\n uFieldOnMBigObject: String!\n vFieldOnMBigObject: Int!\n wFieldOnMBigObject: Boolean!\n xFieldOnMBigObject: Float!\n yFieldOnMBigObject: String!\n zFieldOnMBigObject: Int!\n}\n\nscalar Map\n\ntype NBigObject {\n aFieldOnNBigObject: String!\n bFieldOnNBigObject: Int!\n cFieldOnNBigObject: Boolean!\n dFieldOnNBigObject: Float!\n eFieldOnNBigObject: String!\n fFieldOnNBigObject: Int!\n gFieldOnNBigObject: Boolean!\n hFieldOnNBigObject: Float!\n iFieldOnNBigObject: String!\n jFieldOnNBigObject: Int!\n kFieldOnNBigObject: Boolean!\n lFieldOnNBigObject: Float!\n mFieldOnNBigObject: String!\n nFieldOnNBigObject: Int!\n oFieldOnNBigObject: Boolean!\n pFieldOnNBigObject: Float!\n qFieldOnNBigObject: String!\n rFieldOnNBigObject: Int!\n sFieldOnNBigObject: Boolean!\n tFieldOnNBigObject: Float!\n uFieldOnNBigObject: String!\n vFieldOnNBigObject: Int!\n wFieldOnNBigObject: Boolean!\n xFieldOnNBigObject: Float!\n yFieldOnNBigObject: String!\n zFieldOnNBigObject: Int!\n}\n\ntype NestedObject {\n deeplyNestedObjects: [DeeplyNestedObject!]!\n}\n\ntype OBigObject {\n aFieldOnOBigObject: String!\n bFieldOnOBigObject: Int!\n cFieldOnOBigObject: Boolean!\n dFieldOnOBigObject: Float!\n eFieldOnOBigObject: String!\n fFieldOnOBigObject: Int!\n gFieldOnOBigObject: Boolean!\n hFieldOnOBigObject: Float!\n iFieldOnOBigObject: String!\n jFieldOnOBigObject: Int!\n kFieldOnOBigObject: Boolean!\n lFieldOnOBigObject: Float!\n mFieldOnOBigObject: String!\n nFieldOnOBigObject: Int!\n oFieldOnOBigObject: Boolean!\n pFieldOnOBigObject: Float!\n qFieldOnOBigObject: String!\n rFieldOnOBigObject: Int!\n sFieldOnOBigObject: Boolean!\n tFieldOnOBigObject: Float!\n uFieldOnOBigObject: String!\n vFieldOnOBigObject: Int!\n wFieldOnOBigObject: Boolean!\n xFieldOnOBigObject: Float!\n yFieldOnOBigObject: String!\n zFieldOnOBigObject: Int!\n}\n\ntype PBigObject {\n aFieldOnPBigObject: String!\n bFieldOnPBigObject: Int!\n cFieldOnPBigObject: Boolean!\n dFieldOnPBigObject: Float!\n eFieldOnPBigObject: String!\n fFieldOnPBigObject: Int!\n gFieldOnPBigObject: Boolean!\n hFieldOnPBigObject: Float!\n iFieldOnPBigObject: String!\n jFieldOnPBigObject: Int!\n kFieldOnPBigObject: Boolean!\n lFieldOnPBigObject: Float!\n mFieldOnPBigObject: String!\n nFieldOnPBigObject: Int!\n oFieldOnPBigObject: Boolean!\n pFieldOnPBigObject: Float!\n qFieldOnPBigObject: String!\n rFieldOnPBigObject: Int!\n sFieldOnPBigObject: Boolean!\n tFieldOnPBigObject: Float!\n uFieldOnPBigObject: String!\n vFieldOnPBigObject: Int!\n wFieldOnPBigObject: Boolean!\n xFieldOnPBigObject: Float!\n yFieldOnPBigObject: String!\n zFieldOnPBigObject: Int!\n}\n\ntype QBigObject {\n aFieldOnQBigObject: String!\n bFieldOnQBigObject: Int!\n cFieldOnQBigObject: Boolean!\n dFieldOnQBigObject: Float!\n eFieldOnQBigObject: String!\n fFieldOnQBigObject: Int!\n gFieldOnQBigObject: Boolean!\n hFieldOnQBigObject: Float!\n iFieldOnQBigObject: String!\n jFieldOnQBigObject: Int!\n kFieldOnQBigObject: Boolean!\n lFieldOnQBigObject: Float!\n mFieldOnQBigObject: String!\n nFieldOnQBigObject: Int!\n oFieldOnQBigObject: Boolean!\n pFieldOnQBigObject: Float!\n qFieldOnQBigObject: String!\n rFieldOnQBigObject: Int!\n sFieldOnQBigObject: Boolean!\n tFieldOnQBigObject: Float!\n uFieldOnQBigObject: String!\n vFieldOnQBigObject: Int!\n wFieldOnQBigObject: Boolean!\n xFieldOnQBigObject: Float!\n yFieldOnQBigObject: String!\n zFieldOnQBigObject: Int!\n}\n\ntype Query {\n bigAbstractResponse: BigAbstractResponse\n bigResponse(artificialDelay: Int! = 0, bigObjects: Int! = 100, deeplyNestedObjects: Int! = 100, nestedObjects: Int! = 100): [BigObject!]!\n \"\"\"Returns response after the given delay\"\"\"\n delay(ms: Int!, response: String!): String!\n floatField(arg: Float): Float\n \"\"\"Returns the value of the received HTTP header.\"\"\"\n headerValue(name: String!): String!\n \"\"\"Returns the value of the given key in the WS initial payload.\"\"\"\n initPayloadValue(key: String!): String!\n initialPayload: Map\n longResponse(artificialDelay: Int! = 0, bytes: Int!): String\n rootFieldWithInput(arg: InputArg!): String!\n rootFieldWithListArg(arg: [String!]!): [String!]!\n rootFieldWithListOfEnumArg(arg: [EnumType!]!): [EnumType!]!\n rootFieldWithListOfInputArg(arg: [InputType!]!): [InputResponse!]!\n rootFieldWithNestedListArg(arg: [[String!]!]!): [[String!]!]!\n secret: Secret @requiresScopes(scopes: [[\"read:secret\"]])\n sharedThings(numOfA: Int!, numOfB: Int!): [Thing!]! @shareable\n}\n\ntype RBigObject {\n aFieldOnRBigObject: String!\n bFieldOnRBigObject: Int!\n cFieldOnRBigObject: Boolean!\n dFieldOnRBigObject: Float!\n eFieldOnRBigObject: String!\n fFieldOnRBigObject: Int!\n gFieldOnRBigObject: Boolean!\n hFieldOnRBigObject: Float!\n iFieldOnRBigObject: String!\n jFieldOnRBigObject: Int!\n kFieldOnRBigObject: Boolean!\n lFieldOnRBigObject: Float!\n mFieldOnRBigObject: String!\n nFieldOnRBigObject: Int!\n oFieldOnRBigObject: Boolean!\n pFieldOnRBigObject: Float!\n qFieldOnRBigObject: String!\n rFieldOnRBigObject: Int!\n sFieldOnRBigObject: Boolean!\n tFieldOnRBigObject: Float!\n uFieldOnRBigObject: String!\n vFieldOnRBigObject: Int!\n wFieldOnRBigObject: Boolean!\n xFieldOnRBigObject: Float!\n yFieldOnRBigObject: String!\n zFieldOnRBigObject: Int!\n}\n\ntype SBigObject {\n aFieldOnSBigObject: String!\n bFieldOnSBigObject: Int!\n cFieldOnSBigObject: Boolean!\n dFieldOnSBigObject: Float!\n eFieldOnSBigObject: String!\n fFieldOnSBigObject: Int!\n gFieldOnSBigObject: Boolean!\n hFieldOnSBigObject: Float!\n iFieldOnSBigObject: String!\n jFieldOnSBigObject: Int!\n kFieldOnSBigObject: Boolean!\n lFieldOnSBigObject: Float!\n mFieldOnSBigObject: String!\n nFieldOnSBigObject: Int!\n oFieldOnSBigObject: Boolean!\n pFieldOnSBigObject: Float!\n qFieldOnSBigObject: String!\n rFieldOnSBigObject: Int!\n sFieldOnSBigObject: Boolean!\n tFieldOnSBigObject: Float!\n uFieldOnSBigObject: String!\n vFieldOnSBigObject: Int!\n wFieldOnSBigObject: Boolean!\n xFieldOnSBigObject: Float!\n yFieldOnSBigObject: String!\n zFieldOnSBigObject: Int!\n}\n\ntype Secret {\n value: String\n}\n\ntype SubscribeMetadata {\n initialPayload: Map\n subscribeExtensions: Map\n}\n\ntype Subscription {\n \"\"\"Returns a stream with the value of the received HTTP header.\"\"\"\n headerValue(name: String!, repeat: Int): TimestampedString!\n \"\"\"\n Returns a stream with the value of value of the given key in the WS initial payload.\n \"\"\"\n initPayloadValue(key: String!, repeat: Int): TimestampedString!\n \"\"\"Returns a stream with the value of the WS initial payload.\"\"\"\n initialPayload(repeat: Int): Map\n \"\"\"\n Returns a stream with the values of the WS initial payload and subscribe extensions\n \"\"\"\n metadata(repeat: Int! = 1): SubscribeMetadata!\n returnsError: String!\n}\n\ntype TBigObject {\n aFieldOnTBigObject: String!\n bFieldOnTBigObject: Int!\n cFieldOnTBigObject: Boolean!\n dFieldOnTBigObject: Float!\n eFieldOnTBigObject: String!\n fFieldOnTBigObject: Int!\n gFieldOnTBigObject: Boolean!\n hFieldOnTBigObject: Float!\n iFieldOnTBigObject: String!\n jFieldOnTBigObject: Int!\n kFieldOnTBigObject: Boolean!\n lFieldOnTBigObject: Float!\n mFieldOnTBigObject: String!\n nFieldOnTBigObject: Int!\n oFieldOnTBigObject: Boolean!\n pFieldOnTBigObject: Float!\n qFieldOnTBigObject: String!\n rFieldOnTBigObject: Int!\n sFieldOnTBigObject: Boolean!\n tFieldOnTBigObject: Float!\n uFieldOnTBigObject: String!\n vFieldOnTBigObject: Int!\n wFieldOnTBigObject: Boolean!\n xFieldOnTBigObject: Float!\n yFieldOnTBigObject: String!\n zFieldOnTBigObject: Int!\n}\n\ntype Thing {\n b: String! @shareable\n}\n\ntype TimestampedString {\n extensions: Map\n initialPayload: Map\n \"\"\"Sequence number\"\"\"\n seq: Int!\n \"\"\"Total number of responses to be sent\"\"\"\n total: Int!\n \"\"\"The timestamp when the response was generated.\"\"\"\n unixTime: Int!\n \"\"\"The value of the string.\"\"\"\n value: String!\n}\n\ntype UBigObject {\n aFieldOnUBigObject: String!\n bFieldOnUBigObject: Int!\n cFieldOnUBigObject: Boolean!\n dFieldOnUBigObject: Float!\n eFieldOnUBigObject: String!\n fFieldOnUBigObject: Int!\n gFieldOnUBigObject: Boolean!\n hFieldOnUBigObject: Float!\n iFieldOnUBigObject: String!\n jFieldOnUBigObject: Int!\n kFieldOnUBigObject: Boolean!\n lFieldOnUBigObject: Float!\n mFieldOnUBigObject: String!\n nFieldOnUBigObject: Int!\n oFieldOnUBigObject: Boolean!\n pFieldOnUBigObject: Float!\n qFieldOnUBigObject: String!\n rFieldOnUBigObject: Int!\n sFieldOnUBigObject: Boolean!\n tFieldOnUBigObject: Float!\n uFieldOnUBigObject: String!\n vFieldOnUBigObject: Int!\n wFieldOnUBigObject: Boolean!\n xFieldOnUBigObject: Float!\n yFieldOnUBigObject: String!\n zFieldOnUBigObject: Int!\n}\n\ntype VBigObject {\n aFieldOnVBigObject: String!\n bFieldOnVBigObject: Int!\n cFieldOnVBigObject: Boolean!\n dFieldOnVBigObject: Float!\n eFieldOnVBigObject: String!\n fFieldOnVBigObject: Int!\n gFieldOnVBigObject: Boolean!\n hFieldOnVBigObject: Float!\n iFieldOnVBigObject: String!\n jFieldOnVBigObject: Int!\n kFieldOnVBigObject: Boolean!\n lFieldOnVBigObject: Float!\n mFieldOnVBigObject: String!\n nFieldOnVBigObject: Int!\n oFieldOnVBigObject: Boolean!\n pFieldOnVBigObject: Float!\n qFieldOnVBigObject: String!\n rFieldOnVBigObject: Int!\n sFieldOnVBigObject: Boolean!\n tFieldOnVBigObject: Float!\n uFieldOnVBigObject: String!\n vFieldOnVBigObject: Int!\n wFieldOnVBigObject: Boolean!\n xFieldOnVBigObject: Float!\n yFieldOnVBigObject: String!\n zFieldOnVBigObject: Int!\n}\n\ntype WBigObject {\n aFieldOnWBigObject: String!\n bFieldOnWBigObject: Int!\n cFieldOnWBigObject: Boolean!\n dFieldOnWBigObject: Float!\n eFieldOnWBigObject: String!\n fFieldOnWBigObject: Int!\n gFieldOnWBigObject: Boolean!\n hFieldOnWBigObject: Float!\n iFieldOnWBigObject: String!\n jFieldOnWBigObject: Int!\n kFieldOnWBigObject: Boolean!\n lFieldOnWBigObject: Float!\n mFieldOnWBigObject: String!\n nFieldOnWBigObject: Int!\n oFieldOnWBigObject: Boolean!\n pFieldOnWBigObject: Float!\n qFieldOnWBigObject: String!\n rFieldOnWBigObject: Int!\n sFieldOnWBigObject: Boolean!\n tFieldOnWBigObject: Float!\n uFieldOnWBigObject: String!\n vFieldOnWBigObject: Int!\n wFieldOnWBigObject: Boolean!\n xFieldOnWBigObject: Float!\n yFieldOnWBigObject: String!\n zFieldOnWBigObject: Int!\n}\n\ntype XBigObject {\n aFieldOnXBigObject: String!\n bFieldOnXBigObject: Int!\n cFieldOnXBigObject: Boolean!\n dFieldOnXBigObject: Float!\n eFieldOnXBigObject: String!\n fFieldOnXBigObject: Int!\n gFieldOnXBigObject: Boolean!\n hFieldOnXBigObject: Float!\n iFieldOnXBigObject: String!\n jFieldOnXBigObject: Int!\n kFieldOnXBigObject: Boolean!\n lFieldOnXBigObject: Float!\n mFieldOnXBigObject: String!\n nFieldOnXBigObject: Int!\n oFieldOnXBigObject: Boolean!\n pFieldOnXBigObject: Float!\n qFieldOnXBigObject: String!\n rFieldOnXBigObject: Int!\n sFieldOnXBigObject: Boolean!\n tFieldOnXBigObject: Float!\n uFieldOnXBigObject: String!\n vFieldOnXBigObject: Int!\n wFieldOnXBigObject: Boolean!\n xFieldOnXBigObject: Float!\n yFieldOnXBigObject: String!\n zFieldOnXBigObject: Int!\n}\n\ntype YBigObject {\n aFieldOnYBigObject: String!\n bFieldOnYBigObject: Int!\n cFieldOnYBigObject: Boolean!\n dFieldOnYBigObject: Float!\n eFieldOnYBigObject: String!\n fFieldOnYBigObject: Int!\n gFieldOnYBigObject: Boolean!\n hFieldOnYBigObject: Float!\n iFieldOnYBigObject: String!\n jFieldOnYBigObject: Int!\n kFieldOnYBigObject: Boolean!\n lFieldOnYBigObject: Float!\n mFieldOnYBigObject: String!\n nFieldOnYBigObject: Int!\n oFieldOnYBigObject: Boolean!\n pFieldOnYBigObject: Float!\n qFieldOnYBigObject: String!\n rFieldOnYBigObject: Int!\n sFieldOnYBigObject: Boolean!\n tFieldOnYBigObject: Float!\n uFieldOnYBigObject: String!\n vFieldOnYBigObject: Int!\n wFieldOnYBigObject: Boolean!\n xFieldOnYBigObject: Float!\n yFieldOnYBigObject: String!\n zFieldOnYBigObject: Int!\n}\n\ntype ZBigObject {\n aFieldOnZBigObject: String!\n bFieldOnZBigObject: Int!\n cFieldOnZBigObject: Boolean!\n dFieldOnZBigObject: Float!\n eFieldOnZBigObject: String!\n fFieldOnZBigObject: Int!\n gFieldOnZBigObject: Boolean!\n hFieldOnZBigObject: Float!\n iFieldOnZBigObject: String!\n jFieldOnZBigObject: Int!\n kFieldOnZBigObject: Boolean!\n lFieldOnZBigObject: Float!\n mFieldOnZBigObject: String!\n nFieldOnZBigObject: Int!\n oFieldOnZBigObject: Boolean!\n pFieldOnZBigObject: Float!\n qFieldOnZBigObject: String!\n rFieldOnZBigObject: Int!\n sFieldOnZBigObject: Boolean!\n tFieldOnZBigObject: Float!\n uFieldOnZBigObject: String!\n vFieldOnZBigObject: Int!\n wFieldOnZBigObject: Boolean!\n xFieldOnZBigObject: Float!\n yFieldOnZBigObject: String!\n zFieldOnZBigObject: Int!\n}\n\nscalar link__Import\n\nenum link__Purpose {\n EXECUTION\n SECURITY\n}\n\nscalar openfed__FieldSet\n\nscalar openfed__Scope",
"865e365ca4e3de8aec4ccd25e875ca9a82a7edde": "schema {\n mutation: Mutation\n}\n\ndirective @key(fields: openfed__FieldSet!, resolvable: Boolean = true) repeatable on INTERFACE | OBJECT\n\ndirective @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA\n\ntype Employee @key(fields: \"id\") {\n id: Int!\n isAvailable: Boolean\n}\n\ntype Mutation {\n \"\"\" This mutation updates the availability status of an employee in the system.\n \"\"\"\n updateAvailability(employeeID: Int!, isAvailable: Boolean!): Employee!\n}\n\nscalar link__Import\n\nenum link__Purpose {\n EXECUTION\n SECURITY\n}\n\nscalar openfed__FieldSet",
"10eccb92890a5709d24ac8c1293264d758b997c7": "schema {\n mutation: Mutation\n}\n\ndirective @inaccessible on ARGUMENT_DEFINITION | ENUM | ENUM_VALUE | FIELD_DEFINITION | INPUT_FIELD_DEFINITION | INPUT_OBJECT | INTERFACE | OBJECT | SCALAR | UNION\n\ndirective @key(fields: openfed__FieldSet!, resolvable: Boolean = true) repeatable on INTERFACE | OBJECT\n\ndirective @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA\n\ntype Employee @key(fields: \"id\") {\n currentMood: Mood!\n id: Int!\n}\n\nenum Mood {\n APATHETIC @inaccessible\n HAPPY\n SAD\n}\n\ntype Mutation {\n \"\"\" This mutation update the mood of an employee. \"\"\"\n updateMood(employeeID: Int!, mood: Mood!): Employee!\n}\n\nscalar link__Import\n\nenum link__Purpose {\n EXECUTION\n SECURITY\n}\n\nscalar openfed__FieldSet",
"0c7a814514a54c0b54af7ea5fa33730a321921e6": "directive @key(fields: openfed__FieldSet!, resolvable: Boolean = true) repeatable on INTERFACE | OBJECT\n\ndirective @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA\n\ntype Country @key(fields: \"key { name }\") {\n key: CountryKey!\n language: String\n}\n\ntype CountryKey {\n name: String!\n}\n\nscalar link__Import\n\nenum link__Purpose {\n EXECUTION\n SECURITY\n}\n\nscalar openfed__FieldSet"
},
- "graphqlClientSchema": "schema {\n query: Query\n mutation: Mutation\n subscription: Subscription\n}\n\ntype Query {\n employee(id: Int!): Employee\n employeeAsList(id: Int!): [Employee]\n employees: [Employee]\n products: [Products!]!\n teammates(team: Department!): [Employee!]!\n firstEmployee: Employee!\n findEmployeesBy(criteria: FindEmployeeCriteria!): [Employee!]!\n \"\"\" This is a GraphQL query that retrieves a list of employees.\"\"\"\n findEmployees(criteria: SearchInput): [Employee!]!\n productTypes: [Products!]!\n topSecretFederationFacts: [TopSecretFact!]!\n factTypes: [TopSecretFactType!]\n sharedThings(numOfA: Int!, numOfB: Int!): [Thing!]!\n slicedThings(first: Int, last: Int): [Thing]\n \"\"\"Returns the value of the received HTTP header.\"\"\"\n headerValue(name: String!): String!\n \"\"\"Returns the value of the given key in the WS initial payload.\"\"\"\n initPayloadValue(key: String!): String!\n initialPayload: Map\n \"\"\"Returns response after the given delay\"\"\"\n delay(response: String!, ms: Int!): String!\n bigResponse(artificialDelay: Int! = 0, bigObjects: Int! = 100, nestedObjects: Int! = 100, deeplyNestedObjects: Int! = 100): [BigObject!]!\n longResponse(artificialDelay: Int! = 0, bytes: Int!): String\n bigAbstractResponse: BigAbstractResponse\n rootFieldWithListArg(arg: [String!]!): [String!]!\n rootFieldWithNestedListArg(arg: [[String!]!]!): [[String!]!]!\n rootFieldWithListOfInputArg(arg: [InputType!]!): [InputResponse!]!\n rootFieldWithListOfEnumArg(arg: [EnumType!]!): [EnumType!]!\n rootFieldWithInput(arg: InputArg!): String!\n floatField(arg: Float): Float\n secret: Secret\n}\n\nscalar Upload\n\ntype Mutation {\n updateEmployeeTag(id: Int!, tag: String!): Employee\n singleUpload(file: Upload!): Boolean!\n singleUploadWithInput(arg: FileUpload!): Boolean!\n multipleUpload(files: [Upload!]!): Boolean!\n addFact(fact: TopSecretFactInput!): TopSecretFact!\n \"\"\" This mutation updates the availability status of an employee in the system.\n \"\"\"\n updateAvailability(employeeID: Int!, isAvailable: Boolean!): Employee!\n \"\"\" This mutation update the mood of an employee. \"\"\"\n updateMood(employeeID: Int!, mood: Mood!): Employee!\n}\n\ninput FileUpload {\n nested: DeeplyNestedFileUpload\n nestedList: [Upload!]\n}\n\ninput DeeplyNestedFileUpload {\n file: Upload!\n}\n\ntype Subscription {\n \"\"\"`currentTime` will return a stream of `Time` objects.\"\"\"\n currentTime: Time!\n countEmp(max: Int!, intervalMilliseconds: Int!): Int!\n countEmp2(max: Int!, intervalMilliseconds: Int!): Int!\n countFor(count: Int!): Int!\n countHob(max: Int!, intervalMilliseconds: Int!): Int!\n \"\"\"Returns a stream with the value of the received HTTP header.\"\"\"\n headerValue(name: String!, repeat: Int): TimestampedString!\n \"\"\"\n Returns a stream with the value of value of the given key in the WS initial payload.\n \"\"\"\n initPayloadValue(key: String!, repeat: Int): TimestampedString!\n \"\"\"Returns a stream with the value of the WS initial payload.\"\"\"\n initialPayload(repeat: Int): Map\n returnsError: String\n}\n\nenum Department {\n ENGINEERING\n MARKETING\n OPERATIONS\n}\n\ninterface RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n}\n\nenum EngineerType {\n BACKEND\n FRONTEND\n FULLSTACK\n}\n\ninterface Identifiable {\n id: Int!\n}\n\nenum OperationType {\n FINANCE\n HUMAN_RESOURCES\n}\n\ntype Details {\n forename: String!\n location: Country!\n surname: String!\n pastLocations: [City!]!\n middlename: String @deprecated(reason: \"No longer supported\")\n hasChildren: Boolean!\n maritalStatus: MaritalStatus\n nationality: Nationality!\n pets: [Pet]\n}\n\ntype City {\n type: String!\n name: String!\n country: Country\n}\n\ntype Country {\n key: CountryKey!\n language: String\n}\n\ntype CountryKey {\n name: String!\n}\n\nenum Mood {\n HAPPY\n SAD\n}\n\ntype ErrorWrapper {\n okField: String\n errorField: String\n}\n\ntype Time {\n unixTime: Int!\n timeStamp: String!\n}\n\nunion Products = Consultancy | Cosmo | SDK | Documentation\n\ninterface IProduct {\n upc: ID!\n engineers: [Employee!]!\n}\n\ntype Consultancy {\n upc: ID!\n lead: Employee!\n isLeadAvailable: Boolean\n name: ProductName!\n}\n\ninterface EmployeeWorkItem {\n name: String!\n priority: Int!\n}\n\ntype WorkItemHandler {\n name: String!\n assignedItem: EmployeeWorkItem!\n}\n\ntype TechnicalSpecs {\n name: String!\n complexity: Float!\n metrics: WorkMetrics!\n}\n\ntype ManagementSpecs {\n name: String!\n scope: Float!\n metrics: WorkMetrics!\n}\n\ntype WorkMetrics {\n score: Float!\n efficiency: Float!\n}\n\nunion WorkReviewResult = WorkApproval | WorkRejection\n\ntype WorkApproval {\n comment: String!\n approvedAt: String!\n}\n\ntype WorkRejection {\n reason: String!\n rejectionCode: String!\n}\n\ntype WorkSetup {\n priority: String!\n primaryItem: EmployeeWorkItem!\n}\n\ninput FindEmployeeCriteria @oneOf {\n id: Int\n department: Department\n title: String\n}\n\nenum Class {\n FISH\n MAMMAL\n REPTILE\n}\n\nenum Gender {\n FEMALE\n MALE\n UNKNOWN\n}\n\ninterface Animal {\n class: Class!\n gender: Gender!\n}\n\nenum CatType {\n HOME\n STREET\n}\n\nenum DogBreed {\n GOLDEN_RETRIEVER\n POODLE\n ROTTWEILER\n YORKSHIRE_TERRIER\n}\n\nenum MaritalStatus {\n ENGAGED\n MARRIED\n}\n\nenum Nationality {\n AMERICAN\n DUTCH\n ENGLISH\n GERMAN\n INDIAN\n SPANISH\n UKRAINIAN\n}\n\n\"\"\" Allows to filter employees by their details. \"\"\"\ninput SearchInput {\n hasPets: Boolean\n nationality: Nationality\n nested: NestedSearchInput\n}\n\ninput NestedSearchInput {\n maritalStatus: MaritalStatus\n hasChildren: Boolean\n}\n\nenum ExerciseType {\n CALISTHENICS\n HIKING\n SPORT\n STRENGTH_TRAINING\n}\n\ninterface Experience {\n yearsOfExperience: Float!\n}\n\nenum GameGenre {\n ADVENTURE\n BOARD\n FPS\n CARD\n RPG\n ROGUELITE\n SIMULATION\n STRATEGY\n}\n\nenum ProgrammingLanguage {\n CSHARP\n GO\n RUST\n TYPESCRIPT\n}\n\ninterface Hobby {\n employees: [Employee!]!\n}\n\ntype Thing {\n a: String!\n b: String!\n}\n\ninput TopSecretFactInput {\n title: String!\n description: FactContent!\n factType: TopSecretFactType!\n}\n\nenum TopSecretFactType {\n DIRECTIVE\n ENTITY\n MISCELLANEOUS\n}\n\ninterface TopSecretFact {\n description: FactContent!\n factType: TopSecretFactType\n}\n\nscalar FactContent\n\nenum ProductName {\n CONSULTANCY\n COSMO\n ENGINE\n FINANCE\n HUMAN_RESOURCES\n MARKETING\n SDK\n}\n\ntype Documentation {\n url(product: ProductName!): String!\n urls(products: [ProductName!]!): [String!]!\n}\n\ntype Secret {\n value: String\n}\n\ninput InputArg {\n enums: [EnumType!]\n enum: EnumType\n string: String\n strings: [String!]\n}\n\nenum EnumType {\n A\n B\n C\n}\n\ninput InputType {\n arg: String!\n}\n\ntype InputResponse {\n arg: String!\n}\n\nscalar Map\n\ntype TimestampedString {\n \"\"\"The value of the string.\"\"\"\n value: String!\n \"\"\"The timestamp when the response was generated.\"\"\"\n unixTime: Int!\n \"\"\"Sequence number\"\"\"\n seq: Int!\n \"\"\"Total number of responses to be sent\"\"\"\n total: Int!\n initialPayload: Map\n}\n\ntype BigObject {\n nestedObjects: [NestedObject!]!\n}\n\ntype NestedObject {\n deeplyNestedObjects: [DeeplyNestedObject!]!\n}\n\ntype DeeplyNestedObject {\n aFieldOnDeeplyNestedObject: String!\n bFieldOnDeeplyNestedObject: Int!\n cFieldOnDeeplyNestedObject: Boolean!\n dFieldOnDeeplyNestedObject: Float!\n eFieldOnDeeplyNestedObject: String!\n fFieldOnDeeplyNestedObject: Int!\n gFieldOnDeeplyNestedObject: Boolean!\n hFieldOnDeeplyNestedObject: Float!\n iFieldOnDeeplyNestedObject: String!\n jFieldOnDeeplyNestedObject: Int!\n kFieldOnDeeplyNestedObject: Boolean!\n lFieldOnDeeplyNestedObject: Float!\n mFieldOnDeeplyNestedObject: String!\n nFieldOnDeeplyNestedObject: Int!\n oFieldOnDeeplyNestedObject: Boolean!\n pFieldOnDeeplyNestedObject: Float!\n qFieldOnDeeplyNestedObject: String!\n rFieldOnDeeplyNestedObject: Int!\n sFieldOnDeeplyNestedObject: Boolean!\n tFieldOnDeeplyNestedObject: Float!\n uFieldOnDeeplyNestedObject: String!\n vFieldOnDeeplyNestedObject: Int!\n wFieldOnDeeplyNestedObject: Boolean!\n xFieldOnDeeplyNestedObject: Float!\n yFieldOnDeeplyNestedObject: String!\n zFieldOnDeeplyNestedObject: Int!\n}\n\nunion BigAbstractResponse = ABigObject | BBigObject | CBigObject | DBigObject | EBigObject | FBigObject | GBigObject | HBigObject | IBigObject | JBigObject | KBigObject | LBigObject | MBigObject | NBigObject | OBigObject | PBigObject | QBigObject | RBigObject | SBigObject | TBigObject | UBigObject | VBigObject | WBigObject | XBigObject | YBigObject | ZBigObject\n\ntype ABigObject {\n aFieldOnABigObject: String!\n bFieldOnABigObject: Int!\n cFieldOnABigObject: Boolean!\n dFieldOnABigObject: Float!\n eFieldOnABigObject: String!\n fFieldOnABigObject: Int!\n gFieldOnABigObject: Boolean!\n hFieldOnABigObject: Float!\n iFieldOnABigObject: String!\n jFieldOnABigObject: Int!\n kFieldOnABigObject: Boolean!\n lFieldOnABigObject: Float!\n mFieldOnABigObject: String!\n nFieldOnABigObject: Int!\n oFieldOnABigObject: Boolean!\n pFieldOnABigObject: Float!\n qFieldOnABigObject: String!\n rFieldOnABigObject: Int!\n sFieldOnABigObject: Boolean!\n tFieldOnABigObject: Float!\n uFieldOnABigObject: String!\n vFieldOnABigObject: Int!\n wFieldOnABigObject: Boolean!\n xFieldOnABigObject: Float!\n yFieldOnABigObject: String!\n zFieldOnABigObject: Int!\n}\n\ntype BBigObject {\n aFieldOnBBigObject: String!\n bFieldOnBBigObject: Int!\n cFieldOnBBigObject: Boolean!\n dFieldOnBBigObject: Float!\n eFieldOnBBigObject: String!\n fFieldOnBBigObject: Int!\n gFieldOnBBigObject: Boolean!\n hFieldOnBBigObject: Float!\n iFieldOnBBigObject: String!\n jFieldOnBBigObject: Int!\n kFieldOnBBigObject: Boolean!\n lFieldOnBBigObject: Float!\n mFieldOnBBigObject: String!\n nFieldOnBBigObject: Int!\n oFieldOnBBigObject: Boolean!\n pFieldOnBBigObject: Float!\n qFieldOnBBigObject: String!\n rFieldOnBBigObject: Int!\n sFieldOnBBigObject: Boolean!\n tFieldOnBBigObject: Float!\n uFieldOnBBigObject: String!\n vFieldOnBBigObject: Int!\n wFieldOnBBigObject: Boolean!\n xFieldOnBBigObject: Float!\n yFieldOnBBigObject: String!\n zFieldOnBBigObject: Int!\n}\n\ntype CBigObject {\n aFieldOnCBigObject: String!\n bFieldOnCBigObject: Int!\n cFieldOnCBigObject: Boolean!\n dFieldOnCBigObject: Float!\n eFieldOnCBigObject: String!\n fFieldOnCBigObject: Int!\n gFieldOnCBigObject: Boolean!\n hFieldOnCBigObject: Float!\n iFieldOnCBigObject: String!\n jFieldOnCBigObject: Int!\n kFieldOnCBigObject: Boolean!\n lFieldOnCBigObject: Float!\n mFieldOnCBigObject: String!\n nFieldOnCBigObject: Int!\n oFieldOnCBigObject: Boolean!\n pFieldOnCBigObject: Float!\n qFieldOnCBigObject: String!\n rFieldOnCBigObject: Int!\n sFieldOnCBigObject: Boolean!\n tFieldOnCBigObject: Float!\n uFieldOnCBigObject: String!\n vFieldOnCBigObject: Int!\n wFieldOnCBigObject: Boolean!\n xFieldOnCBigObject: Float!\n yFieldOnCBigObject: String!\n zFieldOnCBigObject: Int!\n}\n\ntype DBigObject {\n aFieldOnDBigObject: String!\n bFieldOnDBigObject: Int!\n cFieldOnDBigObject: Boolean!\n dFieldOnDBigObject: Float!\n eFieldOnDBigObject: String!\n fFieldOnDBigObject: Int!\n gFieldOnDBigObject: Boolean!\n hFieldOnDBigObject: Float!\n iFieldOnDBigObject: String!\n jFieldOnDBigObject: Int!\n kFieldOnDBigObject: Boolean!\n lFieldOnDBigObject: Float!\n mFieldOnDBigObject: String!\n nFieldOnDBigObject: Int!\n oFieldOnDBigObject: Boolean!\n pFieldOnDBigObject: Float!\n qFieldOnDBigObject: String!\n rFieldOnDBigObject: Int!\n sFieldOnDBigObject: Boolean!\n tFieldOnDBigObject: Float!\n uFieldOnDBigObject: String!\n vFieldOnDBigObject: Int!\n wFieldOnDBigObject: Boolean!\n xFieldOnDBigObject: Float!\n yFieldOnDBigObject: String!\n zFieldOnDBigObject: Int!\n}\n\ntype EBigObject {\n aFieldOnEBigObject: String!\n bFieldOnEBigObject: Int!\n cFieldOnEBigObject: Boolean!\n dFieldOnEBigObject: Float!\n eFieldOnEBigObject: String!\n fFieldOnEBigObject: Int!\n gFieldOnEBigObject: Boolean!\n hFieldOnEBigObject: Float!\n iFieldOnEBigObject: String!\n jFieldOnEBigObject: Int!\n kFieldOnEBigObject: Boolean!\n lFieldOnEBigObject: Float!\n mFieldOnEBigObject: String!\n nFieldOnEBigObject: Int!\n oFieldOnEBigObject: Boolean!\n pFieldOnEBigObject: Float!\n qFieldOnEBigObject: String!\n rFieldOnEBigObject: Int!\n sFieldOnEBigObject: Boolean!\n tFieldOnEBigObject: Float!\n uFieldOnEBigObject: String!\n vFieldOnEBigObject: Int!\n wFieldOnEBigObject: Boolean!\n xFieldOnEBigObject: Float!\n yFieldOnEBigObject: String!\n zFieldOnEBigObject: Int!\n}\n\ntype FBigObject {\n aFieldOnFBigObject: String!\n bFieldOnFBigObject: Int!\n cFieldOnFBigObject: Boolean!\n dFieldOnFBigObject: Float!\n eFieldOnFBigObject: String!\n fFieldOnFBigObject: Int!\n gFieldOnFBigObject: Boolean!\n hFieldOnFBigObject: Float!\n iFieldOnFBigObject: String!\n jFieldOnFBigObject: Int!\n kFieldOnFBigObject: Boolean!\n lFieldOnFBigObject: Float!\n mFieldOnFBigObject: String!\n nFieldOnFBigObject: Int!\n oFieldOnFBigObject: Boolean!\n pFieldOnFBigObject: Float!\n qFieldOnFBigObject: String!\n rFieldOnFBigObject: Int!\n sFieldOnFBigObject: Boolean!\n tFieldOnFBigObject: Float!\n uFieldOnFBigObject: String!\n vFieldOnFBigObject: Int!\n wFieldOnFBigObject: Boolean!\n xFieldOnFBigObject: Float!\n yFieldOnFBigObject: String!\n zFieldOnFBigObject: Int!\n}\n\ntype GBigObject {\n aFieldOnGBigObject: String!\n bFieldOnGBigObject: Int!\n cFieldOnGBigObject: Boolean!\n dFieldOnGBigObject: Float!\n eFieldOnGBigObject: String!\n fFieldOnGBigObject: Int!\n gFieldOnGBigObject: Boolean!\n hFieldOnGBigObject: Float!\n iFieldOnGBigObject: String!\n jFieldOnGBigObject: Int!\n kFieldOnGBigObject: Boolean!\n lFieldOnGBigObject: Float!\n mFieldOnGBigObject: String!\n nFieldOnGBigObject: Int!\n oFieldOnGBigObject: Boolean!\n pFieldOnGBigObject: Float!\n qFieldOnGBigObject: String!\n rFieldOnGBigObject: Int!\n sFieldOnGBigObject: Boolean!\n tFieldOnGBigObject: Float!\n uFieldOnGBigObject: String!\n vFieldOnGBigObject: Int!\n wFieldOnGBigObject: Boolean!\n xFieldOnGBigObject: Float!\n yFieldOnGBigObject: String!\n zFieldOnGBigObject: Int!\n}\n\ntype HBigObject {\n aFieldOnHBigObject: String!\n bFieldOnHBigObject: Int!\n cFieldOnHBigObject: Boolean!\n dFieldOnHBigObject: Float!\n eFieldOnHBigObject: String!\n fFieldOnHBigObject: Int!\n gFieldOnHBigObject: Boolean!\n hFieldOnHBigObject: Float!\n iFieldOnHBigObject: String!\n jFieldOnHBigObject: Int!\n kFieldOnHBigObject: Boolean!\n lFieldOnHBigObject: Float!\n mFieldOnHBigObject: String!\n nFieldOnHBigObject: Int!\n oFieldOnHBigObject: Boolean!\n pFieldOnHBigObject: Float!\n qFieldOnHBigObject: String!\n rFieldOnHBigObject: Int!\n sFieldOnHBigObject: Boolean!\n tFieldOnHBigObject: Float!\n uFieldOnHBigObject: String!\n vFieldOnHBigObject: Int!\n wFieldOnHBigObject: Boolean!\n xFieldOnHBigObject: Float!\n yFieldOnHBigObject: String!\n zFieldOnHBigObject: Int!\n}\n\ntype IBigObject {\n aFieldOnIBigObject: String!\n bFieldOnIBigObject: Int!\n cFieldOnIBigObject: Boolean!\n dFieldOnIBigObject: Float!\n eFieldOnIBigObject: String!\n fFieldOnIBigObject: Int!\n gFieldOnIBigObject: Boolean!\n hFieldOnIBigObject: Float!\n iFieldOnIBigObject: String!\n jFieldOnIBigObject: Int!\n kFieldOnIBigObject: Boolean!\n lFieldOnIBigObject: Float!\n mFieldOnIBigObject: String!\n nFieldOnIBigObject: Int!\n oFieldOnIBigObject: Boolean!\n pFieldOnIBigObject: Float!\n qFieldOnIBigObject: String!\n rFieldOnIBigObject: Int!\n sFieldOnIBigObject: Boolean!\n tFieldOnIBigObject: Float!\n uFieldOnIBigObject: String!\n vFieldOnIBigObject: Int!\n wFieldOnIBigObject: Boolean!\n xFieldOnIBigObject: Float!\n yFieldOnIBigObject: String!\n zFieldOnIBigObject: Int!\n}\n\ntype JBigObject {\n aFieldOnJBigObject: String!\n bFieldOnJBigObject: Int!\n cFieldOnJBigObject: Boolean!\n dFieldOnJBigObject: Float!\n eFieldOnJBigObject: String!\n fFieldOnJBigObject: Int!\n gFieldOnJBigObject: Boolean!\n hFieldOnJBigObject: Float!\n iFieldOnJBigObject: String!\n jFieldOnJBigObject: Int!\n kFieldOnJBigObject: Boolean!\n lFieldOnJBigObject: Float!\n mFieldOnJBigObject: String!\n nFieldOnJBigObject: Int!\n oFieldOnJBigObject: Boolean!\n pFieldOnJBigObject: Float!\n qFieldOnJBigObject: String!\n rFieldOnJBigObject: Int!\n sFieldOnJBigObject: Boolean!\n tFieldOnJBigObject: Float!\n uFieldOnJBigObject: String!\n vFieldOnJBigObject: Int!\n wFieldOnJBigObject: Boolean!\n xFieldOnJBigObject: Float!\n yFieldOnJBigObject: String!\n zFieldOnJBigObject: Int!\n}\n\ntype KBigObject {\n aFieldOnKBigObject: String!\n bFieldOnKBigObject: Int!\n cFieldOnKBigObject: Boolean!\n dFieldOnKBigObject: Float!\n eFieldOnKBigObject: String!\n fFieldOnKBigObject: Int!\n gFieldOnKBigObject: Boolean!\n hFieldOnKBigObject: Float!\n iFieldOnKBigObject: String!\n jFieldOnKBigObject: Int!\n kFieldOnKBigObject: Boolean!\n lFieldOnKBigObject: Float!\n mFieldOnKBigObject: String!\n nFieldOnKBigObject: Int!\n oFieldOnKBigObject: Boolean!\n pFieldOnKBigObject: Float!\n qFieldOnKBigObject: String!\n rFieldOnKBigObject: Int!\n sFieldOnKBigObject: Boolean!\n tFieldOnKBigObject: Float!\n uFieldOnKBigObject: String!\n vFieldOnKBigObject: Int!\n wFieldOnKBigObject: Boolean!\n xFieldOnKBigObject: Float!\n yFieldOnKBigObject: String!\n zFieldOnKBigObject: Int!\n}\n\ntype LBigObject {\n aFieldOnLBigObject: String!\n bFieldOnLBigObject: Int!\n cFieldOnLBigObject: Boolean!\n dFieldOnLBigObject: Float!\n eFieldOnLBigObject: String!\n fFieldOnLBigObject: Int!\n gFieldOnLBigObject: Boolean!\n hFieldOnLBigObject: Float!\n iFieldOnLBigObject: String!\n jFieldOnLBigObject: Int!\n kFieldOnLBigObject: Boolean!\n lFieldOnLBigObject: Float!\n mFieldOnLBigObject: String!\n nFieldOnLBigObject: Int!\n oFieldOnLBigObject: Boolean!\n pFieldOnLBigObject: Float!\n qFieldOnLBigObject: String!\n rFieldOnLBigObject: Int!\n sFieldOnLBigObject: Boolean!\n tFieldOnLBigObject: Float!\n uFieldOnLBigObject: String!\n vFieldOnLBigObject: Int!\n wFieldOnLBigObject: Boolean!\n xFieldOnLBigObject: Float!\n yFieldOnLBigObject: String!\n zFieldOnLBigObject: Int!\n}\n\ntype MBigObject {\n aFieldOnMBigObject: String!\n bFieldOnMBigObject: Int!\n cFieldOnMBigObject: Boolean!\n dFieldOnMBigObject: Float!\n eFieldOnMBigObject: String!\n fFieldOnMBigObject: Int!\n gFieldOnMBigObject: Boolean!\n hFieldOnMBigObject: Float!\n iFieldOnMBigObject: String!\n jFieldOnMBigObject: Int!\n kFieldOnMBigObject: Boolean!\n lFieldOnMBigObject: Float!\n mFieldOnMBigObject: String!\n nFieldOnMBigObject: Int!\n oFieldOnMBigObject: Boolean!\n pFieldOnMBigObject: Float!\n qFieldOnMBigObject: String!\n rFieldOnMBigObject: Int!\n sFieldOnMBigObject: Boolean!\n tFieldOnMBigObject: Float!\n uFieldOnMBigObject: String!\n vFieldOnMBigObject: Int!\n wFieldOnMBigObject: Boolean!\n xFieldOnMBigObject: Float!\n yFieldOnMBigObject: String!\n zFieldOnMBigObject: Int!\n}\n\ntype NBigObject {\n aFieldOnNBigObject: String!\n bFieldOnNBigObject: Int!\n cFieldOnNBigObject: Boolean!\n dFieldOnNBigObject: Float!\n eFieldOnNBigObject: String!\n fFieldOnNBigObject: Int!\n gFieldOnNBigObject: Boolean!\n hFieldOnNBigObject: Float!\n iFieldOnNBigObject: String!\n jFieldOnNBigObject: Int!\n kFieldOnNBigObject: Boolean!\n lFieldOnNBigObject: Float!\n mFieldOnNBigObject: String!\n nFieldOnNBigObject: Int!\n oFieldOnNBigObject: Boolean!\n pFieldOnNBigObject: Float!\n qFieldOnNBigObject: String!\n rFieldOnNBigObject: Int!\n sFieldOnNBigObject: Boolean!\n tFieldOnNBigObject: Float!\n uFieldOnNBigObject: String!\n vFieldOnNBigObject: Int!\n wFieldOnNBigObject: Boolean!\n xFieldOnNBigObject: Float!\n yFieldOnNBigObject: String!\n zFieldOnNBigObject: Int!\n}\n\ntype OBigObject {\n aFieldOnOBigObject: String!\n bFieldOnOBigObject: Int!\n cFieldOnOBigObject: Boolean!\n dFieldOnOBigObject: Float!\n eFieldOnOBigObject: String!\n fFieldOnOBigObject: Int!\n gFieldOnOBigObject: Boolean!\n hFieldOnOBigObject: Float!\n iFieldOnOBigObject: String!\n jFieldOnOBigObject: Int!\n kFieldOnOBigObject: Boolean!\n lFieldOnOBigObject: Float!\n mFieldOnOBigObject: String!\n nFieldOnOBigObject: Int!\n oFieldOnOBigObject: Boolean!\n pFieldOnOBigObject: Float!\n qFieldOnOBigObject: String!\n rFieldOnOBigObject: Int!\n sFieldOnOBigObject: Boolean!\n tFieldOnOBigObject: Float!\n uFieldOnOBigObject: String!\n vFieldOnOBigObject: Int!\n wFieldOnOBigObject: Boolean!\n xFieldOnOBigObject: Float!\n yFieldOnOBigObject: String!\n zFieldOnOBigObject: Int!\n}\n\ntype PBigObject {\n aFieldOnPBigObject: String!\n bFieldOnPBigObject: Int!\n cFieldOnPBigObject: Boolean!\n dFieldOnPBigObject: Float!\n eFieldOnPBigObject: String!\n fFieldOnPBigObject: Int!\n gFieldOnPBigObject: Boolean!\n hFieldOnPBigObject: Float!\n iFieldOnPBigObject: String!\n jFieldOnPBigObject: Int!\n kFieldOnPBigObject: Boolean!\n lFieldOnPBigObject: Float!\n mFieldOnPBigObject: String!\n nFieldOnPBigObject: Int!\n oFieldOnPBigObject: Boolean!\n pFieldOnPBigObject: Float!\n qFieldOnPBigObject: String!\n rFieldOnPBigObject: Int!\n sFieldOnPBigObject: Boolean!\n tFieldOnPBigObject: Float!\n uFieldOnPBigObject: String!\n vFieldOnPBigObject: Int!\n wFieldOnPBigObject: Boolean!\n xFieldOnPBigObject: Float!\n yFieldOnPBigObject: String!\n zFieldOnPBigObject: Int!\n}\n\ntype QBigObject {\n aFieldOnQBigObject: String!\n bFieldOnQBigObject: Int!\n cFieldOnQBigObject: Boolean!\n dFieldOnQBigObject: Float!\n eFieldOnQBigObject: String!\n fFieldOnQBigObject: Int!\n gFieldOnQBigObject: Boolean!\n hFieldOnQBigObject: Float!\n iFieldOnQBigObject: String!\n jFieldOnQBigObject: Int!\n kFieldOnQBigObject: Boolean!\n lFieldOnQBigObject: Float!\n mFieldOnQBigObject: String!\n nFieldOnQBigObject: Int!\n oFieldOnQBigObject: Boolean!\n pFieldOnQBigObject: Float!\n qFieldOnQBigObject: String!\n rFieldOnQBigObject: Int!\n sFieldOnQBigObject: Boolean!\n tFieldOnQBigObject: Float!\n uFieldOnQBigObject: String!\n vFieldOnQBigObject: Int!\n wFieldOnQBigObject: Boolean!\n xFieldOnQBigObject: Float!\n yFieldOnQBigObject: String!\n zFieldOnQBigObject: Int!\n}\n\ntype RBigObject {\n aFieldOnRBigObject: String!\n bFieldOnRBigObject: Int!\n cFieldOnRBigObject: Boolean!\n dFieldOnRBigObject: Float!\n eFieldOnRBigObject: String!\n fFieldOnRBigObject: Int!\n gFieldOnRBigObject: Boolean!\n hFieldOnRBigObject: Float!\n iFieldOnRBigObject: String!\n jFieldOnRBigObject: Int!\n kFieldOnRBigObject: Boolean!\n lFieldOnRBigObject: Float!\n mFieldOnRBigObject: String!\n nFieldOnRBigObject: Int!\n oFieldOnRBigObject: Boolean!\n pFieldOnRBigObject: Float!\n qFieldOnRBigObject: String!\n rFieldOnRBigObject: Int!\n sFieldOnRBigObject: Boolean!\n tFieldOnRBigObject: Float!\n uFieldOnRBigObject: String!\n vFieldOnRBigObject: Int!\n wFieldOnRBigObject: Boolean!\n xFieldOnRBigObject: Float!\n yFieldOnRBigObject: String!\n zFieldOnRBigObject: Int!\n}\n\ntype SBigObject {\n aFieldOnSBigObject: String!\n bFieldOnSBigObject: Int!\n cFieldOnSBigObject: Boolean!\n dFieldOnSBigObject: Float!\n eFieldOnSBigObject: String!\n fFieldOnSBigObject: Int!\n gFieldOnSBigObject: Boolean!\n hFieldOnSBigObject: Float!\n iFieldOnSBigObject: String!\n jFieldOnSBigObject: Int!\n kFieldOnSBigObject: Boolean!\n lFieldOnSBigObject: Float!\n mFieldOnSBigObject: String!\n nFieldOnSBigObject: Int!\n oFieldOnSBigObject: Boolean!\n pFieldOnSBigObject: Float!\n qFieldOnSBigObject: String!\n rFieldOnSBigObject: Int!\n sFieldOnSBigObject: Boolean!\n tFieldOnSBigObject: Float!\n uFieldOnSBigObject: String!\n vFieldOnSBigObject: Int!\n wFieldOnSBigObject: Boolean!\n xFieldOnSBigObject: Float!\n yFieldOnSBigObject: String!\n zFieldOnSBigObject: Int!\n}\n\ntype TBigObject {\n aFieldOnTBigObject: String!\n bFieldOnTBigObject: Int!\n cFieldOnTBigObject: Boolean!\n dFieldOnTBigObject: Float!\n eFieldOnTBigObject: String!\n fFieldOnTBigObject: Int!\n gFieldOnTBigObject: Boolean!\n hFieldOnTBigObject: Float!\n iFieldOnTBigObject: String!\n jFieldOnTBigObject: Int!\n kFieldOnTBigObject: Boolean!\n lFieldOnTBigObject: Float!\n mFieldOnTBigObject: String!\n nFieldOnTBigObject: Int!\n oFieldOnTBigObject: Boolean!\n pFieldOnTBigObject: Float!\n qFieldOnTBigObject: String!\n rFieldOnTBigObject: Int!\n sFieldOnTBigObject: Boolean!\n tFieldOnTBigObject: Float!\n uFieldOnTBigObject: String!\n vFieldOnTBigObject: Int!\n wFieldOnTBigObject: Boolean!\n xFieldOnTBigObject: Float!\n yFieldOnTBigObject: String!\n zFieldOnTBigObject: Int!\n}\n\ntype UBigObject {\n aFieldOnUBigObject: String!\n bFieldOnUBigObject: Int!\n cFieldOnUBigObject: Boolean!\n dFieldOnUBigObject: Float!\n eFieldOnUBigObject: String!\n fFieldOnUBigObject: Int!\n gFieldOnUBigObject: Boolean!\n hFieldOnUBigObject: Float!\n iFieldOnUBigObject: String!\n jFieldOnUBigObject: Int!\n kFieldOnUBigObject: Boolean!\n lFieldOnUBigObject: Float!\n mFieldOnUBigObject: String!\n nFieldOnUBigObject: Int!\n oFieldOnUBigObject: Boolean!\n pFieldOnUBigObject: Float!\n qFieldOnUBigObject: String!\n rFieldOnUBigObject: Int!\n sFieldOnUBigObject: Boolean!\n tFieldOnUBigObject: Float!\n uFieldOnUBigObject: String!\n vFieldOnUBigObject: Int!\n wFieldOnUBigObject: Boolean!\n xFieldOnUBigObject: Float!\n yFieldOnUBigObject: String!\n zFieldOnUBigObject: Int!\n}\n\ntype VBigObject {\n aFieldOnVBigObject: String!\n bFieldOnVBigObject: Int!\n cFieldOnVBigObject: Boolean!\n dFieldOnVBigObject: Float!\n eFieldOnVBigObject: String!\n fFieldOnVBigObject: Int!\n gFieldOnVBigObject: Boolean!\n hFieldOnVBigObject: Float!\n iFieldOnVBigObject: String!\n jFieldOnVBigObject: Int!\n kFieldOnVBigObject: Boolean!\n lFieldOnVBigObject: Float!\n mFieldOnVBigObject: String!\n nFieldOnVBigObject: Int!\n oFieldOnVBigObject: Boolean!\n pFieldOnVBigObject: Float!\n qFieldOnVBigObject: String!\n rFieldOnVBigObject: Int!\n sFieldOnVBigObject: Boolean!\n tFieldOnVBigObject: Float!\n uFieldOnVBigObject: String!\n vFieldOnVBigObject: Int!\n wFieldOnVBigObject: Boolean!\n xFieldOnVBigObject: Float!\n yFieldOnVBigObject: String!\n zFieldOnVBigObject: Int!\n}\n\ntype WBigObject {\n aFieldOnWBigObject: String!\n bFieldOnWBigObject: Int!\n cFieldOnWBigObject: Boolean!\n dFieldOnWBigObject: Float!\n eFieldOnWBigObject: String!\n fFieldOnWBigObject: Int!\n gFieldOnWBigObject: Boolean!\n hFieldOnWBigObject: Float!\n iFieldOnWBigObject: String!\n jFieldOnWBigObject: Int!\n kFieldOnWBigObject: Boolean!\n lFieldOnWBigObject: Float!\n mFieldOnWBigObject: String!\n nFieldOnWBigObject: Int!\n oFieldOnWBigObject: Boolean!\n pFieldOnWBigObject: Float!\n qFieldOnWBigObject: String!\n rFieldOnWBigObject: Int!\n sFieldOnWBigObject: Boolean!\n tFieldOnWBigObject: Float!\n uFieldOnWBigObject: String!\n vFieldOnWBigObject: Int!\n wFieldOnWBigObject: Boolean!\n xFieldOnWBigObject: Float!\n yFieldOnWBigObject: String!\n zFieldOnWBigObject: Int!\n}\n\ntype XBigObject {\n aFieldOnXBigObject: String!\n bFieldOnXBigObject: Int!\n cFieldOnXBigObject: Boolean!\n dFieldOnXBigObject: Float!\n eFieldOnXBigObject: String!\n fFieldOnXBigObject: Int!\n gFieldOnXBigObject: Boolean!\n hFieldOnXBigObject: Float!\n iFieldOnXBigObject: String!\n jFieldOnXBigObject: Int!\n kFieldOnXBigObject: Boolean!\n lFieldOnXBigObject: Float!\n mFieldOnXBigObject: String!\n nFieldOnXBigObject: Int!\n oFieldOnXBigObject: Boolean!\n pFieldOnXBigObject: Float!\n qFieldOnXBigObject: String!\n rFieldOnXBigObject: Int!\n sFieldOnXBigObject: Boolean!\n tFieldOnXBigObject: Float!\n uFieldOnXBigObject: String!\n vFieldOnXBigObject: Int!\n wFieldOnXBigObject: Boolean!\n xFieldOnXBigObject: Float!\n yFieldOnXBigObject: String!\n zFieldOnXBigObject: Int!\n}\n\ntype YBigObject {\n aFieldOnYBigObject: String!\n bFieldOnYBigObject: Int!\n cFieldOnYBigObject: Boolean!\n dFieldOnYBigObject: Float!\n eFieldOnYBigObject: String!\n fFieldOnYBigObject: Int!\n gFieldOnYBigObject: Boolean!\n hFieldOnYBigObject: Float!\n iFieldOnYBigObject: String!\n jFieldOnYBigObject: Int!\n kFieldOnYBigObject: Boolean!\n lFieldOnYBigObject: Float!\n mFieldOnYBigObject: String!\n nFieldOnYBigObject: Int!\n oFieldOnYBigObject: Boolean!\n pFieldOnYBigObject: Float!\n qFieldOnYBigObject: String!\n rFieldOnYBigObject: Int!\n sFieldOnYBigObject: Boolean!\n tFieldOnYBigObject: Float!\n uFieldOnYBigObject: String!\n vFieldOnYBigObject: Int!\n wFieldOnYBigObject: Boolean!\n xFieldOnYBigObject: Float!\n yFieldOnYBigObject: String!\n zFieldOnYBigObject: Int!\n}\n\ntype ZBigObject {\n aFieldOnZBigObject: String!\n bFieldOnZBigObject: Int!\n cFieldOnZBigObject: Boolean!\n dFieldOnZBigObject: Float!\n eFieldOnZBigObject: String!\n fFieldOnZBigObject: Int!\n gFieldOnZBigObject: Boolean!\n hFieldOnZBigObject: Float!\n iFieldOnZBigObject: String!\n jFieldOnZBigObject: Int!\n kFieldOnZBigObject: Boolean!\n lFieldOnZBigObject: Float!\n mFieldOnZBigObject: String!\n nFieldOnZBigObject: Int!\n oFieldOnZBigObject: Boolean!\n pFieldOnZBigObject: Float!\n qFieldOnZBigObject: String!\n rFieldOnZBigObject: Int!\n sFieldOnZBigObject: Boolean!\n tFieldOnZBigObject: Float!\n uFieldOnZBigObject: String!\n vFieldOnZBigObject: Int!\n wFieldOnZBigObject: Boolean!\n xFieldOnZBigObject: Float!\n yFieldOnZBigObject: String!\n zFieldOnZBigObject: Int!\n}\n\ntype Engineer implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n engineerType: EngineerType!\n}\n\ntype Marketer implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n}\n\ntype Operator implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n operatorType: [OperationType!]!\n}\n\ntype Employee implements Identifiable {\n details: Details\n id: Int!\n tag: String!\n expertise: String!\n role: RoleType!\n notes: String\n updatedAt: String!\n startDate: String!\n currentMood: Mood!\n derivedMood: Mood!\n isAvailable: Boolean\n rootFieldThrowsError: String\n rootFieldErrorWrapper: ErrorWrapper\n primaryWorkItem: EmployeeWorkItem\n lastWorkReview: WorkReviewResult\n workSetup: WorkSetup\n hobbies: [Hobby!]\n products: [ProductName!]!\n fieldThrowsError: String\n}\n\ntype Cosmo implements IProduct {\n upc: ID!\n engineers: [Employee!]!\n lead: Employee!\n isLeadAvailable: Boolean\n name: ProductName!\n repositoryURL: String!\n}\n\ntype SDK implements IProduct {\n upc: ID!\n engineers: [Employee!]!\n owner: Employee!\n unicode: String!\n clientLanguages: [ProgrammingLanguage!]!\n}\n\ntype TechnicalWorkItem implements EmployeeWorkItem {\n name: String!\n priority: Int!\n codeCount: Int!\n handler: WorkItemHandler!\n specs: TechnicalSpecs!\n}\n\ntype ManagementWorkItem implements EmployeeWorkItem {\n name: String!\n priority: Int!\n teamSize: String!\n handler: WorkItemHandler!\n specs: ManagementSpecs!\n}\n\ninterface Pet implements Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Alligator implements Pet & Animal {\n class: Class!\n dangerous: String!\n gender: Gender!\n name: String!\n}\n\ntype Cat implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n type: CatType!\n}\n\ntype Dog implements Pet & Animal {\n breed: DogBreed!\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Mouse implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Pony implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Exercise implements Hobby {\n employees: [Employee!]!\n category: ExerciseType!\n}\n\ntype Flying implements Experience & Hobby {\n employees: [Employee!]!\n planeModels: [String!]!\n yearsOfExperience: Float!\n}\n\ntype Gaming implements Experience & Hobby {\n employees: [Employee!]!\n genres: [GameGenre!]!\n name: String!\n yearsOfExperience: Float!\n}\n\ntype Other implements Hobby {\n employees: [Employee!]!\n name: String!\n}\n\ntype Programming implements Hobby {\n employees: [Employee!]!\n languages: [ProgrammingLanguage!]!\n}\n\ntype Travelling implements Hobby {\n employees: [Employee!]!\n countriesLived: [Country!]!\n}\n\ntype DirectiveFact implements TopSecretFact {\n title: String!\n description: FactContent!\n factType: TopSecretFactType\n}\n\ntype EntityFact implements TopSecretFact {\n title: String!\n description: FactContent!\n factType: TopSecretFactType\n}\n\ntype MiscellaneousFact implements TopSecretFact {\n title: String!\n description: FactContent!\n factType: TopSecretFactType\n}"
+ "graphqlClientSchema": "schema {\n query: Query\n mutation: Mutation\n subscription: Subscription\n}\n\ntype Query {\n employee(id: Int!): Employee\n employeeAsList(id: Int!): [Employee]\n employees: [Employee]\n products: [Products!]!\n teammates(team: Department!): [Employee!]!\n firstEmployee: Employee!\n findEmployeesBy(criteria: FindEmployeeCriteria!): [Employee!]!\n \"\"\" This is a GraphQL query that retrieves a list of employees.\"\"\"\n findEmployees(criteria: SearchInput): [Employee!]!\n productTypes: [Products!]!\n topSecretFederationFacts: [TopSecretFact!]!\n factTypes: [TopSecretFactType!]\n sharedThings(numOfA: Int!, numOfB: Int!): [Thing!]!\n slicedThings(first: Int, last: Int): [Thing]\n \"\"\"Returns the value of the received HTTP header.\"\"\"\n headerValue(name: String!): String!\n \"\"\"Returns the value of the given key in the WS initial payload.\"\"\"\n initPayloadValue(key: String!): String!\n initialPayload: Map\n \"\"\"Returns response after the given delay\"\"\"\n delay(response: String!, ms: Int!): String!\n bigResponse(artificialDelay: Int! = 0, bigObjects: Int! = 100, nestedObjects: Int! = 100, deeplyNestedObjects: Int! = 100): [BigObject!]!\n longResponse(artificialDelay: Int! = 0, bytes: Int!): String\n bigAbstractResponse: BigAbstractResponse\n rootFieldWithListArg(arg: [String!]!): [String!]!\n rootFieldWithNestedListArg(arg: [[String!]!]!): [[String!]!]!\n rootFieldWithListOfInputArg(arg: [InputType!]!): [InputResponse!]!\n rootFieldWithListOfEnumArg(arg: [EnumType!]!): [EnumType!]!\n rootFieldWithInput(arg: InputArg!): String!\n floatField(arg: Float): Float\n secret: Secret\n}\n\nscalar Upload\n\ntype Mutation {\n updateEmployeeTag(id: Int!, tag: String!): Employee\n singleUpload(file: Upload!): Boolean!\n singleUploadWithInput(arg: FileUpload!): Boolean!\n multipleUpload(files: [Upload!]!): Boolean!\n addFact(fact: TopSecretFactInput!): TopSecretFact!\n \"\"\" This mutation updates the availability status of an employee in the system.\n \"\"\"\n updateAvailability(employeeID: Int!, isAvailable: Boolean!): Employee!\n \"\"\" This mutation update the mood of an employee. \"\"\"\n updateMood(employeeID: Int!, mood: Mood!): Employee!\n}\n\ninput FileUpload {\n nested: DeeplyNestedFileUpload\n nestedList: [Upload!]\n}\n\ninput DeeplyNestedFileUpload {\n file: Upload!\n}\n\ntype Subscription {\n \"\"\"`currentTime` will return a stream of `Time` objects.\"\"\"\n currentTime: Time!\n countEmp(max: Int!, intervalMilliseconds: Int!): Int!\n countEmp2(max: Int!, intervalMilliseconds: Int!): Int!\n countFor(count: Int!): Int!\n countHob(max: Int!, intervalMilliseconds: Int!): Int!\n \"\"\"Returns a stream with the value of the received HTTP header.\"\"\"\n headerValue(name: String!, repeat: Int): TimestampedString!\n \"\"\"\n Returns a stream with the value of value of the given key in the WS initial payload.\n \"\"\"\n initPayloadValue(key: String!, repeat: Int): TimestampedString!\n \"\"\"Returns a stream with the value of the WS initial payload.\"\"\"\n initialPayload(repeat: Int): Map\n returnsError: String!\n \"\"\"\n Returns a stream with the values of the WS initial payload and subscribe extensions\n \"\"\"\n metadata(repeat: Int! = 1): SubscribeMetadata!\n}\n\nenum Department {\n ENGINEERING\n MARKETING\n OPERATIONS\n}\n\ninterface RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n}\n\nenum EngineerType {\n BACKEND\n FRONTEND\n FULLSTACK\n}\n\ninterface Identifiable {\n id: Int!\n}\n\nenum OperationType {\n FINANCE\n HUMAN_RESOURCES\n}\n\ntype Details {\n forename: String!\n location: Country!\n surname: String!\n pastLocations: [City!]!\n middlename: String @deprecated(reason: \"No longer supported\")\n hasChildren: Boolean!\n maritalStatus: MaritalStatus\n nationality: Nationality!\n pets: [Pet]\n}\n\ntype City {\n type: String!\n name: String!\n country: Country\n}\n\ntype Country {\n key: CountryKey!\n language: String\n}\n\ntype CountryKey {\n name: String!\n}\n\nenum Mood {\n HAPPY\n SAD\n}\n\ntype ErrorWrapper {\n okField: String\n errorField: String\n}\n\ntype Time {\n unixTime: Int!\n timeStamp: String!\n}\n\nunion Products = Consultancy | Cosmo | SDK | Documentation\n\ninterface IProduct {\n upc: ID!\n engineers: [Employee!]!\n}\n\ntype Consultancy {\n upc: ID!\n lead: Employee!\n isLeadAvailable: Boolean\n name: ProductName!\n}\n\ninterface EmployeeWorkItem {\n name: String!\n priority: Int!\n}\n\ntype WorkItemHandler {\n name: String!\n assignedItem: EmployeeWorkItem!\n}\n\ntype TechnicalSpecs {\n name: String!\n complexity: Float!\n metrics: WorkMetrics!\n}\n\ntype ManagementSpecs {\n name: String!\n scope: Float!\n metrics: WorkMetrics!\n}\n\ntype WorkMetrics {\n score: Float!\n efficiency: Float!\n}\n\nunion WorkReviewResult = WorkApproval | WorkRejection\n\ntype WorkApproval {\n comment: String!\n approvedAt: String!\n}\n\ntype WorkRejection {\n reason: String!\n rejectionCode: String!\n}\n\ntype WorkSetup {\n priority: String!\n primaryItem: EmployeeWorkItem!\n}\n\ninput FindEmployeeCriteria @oneOf {\n id: Int\n department: Department\n title: String\n}\n\nenum Class {\n FISH\n MAMMAL\n REPTILE\n}\n\nenum Gender {\n FEMALE\n MALE\n UNKNOWN\n}\n\ninterface Animal {\n class: Class!\n gender: Gender!\n}\n\nenum CatType {\n HOME\n STREET\n}\n\nenum DogBreed {\n GOLDEN_RETRIEVER\n POODLE\n ROTTWEILER\n YORKSHIRE_TERRIER\n}\n\nenum MaritalStatus {\n ENGAGED\n MARRIED\n}\n\nenum Nationality {\n AMERICAN\n DUTCH\n ENGLISH\n GERMAN\n INDIAN\n SPANISH\n UKRAINIAN\n}\n\n\"\"\" Allows to filter employees by their details. \"\"\"\ninput SearchInput {\n hasPets: Boolean\n nationality: Nationality\n nested: NestedSearchInput\n}\n\ninput NestedSearchInput {\n maritalStatus: MaritalStatus\n hasChildren: Boolean\n}\n\nenum ExerciseType {\n CALISTHENICS\n HIKING\n SPORT\n STRENGTH_TRAINING\n}\n\ninterface Experience {\n yearsOfExperience: Float!\n}\n\nenum GameGenre {\n ADVENTURE\n BOARD\n FPS\n CARD\n RPG\n ROGUELITE\n SIMULATION\n STRATEGY\n}\n\nenum ProgrammingLanguage {\n CSHARP\n GO\n RUST\n TYPESCRIPT\n}\n\ninterface Hobby {\n employees: [Employee!]!\n}\n\ntype Thing {\n a: String!\n b: String!\n}\n\ninput TopSecretFactInput {\n title: String!\n description: FactContent!\n factType: TopSecretFactType!\n}\n\nenum TopSecretFactType {\n DIRECTIVE\n ENTITY\n MISCELLANEOUS\n}\n\ninterface TopSecretFact {\n description: FactContent!\n factType: TopSecretFactType\n}\n\nscalar FactContent\n\nenum ProductName {\n CONSULTANCY\n COSMO\n ENGINE\n FINANCE\n HUMAN_RESOURCES\n MARKETING\n SDK\n}\n\ntype Documentation {\n url(product: ProductName!): String!\n urls(products: [ProductName!]!): [String!]!\n}\n\ntype Secret {\n value: String\n}\n\ninput InputArg {\n enums: [EnumType!]\n enum: EnumType\n string: String\n strings: [String!]\n}\n\nenum EnumType {\n A\n B\n C\n}\n\ninput InputType {\n arg: String!\n}\n\ntype InputResponse {\n arg: String!\n}\n\nscalar Map\n\ntype TimestampedString {\n \"\"\"The value of the string.\"\"\"\n value: String!\n \"\"\"The timestamp when the response was generated.\"\"\"\n unixTime: Int!\n \"\"\"Sequence number\"\"\"\n seq: Int!\n \"\"\"Total number of responses to be sent\"\"\"\n total: Int!\n initialPayload: Map\n extensions: Map\n}\n\ntype SubscribeMetadata {\n initialPayload: Map\n subscribeExtensions: Map\n}\n\ntype BigObject {\n nestedObjects: [NestedObject!]!\n}\n\ntype NestedObject {\n deeplyNestedObjects: [DeeplyNestedObject!]!\n}\n\ntype DeeplyNestedObject {\n aFieldOnDeeplyNestedObject: String!\n bFieldOnDeeplyNestedObject: Int!\n cFieldOnDeeplyNestedObject: Boolean!\n dFieldOnDeeplyNestedObject: Float!\n eFieldOnDeeplyNestedObject: String!\n fFieldOnDeeplyNestedObject: Int!\n gFieldOnDeeplyNestedObject: Boolean!\n hFieldOnDeeplyNestedObject: Float!\n iFieldOnDeeplyNestedObject: String!\n jFieldOnDeeplyNestedObject: Int!\n kFieldOnDeeplyNestedObject: Boolean!\n lFieldOnDeeplyNestedObject: Float!\n mFieldOnDeeplyNestedObject: String!\n nFieldOnDeeplyNestedObject: Int!\n oFieldOnDeeplyNestedObject: Boolean!\n pFieldOnDeeplyNestedObject: Float!\n qFieldOnDeeplyNestedObject: String!\n rFieldOnDeeplyNestedObject: Int!\n sFieldOnDeeplyNestedObject: Boolean!\n tFieldOnDeeplyNestedObject: Float!\n uFieldOnDeeplyNestedObject: String!\n vFieldOnDeeplyNestedObject: Int!\n wFieldOnDeeplyNestedObject: Boolean!\n xFieldOnDeeplyNestedObject: Float!\n yFieldOnDeeplyNestedObject: String!\n zFieldOnDeeplyNestedObject: Int!\n}\n\nunion BigAbstractResponse = ABigObject | BBigObject | CBigObject | DBigObject | EBigObject | FBigObject | GBigObject | HBigObject | IBigObject | JBigObject | KBigObject | LBigObject | MBigObject | NBigObject | OBigObject | PBigObject | QBigObject | RBigObject | SBigObject | TBigObject | UBigObject | VBigObject | WBigObject | XBigObject | YBigObject | ZBigObject\n\ntype ABigObject {\n aFieldOnABigObject: String!\n bFieldOnABigObject: Int!\n cFieldOnABigObject: Boolean!\n dFieldOnABigObject: Float!\n eFieldOnABigObject: String!\n fFieldOnABigObject: Int!\n gFieldOnABigObject: Boolean!\n hFieldOnABigObject: Float!\n iFieldOnABigObject: String!\n jFieldOnABigObject: Int!\n kFieldOnABigObject: Boolean!\n lFieldOnABigObject: Float!\n mFieldOnABigObject: String!\n nFieldOnABigObject: Int!\n oFieldOnABigObject: Boolean!\n pFieldOnABigObject: Float!\n qFieldOnABigObject: String!\n rFieldOnABigObject: Int!\n sFieldOnABigObject: Boolean!\n tFieldOnABigObject: Float!\n uFieldOnABigObject: String!\n vFieldOnABigObject: Int!\n wFieldOnABigObject: Boolean!\n xFieldOnABigObject: Float!\n yFieldOnABigObject: String!\n zFieldOnABigObject: Int!\n}\n\ntype BBigObject {\n aFieldOnBBigObject: String!\n bFieldOnBBigObject: Int!\n cFieldOnBBigObject: Boolean!\n dFieldOnBBigObject: Float!\n eFieldOnBBigObject: String!\n fFieldOnBBigObject: Int!\n gFieldOnBBigObject: Boolean!\n hFieldOnBBigObject: Float!\n iFieldOnBBigObject: String!\n jFieldOnBBigObject: Int!\n kFieldOnBBigObject: Boolean!\n lFieldOnBBigObject: Float!\n mFieldOnBBigObject: String!\n nFieldOnBBigObject: Int!\n oFieldOnBBigObject: Boolean!\n pFieldOnBBigObject: Float!\n qFieldOnBBigObject: String!\n rFieldOnBBigObject: Int!\n sFieldOnBBigObject: Boolean!\n tFieldOnBBigObject: Float!\n uFieldOnBBigObject: String!\n vFieldOnBBigObject: Int!\n wFieldOnBBigObject: Boolean!\n xFieldOnBBigObject: Float!\n yFieldOnBBigObject: String!\n zFieldOnBBigObject: Int!\n}\n\ntype CBigObject {\n aFieldOnCBigObject: String!\n bFieldOnCBigObject: Int!\n cFieldOnCBigObject: Boolean!\n dFieldOnCBigObject: Float!\n eFieldOnCBigObject: String!\n fFieldOnCBigObject: Int!\n gFieldOnCBigObject: Boolean!\n hFieldOnCBigObject: Float!\n iFieldOnCBigObject: String!\n jFieldOnCBigObject: Int!\n kFieldOnCBigObject: Boolean!\n lFieldOnCBigObject: Float!\n mFieldOnCBigObject: String!\n nFieldOnCBigObject: Int!\n oFieldOnCBigObject: Boolean!\n pFieldOnCBigObject: Float!\n qFieldOnCBigObject: String!\n rFieldOnCBigObject: Int!\n sFieldOnCBigObject: Boolean!\n tFieldOnCBigObject: Float!\n uFieldOnCBigObject: String!\n vFieldOnCBigObject: Int!\n wFieldOnCBigObject: Boolean!\n xFieldOnCBigObject: Float!\n yFieldOnCBigObject: String!\n zFieldOnCBigObject: Int!\n}\n\ntype DBigObject {\n aFieldOnDBigObject: String!\n bFieldOnDBigObject: Int!\n cFieldOnDBigObject: Boolean!\n dFieldOnDBigObject: Float!\n eFieldOnDBigObject: String!\n fFieldOnDBigObject: Int!\n gFieldOnDBigObject: Boolean!\n hFieldOnDBigObject: Float!\n iFieldOnDBigObject: String!\n jFieldOnDBigObject: Int!\n kFieldOnDBigObject: Boolean!\n lFieldOnDBigObject: Float!\n mFieldOnDBigObject: String!\n nFieldOnDBigObject: Int!\n oFieldOnDBigObject: Boolean!\n pFieldOnDBigObject: Float!\n qFieldOnDBigObject: String!\n rFieldOnDBigObject: Int!\n sFieldOnDBigObject: Boolean!\n tFieldOnDBigObject: Float!\n uFieldOnDBigObject: String!\n vFieldOnDBigObject: Int!\n wFieldOnDBigObject: Boolean!\n xFieldOnDBigObject: Float!\n yFieldOnDBigObject: String!\n zFieldOnDBigObject: Int!\n}\n\ntype EBigObject {\n aFieldOnEBigObject: String!\n bFieldOnEBigObject: Int!\n cFieldOnEBigObject: Boolean!\n dFieldOnEBigObject: Float!\n eFieldOnEBigObject: String!\n fFieldOnEBigObject: Int!\n gFieldOnEBigObject: Boolean!\n hFieldOnEBigObject: Float!\n iFieldOnEBigObject: String!\n jFieldOnEBigObject: Int!\n kFieldOnEBigObject: Boolean!\n lFieldOnEBigObject: Float!\n mFieldOnEBigObject: String!\n nFieldOnEBigObject: Int!\n oFieldOnEBigObject: Boolean!\n pFieldOnEBigObject: Float!\n qFieldOnEBigObject: String!\n rFieldOnEBigObject: Int!\n sFieldOnEBigObject: Boolean!\n tFieldOnEBigObject: Float!\n uFieldOnEBigObject: String!\n vFieldOnEBigObject: Int!\n wFieldOnEBigObject: Boolean!\n xFieldOnEBigObject: Float!\n yFieldOnEBigObject: String!\n zFieldOnEBigObject: Int!\n}\n\ntype FBigObject {\n aFieldOnFBigObject: String!\n bFieldOnFBigObject: Int!\n cFieldOnFBigObject: Boolean!\n dFieldOnFBigObject: Float!\n eFieldOnFBigObject: String!\n fFieldOnFBigObject: Int!\n gFieldOnFBigObject: Boolean!\n hFieldOnFBigObject: Float!\n iFieldOnFBigObject: String!\n jFieldOnFBigObject: Int!\n kFieldOnFBigObject: Boolean!\n lFieldOnFBigObject: Float!\n mFieldOnFBigObject: String!\n nFieldOnFBigObject: Int!\n oFieldOnFBigObject: Boolean!\n pFieldOnFBigObject: Float!\n qFieldOnFBigObject: String!\n rFieldOnFBigObject: Int!\n sFieldOnFBigObject: Boolean!\n tFieldOnFBigObject: Float!\n uFieldOnFBigObject: String!\n vFieldOnFBigObject: Int!\n wFieldOnFBigObject: Boolean!\n xFieldOnFBigObject: Float!\n yFieldOnFBigObject: String!\n zFieldOnFBigObject: Int!\n}\n\ntype GBigObject {\n aFieldOnGBigObject: String!\n bFieldOnGBigObject: Int!\n cFieldOnGBigObject: Boolean!\n dFieldOnGBigObject: Float!\n eFieldOnGBigObject: String!\n fFieldOnGBigObject: Int!\n gFieldOnGBigObject: Boolean!\n hFieldOnGBigObject: Float!\n iFieldOnGBigObject: String!\n jFieldOnGBigObject: Int!\n kFieldOnGBigObject: Boolean!\n lFieldOnGBigObject: Float!\n mFieldOnGBigObject: String!\n nFieldOnGBigObject: Int!\n oFieldOnGBigObject: Boolean!\n pFieldOnGBigObject: Float!\n qFieldOnGBigObject: String!\n rFieldOnGBigObject: Int!\n sFieldOnGBigObject: Boolean!\n tFieldOnGBigObject: Float!\n uFieldOnGBigObject: String!\n vFieldOnGBigObject: Int!\n wFieldOnGBigObject: Boolean!\n xFieldOnGBigObject: Float!\n yFieldOnGBigObject: String!\n zFieldOnGBigObject: Int!\n}\n\ntype HBigObject {\n aFieldOnHBigObject: String!\n bFieldOnHBigObject: Int!\n cFieldOnHBigObject: Boolean!\n dFieldOnHBigObject: Float!\n eFieldOnHBigObject: String!\n fFieldOnHBigObject: Int!\n gFieldOnHBigObject: Boolean!\n hFieldOnHBigObject: Float!\n iFieldOnHBigObject: String!\n jFieldOnHBigObject: Int!\n kFieldOnHBigObject: Boolean!\n lFieldOnHBigObject: Float!\n mFieldOnHBigObject: String!\n nFieldOnHBigObject: Int!\n oFieldOnHBigObject: Boolean!\n pFieldOnHBigObject: Float!\n qFieldOnHBigObject: String!\n rFieldOnHBigObject: Int!\n sFieldOnHBigObject: Boolean!\n tFieldOnHBigObject: Float!\n uFieldOnHBigObject: String!\n vFieldOnHBigObject: Int!\n wFieldOnHBigObject: Boolean!\n xFieldOnHBigObject: Float!\n yFieldOnHBigObject: String!\n zFieldOnHBigObject: Int!\n}\n\ntype IBigObject {\n aFieldOnIBigObject: String!\n bFieldOnIBigObject: Int!\n cFieldOnIBigObject: Boolean!\n dFieldOnIBigObject: Float!\n eFieldOnIBigObject: String!\n fFieldOnIBigObject: Int!\n gFieldOnIBigObject: Boolean!\n hFieldOnIBigObject: Float!\n iFieldOnIBigObject: String!\n jFieldOnIBigObject: Int!\n kFieldOnIBigObject: Boolean!\n lFieldOnIBigObject: Float!\n mFieldOnIBigObject: String!\n nFieldOnIBigObject: Int!\n oFieldOnIBigObject: Boolean!\n pFieldOnIBigObject: Float!\n qFieldOnIBigObject: String!\n rFieldOnIBigObject: Int!\n sFieldOnIBigObject: Boolean!\n tFieldOnIBigObject: Float!\n uFieldOnIBigObject: String!\n vFieldOnIBigObject: Int!\n wFieldOnIBigObject: Boolean!\n xFieldOnIBigObject: Float!\n yFieldOnIBigObject: String!\n zFieldOnIBigObject: Int!\n}\n\ntype JBigObject {\n aFieldOnJBigObject: String!\n bFieldOnJBigObject: Int!\n cFieldOnJBigObject: Boolean!\n dFieldOnJBigObject: Float!\n eFieldOnJBigObject: String!\n fFieldOnJBigObject: Int!\n gFieldOnJBigObject: Boolean!\n hFieldOnJBigObject: Float!\n iFieldOnJBigObject: String!\n jFieldOnJBigObject: Int!\n kFieldOnJBigObject: Boolean!\n lFieldOnJBigObject: Float!\n mFieldOnJBigObject: String!\n nFieldOnJBigObject: Int!\n oFieldOnJBigObject: Boolean!\n pFieldOnJBigObject: Float!\n qFieldOnJBigObject: String!\n rFieldOnJBigObject: Int!\n sFieldOnJBigObject: Boolean!\n tFieldOnJBigObject: Float!\n uFieldOnJBigObject: String!\n vFieldOnJBigObject: Int!\n wFieldOnJBigObject: Boolean!\n xFieldOnJBigObject: Float!\n yFieldOnJBigObject: String!\n zFieldOnJBigObject: Int!\n}\n\ntype KBigObject {\n aFieldOnKBigObject: String!\n bFieldOnKBigObject: Int!\n cFieldOnKBigObject: Boolean!\n dFieldOnKBigObject: Float!\n eFieldOnKBigObject: String!\n fFieldOnKBigObject: Int!\n gFieldOnKBigObject: Boolean!\n hFieldOnKBigObject: Float!\n iFieldOnKBigObject: String!\n jFieldOnKBigObject: Int!\n kFieldOnKBigObject: Boolean!\n lFieldOnKBigObject: Float!\n mFieldOnKBigObject: String!\n nFieldOnKBigObject: Int!\n oFieldOnKBigObject: Boolean!\n pFieldOnKBigObject: Float!\n qFieldOnKBigObject: String!\n rFieldOnKBigObject: Int!\n sFieldOnKBigObject: Boolean!\n tFieldOnKBigObject: Float!\n uFieldOnKBigObject: String!\n vFieldOnKBigObject: Int!\n wFieldOnKBigObject: Boolean!\n xFieldOnKBigObject: Float!\n yFieldOnKBigObject: String!\n zFieldOnKBigObject: Int!\n}\n\ntype LBigObject {\n aFieldOnLBigObject: String!\n bFieldOnLBigObject: Int!\n cFieldOnLBigObject: Boolean!\n dFieldOnLBigObject: Float!\n eFieldOnLBigObject: String!\n fFieldOnLBigObject: Int!\n gFieldOnLBigObject: Boolean!\n hFieldOnLBigObject: Float!\n iFieldOnLBigObject: String!\n jFieldOnLBigObject: Int!\n kFieldOnLBigObject: Boolean!\n lFieldOnLBigObject: Float!\n mFieldOnLBigObject: String!\n nFieldOnLBigObject: Int!\n oFieldOnLBigObject: Boolean!\n pFieldOnLBigObject: Float!\n qFieldOnLBigObject: String!\n rFieldOnLBigObject: Int!\n sFieldOnLBigObject: Boolean!\n tFieldOnLBigObject: Float!\n uFieldOnLBigObject: String!\n vFieldOnLBigObject: Int!\n wFieldOnLBigObject: Boolean!\n xFieldOnLBigObject: Float!\n yFieldOnLBigObject: String!\n zFieldOnLBigObject: Int!\n}\n\ntype MBigObject {\n aFieldOnMBigObject: String!\n bFieldOnMBigObject: Int!\n cFieldOnMBigObject: Boolean!\n dFieldOnMBigObject: Float!\n eFieldOnMBigObject: String!\n fFieldOnMBigObject: Int!\n gFieldOnMBigObject: Boolean!\n hFieldOnMBigObject: Float!\n iFieldOnMBigObject: String!\n jFieldOnMBigObject: Int!\n kFieldOnMBigObject: Boolean!\n lFieldOnMBigObject: Float!\n mFieldOnMBigObject: String!\n nFieldOnMBigObject: Int!\n oFieldOnMBigObject: Boolean!\n pFieldOnMBigObject: Float!\n qFieldOnMBigObject: String!\n rFieldOnMBigObject: Int!\n sFieldOnMBigObject: Boolean!\n tFieldOnMBigObject: Float!\n uFieldOnMBigObject: String!\n vFieldOnMBigObject: Int!\n wFieldOnMBigObject: Boolean!\n xFieldOnMBigObject: Float!\n yFieldOnMBigObject: String!\n zFieldOnMBigObject: Int!\n}\n\ntype NBigObject {\n aFieldOnNBigObject: String!\n bFieldOnNBigObject: Int!\n cFieldOnNBigObject: Boolean!\n dFieldOnNBigObject: Float!\n eFieldOnNBigObject: String!\n fFieldOnNBigObject: Int!\n gFieldOnNBigObject: Boolean!\n hFieldOnNBigObject: Float!\n iFieldOnNBigObject: String!\n jFieldOnNBigObject: Int!\n kFieldOnNBigObject: Boolean!\n lFieldOnNBigObject: Float!\n mFieldOnNBigObject: String!\n nFieldOnNBigObject: Int!\n oFieldOnNBigObject: Boolean!\n pFieldOnNBigObject: Float!\n qFieldOnNBigObject: String!\n rFieldOnNBigObject: Int!\n sFieldOnNBigObject: Boolean!\n tFieldOnNBigObject: Float!\n uFieldOnNBigObject: String!\n vFieldOnNBigObject: Int!\n wFieldOnNBigObject: Boolean!\n xFieldOnNBigObject: Float!\n yFieldOnNBigObject: String!\n zFieldOnNBigObject: Int!\n}\n\ntype OBigObject {\n aFieldOnOBigObject: String!\n bFieldOnOBigObject: Int!\n cFieldOnOBigObject: Boolean!\n dFieldOnOBigObject: Float!\n eFieldOnOBigObject: String!\n fFieldOnOBigObject: Int!\n gFieldOnOBigObject: Boolean!\n hFieldOnOBigObject: Float!\n iFieldOnOBigObject: String!\n jFieldOnOBigObject: Int!\n kFieldOnOBigObject: Boolean!\n lFieldOnOBigObject: Float!\n mFieldOnOBigObject: String!\n nFieldOnOBigObject: Int!\n oFieldOnOBigObject: Boolean!\n pFieldOnOBigObject: Float!\n qFieldOnOBigObject: String!\n rFieldOnOBigObject: Int!\n sFieldOnOBigObject: Boolean!\n tFieldOnOBigObject: Float!\n uFieldOnOBigObject: String!\n vFieldOnOBigObject: Int!\n wFieldOnOBigObject: Boolean!\n xFieldOnOBigObject: Float!\n yFieldOnOBigObject: String!\n zFieldOnOBigObject: Int!\n}\n\ntype PBigObject {\n aFieldOnPBigObject: String!\n bFieldOnPBigObject: Int!\n cFieldOnPBigObject: Boolean!\n dFieldOnPBigObject: Float!\n eFieldOnPBigObject: String!\n fFieldOnPBigObject: Int!\n gFieldOnPBigObject: Boolean!\n hFieldOnPBigObject: Float!\n iFieldOnPBigObject: String!\n jFieldOnPBigObject: Int!\n kFieldOnPBigObject: Boolean!\n lFieldOnPBigObject: Float!\n mFieldOnPBigObject: String!\n nFieldOnPBigObject: Int!\n oFieldOnPBigObject: Boolean!\n pFieldOnPBigObject: Float!\n qFieldOnPBigObject: String!\n rFieldOnPBigObject: Int!\n sFieldOnPBigObject: Boolean!\n tFieldOnPBigObject: Float!\n uFieldOnPBigObject: String!\n vFieldOnPBigObject: Int!\n wFieldOnPBigObject: Boolean!\n xFieldOnPBigObject: Float!\n yFieldOnPBigObject: String!\n zFieldOnPBigObject: Int!\n}\n\ntype QBigObject {\n aFieldOnQBigObject: String!\n bFieldOnQBigObject: Int!\n cFieldOnQBigObject: Boolean!\n dFieldOnQBigObject: Float!\n eFieldOnQBigObject: String!\n fFieldOnQBigObject: Int!\n gFieldOnQBigObject: Boolean!\n hFieldOnQBigObject: Float!\n iFieldOnQBigObject: String!\n jFieldOnQBigObject: Int!\n kFieldOnQBigObject: Boolean!\n lFieldOnQBigObject: Float!\n mFieldOnQBigObject: String!\n nFieldOnQBigObject: Int!\n oFieldOnQBigObject: Boolean!\n pFieldOnQBigObject: Float!\n qFieldOnQBigObject: String!\n rFieldOnQBigObject: Int!\n sFieldOnQBigObject: Boolean!\n tFieldOnQBigObject: Float!\n uFieldOnQBigObject: String!\n vFieldOnQBigObject: Int!\n wFieldOnQBigObject: Boolean!\n xFieldOnQBigObject: Float!\n yFieldOnQBigObject: String!\n zFieldOnQBigObject: Int!\n}\n\ntype RBigObject {\n aFieldOnRBigObject: String!\n bFieldOnRBigObject: Int!\n cFieldOnRBigObject: Boolean!\n dFieldOnRBigObject: Float!\n eFieldOnRBigObject: String!\n fFieldOnRBigObject: Int!\n gFieldOnRBigObject: Boolean!\n hFieldOnRBigObject: Float!\n iFieldOnRBigObject: String!\n jFieldOnRBigObject: Int!\n kFieldOnRBigObject: Boolean!\n lFieldOnRBigObject: Float!\n mFieldOnRBigObject: String!\n nFieldOnRBigObject: Int!\n oFieldOnRBigObject: Boolean!\n pFieldOnRBigObject: Float!\n qFieldOnRBigObject: String!\n rFieldOnRBigObject: Int!\n sFieldOnRBigObject: Boolean!\n tFieldOnRBigObject: Float!\n uFieldOnRBigObject: String!\n vFieldOnRBigObject: Int!\n wFieldOnRBigObject: Boolean!\n xFieldOnRBigObject: Float!\n yFieldOnRBigObject: String!\n zFieldOnRBigObject: Int!\n}\n\ntype SBigObject {\n aFieldOnSBigObject: String!\n bFieldOnSBigObject: Int!\n cFieldOnSBigObject: Boolean!\n dFieldOnSBigObject: Float!\n eFieldOnSBigObject: String!\n fFieldOnSBigObject: Int!\n gFieldOnSBigObject: Boolean!\n hFieldOnSBigObject: Float!\n iFieldOnSBigObject: String!\n jFieldOnSBigObject: Int!\n kFieldOnSBigObject: Boolean!\n lFieldOnSBigObject: Float!\n mFieldOnSBigObject: String!\n nFieldOnSBigObject: Int!\n oFieldOnSBigObject: Boolean!\n pFieldOnSBigObject: Float!\n qFieldOnSBigObject: String!\n rFieldOnSBigObject: Int!\n sFieldOnSBigObject: Boolean!\n tFieldOnSBigObject: Float!\n uFieldOnSBigObject: String!\n vFieldOnSBigObject: Int!\n wFieldOnSBigObject: Boolean!\n xFieldOnSBigObject: Float!\n yFieldOnSBigObject: String!\n zFieldOnSBigObject: Int!\n}\n\ntype TBigObject {\n aFieldOnTBigObject: String!\n bFieldOnTBigObject: Int!\n cFieldOnTBigObject: Boolean!\n dFieldOnTBigObject: Float!\n eFieldOnTBigObject: String!\n fFieldOnTBigObject: Int!\n gFieldOnTBigObject: Boolean!\n hFieldOnTBigObject: Float!\n iFieldOnTBigObject: String!\n jFieldOnTBigObject: Int!\n kFieldOnTBigObject: Boolean!\n lFieldOnTBigObject: Float!\n mFieldOnTBigObject: String!\n nFieldOnTBigObject: Int!\n oFieldOnTBigObject: Boolean!\n pFieldOnTBigObject: Float!\n qFieldOnTBigObject: String!\n rFieldOnTBigObject: Int!\n sFieldOnTBigObject: Boolean!\n tFieldOnTBigObject: Float!\n uFieldOnTBigObject: String!\n vFieldOnTBigObject: Int!\n wFieldOnTBigObject: Boolean!\n xFieldOnTBigObject: Float!\n yFieldOnTBigObject: String!\n zFieldOnTBigObject: Int!\n}\n\ntype UBigObject {\n aFieldOnUBigObject: String!\n bFieldOnUBigObject: Int!\n cFieldOnUBigObject: Boolean!\n dFieldOnUBigObject: Float!\n eFieldOnUBigObject: String!\n fFieldOnUBigObject: Int!\n gFieldOnUBigObject: Boolean!\n hFieldOnUBigObject: Float!\n iFieldOnUBigObject: String!\n jFieldOnUBigObject: Int!\n kFieldOnUBigObject: Boolean!\n lFieldOnUBigObject: Float!\n mFieldOnUBigObject: String!\n nFieldOnUBigObject: Int!\n oFieldOnUBigObject: Boolean!\n pFieldOnUBigObject: Float!\n qFieldOnUBigObject: String!\n rFieldOnUBigObject: Int!\n sFieldOnUBigObject: Boolean!\n tFieldOnUBigObject: Float!\n uFieldOnUBigObject: String!\n vFieldOnUBigObject: Int!\n wFieldOnUBigObject: Boolean!\n xFieldOnUBigObject: Float!\n yFieldOnUBigObject: String!\n zFieldOnUBigObject: Int!\n}\n\ntype VBigObject {\n aFieldOnVBigObject: String!\n bFieldOnVBigObject: Int!\n cFieldOnVBigObject: Boolean!\n dFieldOnVBigObject: Float!\n eFieldOnVBigObject: String!\n fFieldOnVBigObject: Int!\n gFieldOnVBigObject: Boolean!\n hFieldOnVBigObject: Float!\n iFieldOnVBigObject: String!\n jFieldOnVBigObject: Int!\n kFieldOnVBigObject: Boolean!\n lFieldOnVBigObject: Float!\n mFieldOnVBigObject: String!\n nFieldOnVBigObject: Int!\n oFieldOnVBigObject: Boolean!\n pFieldOnVBigObject: Float!\n qFieldOnVBigObject: String!\n rFieldOnVBigObject: Int!\n sFieldOnVBigObject: Boolean!\n tFieldOnVBigObject: Float!\n uFieldOnVBigObject: String!\n vFieldOnVBigObject: Int!\n wFieldOnVBigObject: Boolean!\n xFieldOnVBigObject: Float!\n yFieldOnVBigObject: String!\n zFieldOnVBigObject: Int!\n}\n\ntype WBigObject {\n aFieldOnWBigObject: String!\n bFieldOnWBigObject: Int!\n cFieldOnWBigObject: Boolean!\n dFieldOnWBigObject: Float!\n eFieldOnWBigObject: String!\n fFieldOnWBigObject: Int!\n gFieldOnWBigObject: Boolean!\n hFieldOnWBigObject: Float!\n iFieldOnWBigObject: String!\n jFieldOnWBigObject: Int!\n kFieldOnWBigObject: Boolean!\n lFieldOnWBigObject: Float!\n mFieldOnWBigObject: String!\n nFieldOnWBigObject: Int!\n oFieldOnWBigObject: Boolean!\n pFieldOnWBigObject: Float!\n qFieldOnWBigObject: String!\n rFieldOnWBigObject: Int!\n sFieldOnWBigObject: Boolean!\n tFieldOnWBigObject: Float!\n uFieldOnWBigObject: String!\n vFieldOnWBigObject: Int!\n wFieldOnWBigObject: Boolean!\n xFieldOnWBigObject: Float!\n yFieldOnWBigObject: String!\n zFieldOnWBigObject: Int!\n}\n\ntype XBigObject {\n aFieldOnXBigObject: String!\n bFieldOnXBigObject: Int!\n cFieldOnXBigObject: Boolean!\n dFieldOnXBigObject: Float!\n eFieldOnXBigObject: String!\n fFieldOnXBigObject: Int!\n gFieldOnXBigObject: Boolean!\n hFieldOnXBigObject: Float!\n iFieldOnXBigObject: String!\n jFieldOnXBigObject: Int!\n kFieldOnXBigObject: Boolean!\n lFieldOnXBigObject: Float!\n mFieldOnXBigObject: String!\n nFieldOnXBigObject: Int!\n oFieldOnXBigObject: Boolean!\n pFieldOnXBigObject: Float!\n qFieldOnXBigObject: String!\n rFieldOnXBigObject: Int!\n sFieldOnXBigObject: Boolean!\n tFieldOnXBigObject: Float!\n uFieldOnXBigObject: String!\n vFieldOnXBigObject: Int!\n wFieldOnXBigObject: Boolean!\n xFieldOnXBigObject: Float!\n yFieldOnXBigObject: String!\n zFieldOnXBigObject: Int!\n}\n\ntype YBigObject {\n aFieldOnYBigObject: String!\n bFieldOnYBigObject: Int!\n cFieldOnYBigObject: Boolean!\n dFieldOnYBigObject: Float!\n eFieldOnYBigObject: String!\n fFieldOnYBigObject: Int!\n gFieldOnYBigObject: Boolean!\n hFieldOnYBigObject: Float!\n iFieldOnYBigObject: String!\n jFieldOnYBigObject: Int!\n kFieldOnYBigObject: Boolean!\n lFieldOnYBigObject: Float!\n mFieldOnYBigObject: String!\n nFieldOnYBigObject: Int!\n oFieldOnYBigObject: Boolean!\n pFieldOnYBigObject: Float!\n qFieldOnYBigObject: String!\n rFieldOnYBigObject: Int!\n sFieldOnYBigObject: Boolean!\n tFieldOnYBigObject: Float!\n uFieldOnYBigObject: String!\n vFieldOnYBigObject: Int!\n wFieldOnYBigObject: Boolean!\n xFieldOnYBigObject: Float!\n yFieldOnYBigObject: String!\n zFieldOnYBigObject: Int!\n}\n\ntype ZBigObject {\n aFieldOnZBigObject: String!\n bFieldOnZBigObject: Int!\n cFieldOnZBigObject: Boolean!\n dFieldOnZBigObject: Float!\n eFieldOnZBigObject: String!\n fFieldOnZBigObject: Int!\n gFieldOnZBigObject: Boolean!\n hFieldOnZBigObject: Float!\n iFieldOnZBigObject: String!\n jFieldOnZBigObject: Int!\n kFieldOnZBigObject: Boolean!\n lFieldOnZBigObject: Float!\n mFieldOnZBigObject: String!\n nFieldOnZBigObject: Int!\n oFieldOnZBigObject: Boolean!\n pFieldOnZBigObject: Float!\n qFieldOnZBigObject: String!\n rFieldOnZBigObject: Int!\n sFieldOnZBigObject: Boolean!\n tFieldOnZBigObject: Float!\n uFieldOnZBigObject: String!\n vFieldOnZBigObject: Int!\n wFieldOnZBigObject: Boolean!\n xFieldOnZBigObject: Float!\n yFieldOnZBigObject: String!\n zFieldOnZBigObject: Int!\n}\n\ntype Engineer implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n engineerType: EngineerType!\n}\n\ntype Marketer implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n}\n\ntype Operator implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n operatorType: [OperationType!]!\n}\n\ntype Employee implements Identifiable {\n details: Details\n id: Int!\n tag: String!\n expertise: String!\n role: RoleType!\n notes: String\n updatedAt: String!\n startDate: String!\n currentMood: Mood!\n derivedMood: Mood!\n isAvailable: Boolean\n rootFieldThrowsError: String\n rootFieldErrorWrapper: ErrorWrapper\n primaryWorkItem: EmployeeWorkItem\n lastWorkReview: WorkReviewResult\n workSetup: WorkSetup\n hobbies: [Hobby!]\n products: [ProductName!]!\n fieldThrowsError: String\n}\n\ntype Cosmo implements IProduct {\n upc: ID!\n engineers: [Employee!]!\n lead: Employee!\n isLeadAvailable: Boolean\n name: ProductName!\n repositoryURL: String!\n}\n\ntype SDK implements IProduct {\n upc: ID!\n engineers: [Employee!]!\n owner: Employee!\n unicode: String!\n clientLanguages: [ProgrammingLanguage!]!\n}\n\ntype TechnicalWorkItem implements EmployeeWorkItem {\n name: String!\n priority: Int!\n codeCount: Int!\n handler: WorkItemHandler!\n specs: TechnicalSpecs!\n}\n\ntype ManagementWorkItem implements EmployeeWorkItem {\n name: String!\n priority: Int!\n teamSize: String!\n handler: WorkItemHandler!\n specs: ManagementSpecs!\n}\n\ninterface Pet implements Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Alligator implements Pet & Animal {\n class: Class!\n dangerous: String!\n gender: Gender!\n name: String!\n}\n\ntype Cat implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n type: CatType!\n}\n\ntype Dog implements Pet & Animal {\n breed: DogBreed!\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Mouse implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Pony implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Exercise implements Hobby {\n employees: [Employee!]!\n category: ExerciseType!\n}\n\ntype Flying implements Experience & Hobby {\n employees: [Employee!]!\n planeModels: [String!]!\n yearsOfExperience: Float!\n}\n\ntype Gaming implements Experience & Hobby {\n employees: [Employee!]!\n genres: [GameGenre!]!\n name: String!\n yearsOfExperience: Float!\n}\n\ntype Other implements Hobby {\n employees: [Employee!]!\n name: String!\n}\n\ntype Programming implements Hobby {\n employees: [Employee!]!\n languages: [ProgrammingLanguage!]!\n}\n\ntype Travelling implements Hobby {\n employees: [Employee!]!\n countriesLived: [Country!]!\n}\n\ntype DirectiveFact implements TopSecretFact {\n title: String!\n description: FactContent!\n factType: TopSecretFactType\n}\n\ntype EntityFact implements TopSecretFact {\n title: String!\n description: FactContent!\n factType: TopSecretFactType\n}\n\ntype MiscellaneousFact implements TopSecretFact {\n title: String!\n description: FactContent!\n factType: TopSecretFactType\n}"
},
"version": "00000000-0000-0000-0000-000000000000",
"subgraphs": [
@@ -3497,7 +3516,8 @@
"headerValue",
"initPayloadValue",
"initialPayload",
- "returnsError"
+ "returnsError",
+ "metadata"
]
},
{
@@ -3534,7 +3554,15 @@
"unixTime",
"seq",
"total",
- "initialPayload"
+ "initialPayload",
+ "extensions"
+ ]
+ },
+ {
+ "typeName": "SubscribeMetadata",
+ "fieldNames": [
+ "initialPayload",
+ "subscribeExtensions"
]
},
{
@@ -4408,10 +4436,10 @@
},
"federation": {
"enabled": true,
- "serviceSdl": "extend schema\n@link(url: \"https://specs.apollo.dev/federation/v2.5\", import: [\"@authenticated\", \"@composeDirective\", \"@external\", \"@extends\", \"@inaccessible\", \"@interfaceObject\", \"@override\", \"@provides\", \"@key\", \"@requires\", \"@requiresScopes\", \"@shareable\", \"@tag\"])\n\ntype Query {\n \"Returns the value of the received HTTP header.\"\n headerValue(name: String!): String!\n \"Returns the value of the given key in the WS initial payload.\"\n initPayloadValue(key: String!): String!\n initialPayload: Map\n \"Returns response after the given delay\"\n delay(response: String!, ms: Int!): String!\n\n bigResponse(\n artificialDelay: Int! = 0\n bigObjects: Int! = 100\n nestedObjects: Int! = 100\n deeplyNestedObjects: Int! = 100\n ): [BigObject!]!\n\n longResponse(artificialDelay: Int! = 0, bytes: Int!): String\n\n bigAbstractResponse: BigAbstractResponse\n\n rootFieldWithListArg(arg: [String!]!): [String!]!\n rootFieldWithNestedListArg(arg: [[String!]!]!): [[String!]!]!\n rootFieldWithListOfInputArg(arg: [InputType!]!): [InputResponse!]!\n rootFieldWithListOfEnumArg(arg: [EnumType!]!): [EnumType!]!\n rootFieldWithInput(arg: InputArg!): String!\n\n floatField(arg: Float): Float\n\n sharedThings(numOfA: Int! numOfB: Int!): [Thing!]! @shareable\n\n secret: Secret @requiresScopes(scopes: [[\"read:secret\"]])\n}\n\ntype Secret {\n value: String\n}\n\ntype Thing @shareable {\n b: String!\n}\n\ninput InputArg {\n enums: [EnumType!]\n enum: EnumType\n string: String\n strings: [String!]\n}\n\nenum EnumType {\n A\n B\n C\n}\n\ninput InputType {\n arg: String!\n}\n\ntype InputResponse {\n arg: String!\n}\n\nscalar Map\n\ntype TimestampedString {\n \"The value of the string.\"\n value: String!\n \"The timestamp when the response was generated.\"\n unixTime: Int!\n \"Sequence number\"\n seq: Int!\n \"Total number of responses to be sent\"\n total: Int!\n initialPayload: Map\n}\n\ntype Subscription {\n \"Returns a stream with the value of the received HTTP header.\"\n headerValue(name: String!, repeat: Int): TimestampedString!\n \"Returns a stream with the value of value of the given key in the WS initial payload.\"\n initPayloadValue(key: String!, repeat: Int): TimestampedString!\n \"Returns a stream with the value of the WS initial payload.\"\n initialPayload(repeat: Int): Map\n returnsError: String\n}\n\ntype Employee @key(fields: \"id\") {\n id: Int!\n fieldThrowsError: String\n}\n\ntype BigObject {\n nestedObjects: [NestedObject!]!\n}\n\ntype NestedObject {\n deeplyNestedObjects: [DeeplyNestedObject!]!\n}\n\ntype DeeplyNestedObject {\n aFieldOnDeeplyNestedObject: String!\n bFieldOnDeeplyNestedObject: Int!\n cFieldOnDeeplyNestedObject: Boolean!\n dFieldOnDeeplyNestedObject: Float!\n eFieldOnDeeplyNestedObject: String!\n fFieldOnDeeplyNestedObject: Int!\n gFieldOnDeeplyNestedObject: Boolean!\n hFieldOnDeeplyNestedObject: Float!\n iFieldOnDeeplyNestedObject: String!\n jFieldOnDeeplyNestedObject: Int!\n kFieldOnDeeplyNestedObject: Boolean!\n lFieldOnDeeplyNestedObject: Float!\n mFieldOnDeeplyNestedObject: String!\n nFieldOnDeeplyNestedObject: Int!\n oFieldOnDeeplyNestedObject: Boolean!\n pFieldOnDeeplyNestedObject: Float!\n qFieldOnDeeplyNestedObject: String!\n rFieldOnDeeplyNestedObject: Int!\n sFieldOnDeeplyNestedObject: Boolean!\n tFieldOnDeeplyNestedObject: Float!\n uFieldOnDeeplyNestedObject: String!\n vFieldOnDeeplyNestedObject: Int!\n wFieldOnDeeplyNestedObject: Boolean!\n xFieldOnDeeplyNestedObject: Float!\n yFieldOnDeeplyNestedObject: String!\n zFieldOnDeeplyNestedObject: Int!\n}\n\nunion BigAbstractResponse = ABigObject | BBigObject | CBigObject | DBigObject | EBigObject | FBigObject | GBigObject | HBigObject | IBigObject | JBigObject | KBigObject | LBigObject | MBigObject | NBigObject | OBigObject | PBigObject | QBigObject | RBigObject | SBigObject | TBigObject | UBigObject | VBigObject | WBigObject | XBigObject | YBigObject | ZBigObject\n\ntype ABigObject {\n aFieldOnABigObject: String!\n bFieldOnABigObject: Int!\n cFieldOnABigObject: Boolean!\n dFieldOnABigObject: Float!\n eFieldOnABigObject: String!\n fFieldOnABigObject: Int!\n gFieldOnABigObject: Boolean!\n hFieldOnABigObject: Float!\n iFieldOnABigObject: String!\n jFieldOnABigObject: Int!\n kFieldOnABigObject: Boolean!\n lFieldOnABigObject: Float!\n mFieldOnABigObject: String!\n nFieldOnABigObject: Int!\n oFieldOnABigObject: Boolean!\n pFieldOnABigObject: Float!\n qFieldOnABigObject: String!\n rFieldOnABigObject: Int!\n sFieldOnABigObject: Boolean!\n tFieldOnABigObject: Float!\n uFieldOnABigObject: String!\n vFieldOnABigObject: Int!\n wFieldOnABigObject: Boolean!\n xFieldOnABigObject: Float!\n yFieldOnABigObject: String!\n zFieldOnABigObject: Int!\n}\n\ntype BBigObject {\n aFieldOnBBigObject: String!\n bFieldOnBBigObject: Int!\n cFieldOnBBigObject: Boolean!\n dFieldOnBBigObject: Float!\n eFieldOnBBigObject: String!\n fFieldOnBBigObject: Int!\n gFieldOnBBigObject: Boolean!\n hFieldOnBBigObject: Float!\n iFieldOnBBigObject: String!\n jFieldOnBBigObject: Int!\n kFieldOnBBigObject: Boolean!\n lFieldOnBBigObject: Float!\n mFieldOnBBigObject: String!\n nFieldOnBBigObject: Int!\n oFieldOnBBigObject: Boolean!\n pFieldOnBBigObject: Float!\n qFieldOnBBigObject: String!\n rFieldOnBBigObject: Int!\n sFieldOnBBigObject: Boolean!\n tFieldOnBBigObject: Float!\n uFieldOnBBigObject: String!\n vFieldOnBBigObject: Int!\n wFieldOnBBigObject: Boolean!\n xFieldOnBBigObject: Float!\n yFieldOnBBigObject: String!\n zFieldOnBBigObject: Int!\n}\n\ntype CBigObject {\n aFieldOnCBigObject: String!\n bFieldOnCBigObject: Int!\n cFieldOnCBigObject: Boolean!\n dFieldOnCBigObject: Float!\n eFieldOnCBigObject: String!\n fFieldOnCBigObject: Int!\n gFieldOnCBigObject: Boolean!\n hFieldOnCBigObject: Float!\n iFieldOnCBigObject: String!\n jFieldOnCBigObject: Int!\n kFieldOnCBigObject: Boolean!\n lFieldOnCBigObject: Float!\n mFieldOnCBigObject: String!\n nFieldOnCBigObject: Int!\n oFieldOnCBigObject: Boolean!\n pFieldOnCBigObject: Float!\n qFieldOnCBigObject: String!\n rFieldOnCBigObject: Int!\n sFieldOnCBigObject: Boolean!\n tFieldOnCBigObject: Float!\n uFieldOnCBigObject: String!\n vFieldOnCBigObject: Int!\n wFieldOnCBigObject: Boolean!\n xFieldOnCBigObject: Float!\n yFieldOnCBigObject: String!\n zFieldOnCBigObject: Int!\n}\n\ntype DBigObject {\n aFieldOnDBigObject: String!\n bFieldOnDBigObject: Int!\n cFieldOnDBigObject: Boolean!\n dFieldOnDBigObject: Float!\n eFieldOnDBigObject: String!\n fFieldOnDBigObject: Int!\n gFieldOnDBigObject: Boolean!\n hFieldOnDBigObject: Float!\n iFieldOnDBigObject: String!\n jFieldOnDBigObject: Int!\n kFieldOnDBigObject: Boolean!\n lFieldOnDBigObject: Float!\n mFieldOnDBigObject: String!\n nFieldOnDBigObject: Int!\n oFieldOnDBigObject: Boolean!\n pFieldOnDBigObject: Float!\n qFieldOnDBigObject: String!\n rFieldOnDBigObject: Int!\n sFieldOnDBigObject: Boolean!\n tFieldOnDBigObject: Float!\n uFieldOnDBigObject: String!\n vFieldOnDBigObject: Int!\n wFieldOnDBigObject: Boolean!\n xFieldOnDBigObject: Float!\n yFieldOnDBigObject: String!\n zFieldOnDBigObject: Int!\n}\n\ntype EBigObject {\n aFieldOnEBigObject: String!\n bFieldOnEBigObject: Int!\n cFieldOnEBigObject: Boolean!\n dFieldOnEBigObject: Float!\n eFieldOnEBigObject: String!\n fFieldOnEBigObject: Int!\n gFieldOnEBigObject: Boolean!\n hFieldOnEBigObject: Float!\n iFieldOnEBigObject: String!\n jFieldOnEBigObject: Int!\n kFieldOnEBigObject: Boolean!\n lFieldOnEBigObject: Float!\n mFieldOnEBigObject: String!\n nFieldOnEBigObject: Int!\n oFieldOnEBigObject: Boolean!\n pFieldOnEBigObject: Float!\n qFieldOnEBigObject: String!\n rFieldOnEBigObject: Int!\n sFieldOnEBigObject: Boolean!\n tFieldOnEBigObject: Float!\n uFieldOnEBigObject: String!\n vFieldOnEBigObject: Int!\n wFieldOnEBigObject: Boolean!\n xFieldOnEBigObject: Float!\n yFieldOnEBigObject: String!\n zFieldOnEBigObject: Int!\n}\n\ntype FBigObject {\n aFieldOnFBigObject: String!\n bFieldOnFBigObject: Int!\n cFieldOnFBigObject: Boolean!\n dFieldOnFBigObject: Float!\n eFieldOnFBigObject: String!\n fFieldOnFBigObject: Int!\n gFieldOnFBigObject: Boolean!\n hFieldOnFBigObject: Float!\n iFieldOnFBigObject: String!\n jFieldOnFBigObject: Int!\n kFieldOnFBigObject: Boolean!\n lFieldOnFBigObject: Float!\n mFieldOnFBigObject: String!\n nFieldOnFBigObject: Int!\n oFieldOnFBigObject: Boolean!\n pFieldOnFBigObject: Float!\n qFieldOnFBigObject: String!\n rFieldOnFBigObject: Int!\n sFieldOnFBigObject: Boolean!\n tFieldOnFBigObject: Float!\n uFieldOnFBigObject: String!\n vFieldOnFBigObject: Int!\n wFieldOnFBigObject: Boolean!\n xFieldOnFBigObject: Float!\n yFieldOnFBigObject: String!\n zFieldOnFBigObject: Int!\n}\n\ntype GBigObject {\n aFieldOnGBigObject: String!\n bFieldOnGBigObject: Int!\n cFieldOnGBigObject: Boolean!\n dFieldOnGBigObject: Float!\n eFieldOnGBigObject: String!\n fFieldOnGBigObject: Int!\n gFieldOnGBigObject: Boolean!\n hFieldOnGBigObject: Float!\n iFieldOnGBigObject: String!\n jFieldOnGBigObject: Int!\n kFieldOnGBigObject: Boolean!\n lFieldOnGBigObject: Float!\n mFieldOnGBigObject: String!\n nFieldOnGBigObject: Int!\n oFieldOnGBigObject: Boolean!\n pFieldOnGBigObject: Float!\n qFieldOnGBigObject: String!\n rFieldOnGBigObject: Int!\n sFieldOnGBigObject: Boolean!\n tFieldOnGBigObject: Float!\n uFieldOnGBigObject: String!\n vFieldOnGBigObject: Int!\n wFieldOnGBigObject: Boolean!\n xFieldOnGBigObject: Float!\n yFieldOnGBigObject: String!\n zFieldOnGBigObject: Int!\n}\n\ntype HBigObject {\n aFieldOnHBigObject: String!\n bFieldOnHBigObject: Int!\n cFieldOnHBigObject: Boolean!\n dFieldOnHBigObject: Float!\n eFieldOnHBigObject: String!\n fFieldOnHBigObject: Int!\n gFieldOnHBigObject: Boolean!\n hFieldOnHBigObject: Float!\n iFieldOnHBigObject: String!\n jFieldOnHBigObject: Int!\n kFieldOnHBigObject: Boolean!\n lFieldOnHBigObject: Float!\n mFieldOnHBigObject: String!\n nFieldOnHBigObject: Int!\n oFieldOnHBigObject: Boolean!\n pFieldOnHBigObject: Float!\n qFieldOnHBigObject: String!\n rFieldOnHBigObject: Int!\n sFieldOnHBigObject: Boolean!\n tFieldOnHBigObject: Float!\n uFieldOnHBigObject: String!\n vFieldOnHBigObject: Int!\n wFieldOnHBigObject: Boolean!\n xFieldOnHBigObject: Float!\n yFieldOnHBigObject: String!\n zFieldOnHBigObject: Int!\n}\n\ntype IBigObject {\n aFieldOnIBigObject: String!\n bFieldOnIBigObject: Int!\n cFieldOnIBigObject: Boolean!\n dFieldOnIBigObject: Float!\n eFieldOnIBigObject: String!\n fFieldOnIBigObject: Int!\n gFieldOnIBigObject: Boolean!\n hFieldOnIBigObject: Float!\n iFieldOnIBigObject: String!\n jFieldOnIBigObject: Int!\n kFieldOnIBigObject: Boolean!\n lFieldOnIBigObject: Float!\n mFieldOnIBigObject: String!\n nFieldOnIBigObject: Int!\n oFieldOnIBigObject: Boolean!\n pFieldOnIBigObject: Float!\n qFieldOnIBigObject: String!\n rFieldOnIBigObject: Int!\n sFieldOnIBigObject: Boolean!\n tFieldOnIBigObject: Float!\n uFieldOnIBigObject: String!\n vFieldOnIBigObject: Int!\n wFieldOnIBigObject: Boolean!\n xFieldOnIBigObject: Float!\n yFieldOnIBigObject: String!\n zFieldOnIBigObject: Int!\n}\n\ntype JBigObject {\n aFieldOnJBigObject: String!\n bFieldOnJBigObject: Int!\n cFieldOnJBigObject: Boolean!\n dFieldOnJBigObject: Float!\n eFieldOnJBigObject: String!\n fFieldOnJBigObject: Int!\n gFieldOnJBigObject: Boolean!\n hFieldOnJBigObject: Float!\n iFieldOnJBigObject: String!\n jFieldOnJBigObject: Int!\n kFieldOnJBigObject: Boolean!\n lFieldOnJBigObject: Float!\n mFieldOnJBigObject: String!\n nFieldOnJBigObject: Int!\n oFieldOnJBigObject: Boolean!\n pFieldOnJBigObject: Float!\n qFieldOnJBigObject: String!\n rFieldOnJBigObject: Int!\n sFieldOnJBigObject: Boolean!\n tFieldOnJBigObject: Float!\n uFieldOnJBigObject: String!\n vFieldOnJBigObject: Int!\n wFieldOnJBigObject: Boolean!\n xFieldOnJBigObject: Float!\n yFieldOnJBigObject: String!\n zFieldOnJBigObject: Int!\n}\n\ntype KBigObject {\n aFieldOnKBigObject: String!\n bFieldOnKBigObject: Int!\n cFieldOnKBigObject: Boolean!\n dFieldOnKBigObject: Float!\n eFieldOnKBigObject: String!\n fFieldOnKBigObject: Int!\n gFieldOnKBigObject: Boolean!\n hFieldOnKBigObject: Float!\n iFieldOnKBigObject: String!\n jFieldOnKBigObject: Int!\n kFieldOnKBigObject: Boolean!\n lFieldOnKBigObject: Float!\n mFieldOnKBigObject: String!\n nFieldOnKBigObject: Int!\n oFieldOnKBigObject: Boolean!\n pFieldOnKBigObject: Float!\n qFieldOnKBigObject: String!\n rFieldOnKBigObject: Int!\n sFieldOnKBigObject: Boolean!\n tFieldOnKBigObject: Float!\n uFieldOnKBigObject: String!\n vFieldOnKBigObject: Int!\n wFieldOnKBigObject: Boolean!\n xFieldOnKBigObject: Float!\n yFieldOnKBigObject: String!\n zFieldOnKBigObject: Int!\n}\n\ntype LBigObject {\n aFieldOnLBigObject: String!\n bFieldOnLBigObject: Int!\n cFieldOnLBigObject: Boolean!\n dFieldOnLBigObject: Float!\n eFieldOnLBigObject: String!\n fFieldOnLBigObject: Int!\n gFieldOnLBigObject: Boolean!\n hFieldOnLBigObject: Float!\n iFieldOnLBigObject: String!\n jFieldOnLBigObject: Int!\n kFieldOnLBigObject: Boolean!\n lFieldOnLBigObject: Float!\n mFieldOnLBigObject: String!\n nFieldOnLBigObject: Int!\n oFieldOnLBigObject: Boolean!\n pFieldOnLBigObject: Float!\n qFieldOnLBigObject: String!\n rFieldOnLBigObject: Int!\n sFieldOnLBigObject: Boolean!\n tFieldOnLBigObject: Float!\n uFieldOnLBigObject: String!\n vFieldOnLBigObject: Int!\n wFieldOnLBigObject: Boolean!\n xFieldOnLBigObject: Float!\n yFieldOnLBigObject: String!\n zFieldOnLBigObject: Int!\n}\n\ntype MBigObject {\n aFieldOnMBigObject: String!\n bFieldOnMBigObject: Int!\n cFieldOnMBigObject: Boolean!\n dFieldOnMBigObject: Float!\n eFieldOnMBigObject: String!\n fFieldOnMBigObject: Int!\n gFieldOnMBigObject: Boolean!\n hFieldOnMBigObject: Float!\n iFieldOnMBigObject: String!\n jFieldOnMBigObject: Int!\n kFieldOnMBigObject: Boolean!\n lFieldOnMBigObject: Float!\n mFieldOnMBigObject: String!\n nFieldOnMBigObject: Int!\n oFieldOnMBigObject: Boolean!\n pFieldOnMBigObject: Float!\n qFieldOnMBigObject: String!\n rFieldOnMBigObject: Int!\n sFieldOnMBigObject: Boolean!\n tFieldOnMBigObject: Float!\n uFieldOnMBigObject: String!\n vFieldOnMBigObject: Int!\n wFieldOnMBigObject: Boolean!\n xFieldOnMBigObject: Float!\n yFieldOnMBigObject: String!\n zFieldOnMBigObject: Int!\n}\n\ntype NBigObject {\n aFieldOnNBigObject: String!\n bFieldOnNBigObject: Int!\n cFieldOnNBigObject: Boolean!\n dFieldOnNBigObject: Float!\n eFieldOnNBigObject: String!\n fFieldOnNBigObject: Int!\n gFieldOnNBigObject: Boolean!\n hFieldOnNBigObject: Float!\n iFieldOnNBigObject: String!\n jFieldOnNBigObject: Int!\n kFieldOnNBigObject: Boolean!\n lFieldOnNBigObject: Float!\n mFieldOnNBigObject: String!\n nFieldOnNBigObject: Int!\n oFieldOnNBigObject: Boolean!\n pFieldOnNBigObject: Float!\n qFieldOnNBigObject: String!\n rFieldOnNBigObject: Int!\n sFieldOnNBigObject: Boolean!\n tFieldOnNBigObject: Float!\n uFieldOnNBigObject: String!\n vFieldOnNBigObject: Int!\n wFieldOnNBigObject: Boolean!\n xFieldOnNBigObject: Float!\n yFieldOnNBigObject: String!\n zFieldOnNBigObject: Int!\n}\n\ntype OBigObject {\n aFieldOnOBigObject: String!\n bFieldOnOBigObject: Int!\n cFieldOnOBigObject: Boolean!\n dFieldOnOBigObject: Float!\n eFieldOnOBigObject: String!\n fFieldOnOBigObject: Int!\n gFieldOnOBigObject: Boolean!\n hFieldOnOBigObject: Float!\n iFieldOnOBigObject: String!\n jFieldOnOBigObject: Int!\n kFieldOnOBigObject: Boolean!\n lFieldOnOBigObject: Float!\n mFieldOnOBigObject: String!\n nFieldOnOBigObject: Int!\n oFieldOnOBigObject: Boolean!\n pFieldOnOBigObject: Float!\n qFieldOnOBigObject: String!\n rFieldOnOBigObject: Int!\n sFieldOnOBigObject: Boolean!\n tFieldOnOBigObject: Float!\n uFieldOnOBigObject: String!\n vFieldOnOBigObject: Int!\n wFieldOnOBigObject: Boolean!\n xFieldOnOBigObject: Float!\n yFieldOnOBigObject: String!\n zFieldOnOBigObject: Int!\n}\n\ntype PBigObject {\n aFieldOnPBigObject: String!\n bFieldOnPBigObject: Int!\n cFieldOnPBigObject: Boolean!\n dFieldOnPBigObject: Float!\n eFieldOnPBigObject: String!\n fFieldOnPBigObject: Int!\n gFieldOnPBigObject: Boolean!\n hFieldOnPBigObject: Float!\n iFieldOnPBigObject: String!\n jFieldOnPBigObject: Int!\n kFieldOnPBigObject: Boolean!\n lFieldOnPBigObject: Float!\n mFieldOnPBigObject: String!\n nFieldOnPBigObject: Int!\n oFieldOnPBigObject: Boolean!\n pFieldOnPBigObject: Float!\n qFieldOnPBigObject: String!\n rFieldOnPBigObject: Int!\n sFieldOnPBigObject: Boolean!\n tFieldOnPBigObject: Float!\n uFieldOnPBigObject: String!\n vFieldOnPBigObject: Int!\n wFieldOnPBigObject: Boolean!\n xFieldOnPBigObject: Float!\n yFieldOnPBigObject: String!\n zFieldOnPBigObject: Int!\n}\n\ntype QBigObject {\n aFieldOnQBigObject: String!\n bFieldOnQBigObject: Int!\n cFieldOnQBigObject: Boolean!\n dFieldOnQBigObject: Float!\n eFieldOnQBigObject: String!\n fFieldOnQBigObject: Int!\n gFieldOnQBigObject: Boolean!\n hFieldOnQBigObject: Float!\n iFieldOnQBigObject: String!\n jFieldOnQBigObject: Int!\n kFieldOnQBigObject: Boolean!\n lFieldOnQBigObject: Float!\n mFieldOnQBigObject: String!\n nFieldOnQBigObject: Int!\n oFieldOnQBigObject: Boolean!\n pFieldOnQBigObject: Float!\n qFieldOnQBigObject: String!\n rFieldOnQBigObject: Int!\n sFieldOnQBigObject: Boolean!\n tFieldOnQBigObject: Float!\n uFieldOnQBigObject: String!\n vFieldOnQBigObject: Int!\n wFieldOnQBigObject: Boolean!\n xFieldOnQBigObject: Float!\n yFieldOnQBigObject: String!\n zFieldOnQBigObject: Int!\n}\n\ntype RBigObject {\n aFieldOnRBigObject: String!\n bFieldOnRBigObject: Int!\n cFieldOnRBigObject: Boolean!\n dFieldOnRBigObject: Float!\n eFieldOnRBigObject: String!\n fFieldOnRBigObject: Int!\n gFieldOnRBigObject: Boolean!\n hFieldOnRBigObject: Float!\n iFieldOnRBigObject: String!\n jFieldOnRBigObject: Int!\n kFieldOnRBigObject: Boolean!\n lFieldOnRBigObject: Float!\n mFieldOnRBigObject: String!\n nFieldOnRBigObject: Int!\n oFieldOnRBigObject: Boolean!\n pFieldOnRBigObject: Float!\n qFieldOnRBigObject: String!\n rFieldOnRBigObject: Int!\n sFieldOnRBigObject: Boolean!\n tFieldOnRBigObject: Float!\n uFieldOnRBigObject: String!\n vFieldOnRBigObject: Int!\n wFieldOnRBigObject: Boolean!\n xFieldOnRBigObject: Float!\n yFieldOnRBigObject: String!\n zFieldOnRBigObject: Int!\n}\n\ntype SBigObject {\n aFieldOnSBigObject: String!\n bFieldOnSBigObject: Int!\n cFieldOnSBigObject: Boolean!\n dFieldOnSBigObject: Float!\n eFieldOnSBigObject: String!\n fFieldOnSBigObject: Int!\n gFieldOnSBigObject: Boolean!\n hFieldOnSBigObject: Float!\n iFieldOnSBigObject: String!\n jFieldOnSBigObject: Int!\n kFieldOnSBigObject: Boolean!\n lFieldOnSBigObject: Float!\n mFieldOnSBigObject: String!\n nFieldOnSBigObject: Int!\n oFieldOnSBigObject: Boolean!\n pFieldOnSBigObject: Float!\n qFieldOnSBigObject: String!\n rFieldOnSBigObject: Int!\n sFieldOnSBigObject: Boolean!\n tFieldOnSBigObject: Float!\n uFieldOnSBigObject: String!\n vFieldOnSBigObject: Int!\n wFieldOnSBigObject: Boolean!\n xFieldOnSBigObject: Float!\n yFieldOnSBigObject: String!\n zFieldOnSBigObject: Int!\n}\n\ntype TBigObject {\n aFieldOnTBigObject: String!\n bFieldOnTBigObject: Int!\n cFieldOnTBigObject: Boolean!\n dFieldOnTBigObject: Float!\n eFieldOnTBigObject: String!\n fFieldOnTBigObject: Int!\n gFieldOnTBigObject: Boolean!\n hFieldOnTBigObject: Float!\n iFieldOnTBigObject: String!\n jFieldOnTBigObject: Int!\n kFieldOnTBigObject: Boolean!\n lFieldOnTBigObject: Float!\n mFieldOnTBigObject: String!\n nFieldOnTBigObject: Int!\n oFieldOnTBigObject: Boolean!\n pFieldOnTBigObject: Float!\n qFieldOnTBigObject: String!\n rFieldOnTBigObject: Int!\n sFieldOnTBigObject: Boolean!\n tFieldOnTBigObject: Float!\n uFieldOnTBigObject: String!\n vFieldOnTBigObject: Int!\n wFieldOnTBigObject: Boolean!\n xFieldOnTBigObject: Float!\n yFieldOnTBigObject: String!\n zFieldOnTBigObject: Int!\n}\n\ntype UBigObject {\n aFieldOnUBigObject: String!\n bFieldOnUBigObject: Int!\n cFieldOnUBigObject: Boolean!\n dFieldOnUBigObject: Float!\n eFieldOnUBigObject: String!\n fFieldOnUBigObject: Int!\n gFieldOnUBigObject: Boolean!\n hFieldOnUBigObject: Float!\n iFieldOnUBigObject: String!\n jFieldOnUBigObject: Int!\n kFieldOnUBigObject: Boolean!\n lFieldOnUBigObject: Float!\n mFieldOnUBigObject: String!\n nFieldOnUBigObject: Int!\n oFieldOnUBigObject: Boolean!\n pFieldOnUBigObject: Float!\n qFieldOnUBigObject: String!\n rFieldOnUBigObject: Int!\n sFieldOnUBigObject: Boolean!\n tFieldOnUBigObject: Float!\n uFieldOnUBigObject: String!\n vFieldOnUBigObject: Int!\n wFieldOnUBigObject: Boolean!\n xFieldOnUBigObject: Float!\n yFieldOnUBigObject: String!\n zFieldOnUBigObject: Int!\n}\n\ntype VBigObject {\n aFieldOnVBigObject: String!\n bFieldOnVBigObject: Int!\n cFieldOnVBigObject: Boolean!\n dFieldOnVBigObject: Float!\n eFieldOnVBigObject: String!\n fFieldOnVBigObject: Int!\n gFieldOnVBigObject: Boolean!\n hFieldOnVBigObject: Float!\n iFieldOnVBigObject: String!\n jFieldOnVBigObject: Int!\n kFieldOnVBigObject: Boolean!\n lFieldOnVBigObject: Float!\n mFieldOnVBigObject: String!\n nFieldOnVBigObject: Int!\n oFieldOnVBigObject: Boolean!\n pFieldOnVBigObject: Float!\n qFieldOnVBigObject: String!\n rFieldOnVBigObject: Int!\n sFieldOnVBigObject: Boolean!\n tFieldOnVBigObject: Float!\n uFieldOnVBigObject: String!\n vFieldOnVBigObject: Int!\n wFieldOnVBigObject: Boolean!\n xFieldOnVBigObject: Float!\n yFieldOnVBigObject: String!\n zFieldOnVBigObject: Int!\n}\n\ntype WBigObject {\n aFieldOnWBigObject: String!\n bFieldOnWBigObject: Int!\n cFieldOnWBigObject: Boolean!\n dFieldOnWBigObject: Float!\n eFieldOnWBigObject: String!\n fFieldOnWBigObject: Int!\n gFieldOnWBigObject: Boolean!\n hFieldOnWBigObject: Float!\n iFieldOnWBigObject: String!\n jFieldOnWBigObject: Int!\n kFieldOnWBigObject: Boolean!\n lFieldOnWBigObject: Float!\n mFieldOnWBigObject: String!\n nFieldOnWBigObject: Int!\n oFieldOnWBigObject: Boolean!\n pFieldOnWBigObject: Float!\n qFieldOnWBigObject: String!\n rFieldOnWBigObject: Int!\n sFieldOnWBigObject: Boolean!\n tFieldOnWBigObject: Float!\n uFieldOnWBigObject: String!\n vFieldOnWBigObject: Int!\n wFieldOnWBigObject: Boolean!\n xFieldOnWBigObject: Float!\n yFieldOnWBigObject: String!\n zFieldOnWBigObject: Int!\n}\n\ntype XBigObject {\n aFieldOnXBigObject: String!\n bFieldOnXBigObject: Int!\n cFieldOnXBigObject: Boolean!\n dFieldOnXBigObject: Float!\n eFieldOnXBigObject: String!\n fFieldOnXBigObject: Int!\n gFieldOnXBigObject: Boolean!\n hFieldOnXBigObject: Float!\n iFieldOnXBigObject: String!\n jFieldOnXBigObject: Int!\n kFieldOnXBigObject: Boolean!\n lFieldOnXBigObject: Float!\n mFieldOnXBigObject: String!\n nFieldOnXBigObject: Int!\n oFieldOnXBigObject: Boolean!\n pFieldOnXBigObject: Float!\n qFieldOnXBigObject: String!\n rFieldOnXBigObject: Int!\n sFieldOnXBigObject: Boolean!\n tFieldOnXBigObject: Float!\n uFieldOnXBigObject: String!\n vFieldOnXBigObject: Int!\n wFieldOnXBigObject: Boolean!\n xFieldOnXBigObject: Float!\n yFieldOnXBigObject: String!\n zFieldOnXBigObject: Int!\n}\n\ntype YBigObject {\n aFieldOnYBigObject: String!\n bFieldOnYBigObject: Int!\n cFieldOnYBigObject: Boolean!\n dFieldOnYBigObject: Float!\n eFieldOnYBigObject: String!\n fFieldOnYBigObject: Int!\n gFieldOnYBigObject: Boolean!\n hFieldOnYBigObject: Float!\n iFieldOnYBigObject: String!\n jFieldOnYBigObject: Int!\n kFieldOnYBigObject: Boolean!\n lFieldOnYBigObject: Float!\n mFieldOnYBigObject: String!\n nFieldOnYBigObject: Int!\n oFieldOnYBigObject: Boolean!\n pFieldOnYBigObject: Float!\n qFieldOnYBigObject: String!\n rFieldOnYBigObject: Int!\n sFieldOnYBigObject: Boolean!\n tFieldOnYBigObject: Float!\n uFieldOnYBigObject: String!\n vFieldOnYBigObject: Int!\n wFieldOnYBigObject: Boolean!\n xFieldOnYBigObject: Float!\n yFieldOnYBigObject: String!\n zFieldOnYBigObject: Int!\n}\n\ntype ZBigObject {\n aFieldOnZBigObject: String!\n bFieldOnZBigObject: Int!\n cFieldOnZBigObject: Boolean!\n dFieldOnZBigObject: Float!\n eFieldOnZBigObject: String!\n fFieldOnZBigObject: Int!\n gFieldOnZBigObject: Boolean!\n hFieldOnZBigObject: Float!\n iFieldOnZBigObject: String!\n jFieldOnZBigObject: Int!\n kFieldOnZBigObject: Boolean!\n lFieldOnZBigObject: Float!\n mFieldOnZBigObject: String!\n nFieldOnZBigObject: Int!\n oFieldOnZBigObject: Boolean!\n pFieldOnZBigObject: Float!\n qFieldOnZBigObject: String!\n rFieldOnZBigObject: Int!\n sFieldOnZBigObject: Boolean!\n tFieldOnZBigObject: Float!\n uFieldOnZBigObject: String!\n vFieldOnZBigObject: Int!\n wFieldOnZBigObject: Boolean!\n xFieldOnZBigObject: Float!\n yFieldOnZBigObject: String!\n zFieldOnZBigObject: Int!\n}"
+ "serviceSdl": "extend schema\n@link(url: \"https://specs.apollo.dev/federation/v2.5\", import: [\"@authenticated\", \"@composeDirective\", \"@external\", \"@extends\", \"@inaccessible\", \"@interfaceObject\", \"@override\", \"@provides\", \"@key\", \"@requires\", \"@requiresScopes\", \"@shareable\", \"@tag\"])\n\ntype Query {\n \"Returns the value of the received HTTP header.\"\n headerValue(name: String!): String!\n \"Returns the value of the given key in the WS initial payload.\"\n initPayloadValue(key: String!): String!\n initialPayload: Map\n \"Returns response after the given delay\"\n delay(response: String!, ms: Int!): String!\n\n bigResponse(\n artificialDelay: Int! = 0\n bigObjects: Int! = 100\n nestedObjects: Int! = 100\n deeplyNestedObjects: Int! = 100\n ): [BigObject!]!\n\n longResponse(artificialDelay: Int! = 0, bytes: Int!): String\n\n bigAbstractResponse: BigAbstractResponse\n\n rootFieldWithListArg(arg: [String!]!): [String!]!\n rootFieldWithNestedListArg(arg: [[String!]!]!): [[String!]!]!\n rootFieldWithListOfInputArg(arg: [InputType!]!): [InputResponse!]!\n rootFieldWithListOfEnumArg(arg: [EnumType!]!): [EnumType!]!\n rootFieldWithInput(arg: InputArg!): String!\n\n floatField(arg: Float): Float\n\n sharedThings(numOfA: Int! numOfB: Int!): [Thing!]! @shareable\n\n secret: Secret @requiresScopes(scopes: [[\"read:secret\"]])\n}\n\ntype Secret {\n value: String\n}\n\ntype Thing @shareable {\n b: String!\n}\n\ninput InputArg {\n enums: [EnumType!]\n enum: EnumType\n string: String\n strings: [String!]\n}\n\nenum EnumType {\n A\n B\n C\n}\n\ninput InputType {\n arg: String!\n}\n\ntype InputResponse {\n arg: String!\n}\n\nscalar Map\n\ntype TimestampedString {\n \"The value of the string.\"\n value: String!\n \"The timestamp when the response was generated.\"\n unixTime: Int!\n \"Sequence number\"\n seq: Int!\n \"Total number of responses to be sent\"\n total: Int!\n initialPayload: Map\n extensions: Map\n}\n\ntype SubscribeMetadata {\n initialPayload: Map\n subscribeExtensions: Map\n}\n\ntype Subscription {\n \"Returns a stream with the value of the received HTTP header.\"\n headerValue(name: String!, repeat: Int): TimestampedString!\n \"Returns a stream with the value of value of the given key in the WS initial payload.\"\n initPayloadValue(key: String!, repeat: Int): TimestampedString!\n \"Returns a stream with the value of the WS initial payload.\"\n initialPayload(repeat: Int): Map\n returnsError: String!\n \"Returns a stream with the values of the WS initial payload and subscribe extensions\"\n metadata(repeat: Int! = 1): SubscribeMetadata!\n}\n\ntype Employee @key(fields: \"id\") {\n id: Int!\n fieldThrowsError: String\n}\n\ntype BigObject {\n nestedObjects: [NestedObject!]!\n}\n\ntype NestedObject {\n deeplyNestedObjects: [DeeplyNestedObject!]!\n}\n\ntype DeeplyNestedObject {\n aFieldOnDeeplyNestedObject: String!\n bFieldOnDeeplyNestedObject: Int!\n cFieldOnDeeplyNestedObject: Boolean!\n dFieldOnDeeplyNestedObject: Float!\n eFieldOnDeeplyNestedObject: String!\n fFieldOnDeeplyNestedObject: Int!\n gFieldOnDeeplyNestedObject: Boolean!\n hFieldOnDeeplyNestedObject: Float!\n iFieldOnDeeplyNestedObject: String!\n jFieldOnDeeplyNestedObject: Int!\n kFieldOnDeeplyNestedObject: Boolean!\n lFieldOnDeeplyNestedObject: Float!\n mFieldOnDeeplyNestedObject: String!\n nFieldOnDeeplyNestedObject: Int!\n oFieldOnDeeplyNestedObject: Boolean!\n pFieldOnDeeplyNestedObject: Float!\n qFieldOnDeeplyNestedObject: String!\n rFieldOnDeeplyNestedObject: Int!\n sFieldOnDeeplyNestedObject: Boolean!\n tFieldOnDeeplyNestedObject: Float!\n uFieldOnDeeplyNestedObject: String!\n vFieldOnDeeplyNestedObject: Int!\n wFieldOnDeeplyNestedObject: Boolean!\n xFieldOnDeeplyNestedObject: Float!\n yFieldOnDeeplyNestedObject: String!\n zFieldOnDeeplyNestedObject: Int!\n}\n\nunion BigAbstractResponse = ABigObject | BBigObject | CBigObject | DBigObject | EBigObject | FBigObject | GBigObject | HBigObject | IBigObject | JBigObject | KBigObject | LBigObject | MBigObject | NBigObject | OBigObject | PBigObject | QBigObject | RBigObject | SBigObject | TBigObject | UBigObject | VBigObject | WBigObject | XBigObject | YBigObject | ZBigObject\n\ntype ABigObject {\n aFieldOnABigObject: String!\n bFieldOnABigObject: Int!\n cFieldOnABigObject: Boolean!\n dFieldOnABigObject: Float!\n eFieldOnABigObject: String!\n fFieldOnABigObject: Int!\n gFieldOnABigObject: Boolean!\n hFieldOnABigObject: Float!\n iFieldOnABigObject: String!\n jFieldOnABigObject: Int!\n kFieldOnABigObject: Boolean!\n lFieldOnABigObject: Float!\n mFieldOnABigObject: String!\n nFieldOnABigObject: Int!\n oFieldOnABigObject: Boolean!\n pFieldOnABigObject: Float!\n qFieldOnABigObject: String!\n rFieldOnABigObject: Int!\n sFieldOnABigObject: Boolean!\n tFieldOnABigObject: Float!\n uFieldOnABigObject: String!\n vFieldOnABigObject: Int!\n wFieldOnABigObject: Boolean!\n xFieldOnABigObject: Float!\n yFieldOnABigObject: String!\n zFieldOnABigObject: Int!\n}\n\ntype BBigObject {\n aFieldOnBBigObject: String!\n bFieldOnBBigObject: Int!\n cFieldOnBBigObject: Boolean!\n dFieldOnBBigObject: Float!\n eFieldOnBBigObject: String!\n fFieldOnBBigObject: Int!\n gFieldOnBBigObject: Boolean!\n hFieldOnBBigObject: Float!\n iFieldOnBBigObject: String!\n jFieldOnBBigObject: Int!\n kFieldOnBBigObject: Boolean!\n lFieldOnBBigObject: Float!\n mFieldOnBBigObject: String!\n nFieldOnBBigObject: Int!\n oFieldOnBBigObject: Boolean!\n pFieldOnBBigObject: Float!\n qFieldOnBBigObject: String!\n rFieldOnBBigObject: Int!\n sFieldOnBBigObject: Boolean!\n tFieldOnBBigObject: Float!\n uFieldOnBBigObject: String!\n vFieldOnBBigObject: Int!\n wFieldOnBBigObject: Boolean!\n xFieldOnBBigObject: Float!\n yFieldOnBBigObject: String!\n zFieldOnBBigObject: Int!\n}\n\ntype CBigObject {\n aFieldOnCBigObject: String!\n bFieldOnCBigObject: Int!\n cFieldOnCBigObject: Boolean!\n dFieldOnCBigObject: Float!\n eFieldOnCBigObject: String!\n fFieldOnCBigObject: Int!\n gFieldOnCBigObject: Boolean!\n hFieldOnCBigObject: Float!\n iFieldOnCBigObject: String!\n jFieldOnCBigObject: Int!\n kFieldOnCBigObject: Boolean!\n lFieldOnCBigObject: Float!\n mFieldOnCBigObject: String!\n nFieldOnCBigObject: Int!\n oFieldOnCBigObject: Boolean!\n pFieldOnCBigObject: Float!\n qFieldOnCBigObject: String!\n rFieldOnCBigObject: Int!\n sFieldOnCBigObject: Boolean!\n tFieldOnCBigObject: Float!\n uFieldOnCBigObject: String!\n vFieldOnCBigObject: Int!\n wFieldOnCBigObject: Boolean!\n xFieldOnCBigObject: Float!\n yFieldOnCBigObject: String!\n zFieldOnCBigObject: Int!\n}\n\ntype DBigObject {\n aFieldOnDBigObject: String!\n bFieldOnDBigObject: Int!\n cFieldOnDBigObject: Boolean!\n dFieldOnDBigObject: Float!\n eFieldOnDBigObject: String!\n fFieldOnDBigObject: Int!\n gFieldOnDBigObject: Boolean!\n hFieldOnDBigObject: Float!\n iFieldOnDBigObject: String!\n jFieldOnDBigObject: Int!\n kFieldOnDBigObject: Boolean!\n lFieldOnDBigObject: Float!\n mFieldOnDBigObject: String!\n nFieldOnDBigObject: Int!\n oFieldOnDBigObject: Boolean!\n pFieldOnDBigObject: Float!\n qFieldOnDBigObject: String!\n rFieldOnDBigObject: Int!\n sFieldOnDBigObject: Boolean!\n tFieldOnDBigObject: Float!\n uFieldOnDBigObject: String!\n vFieldOnDBigObject: Int!\n wFieldOnDBigObject: Boolean!\n xFieldOnDBigObject: Float!\n yFieldOnDBigObject: String!\n zFieldOnDBigObject: Int!\n}\n\ntype EBigObject {\n aFieldOnEBigObject: String!\n bFieldOnEBigObject: Int!\n cFieldOnEBigObject: Boolean!\n dFieldOnEBigObject: Float!\n eFieldOnEBigObject: String!\n fFieldOnEBigObject: Int!\n gFieldOnEBigObject: Boolean!\n hFieldOnEBigObject: Float!\n iFieldOnEBigObject: String!\n jFieldOnEBigObject: Int!\n kFieldOnEBigObject: Boolean!\n lFieldOnEBigObject: Float!\n mFieldOnEBigObject: String!\n nFieldOnEBigObject: Int!\n oFieldOnEBigObject: Boolean!\n pFieldOnEBigObject: Float!\n qFieldOnEBigObject: String!\n rFieldOnEBigObject: Int!\n sFieldOnEBigObject: Boolean!\n tFieldOnEBigObject: Float!\n uFieldOnEBigObject: String!\n vFieldOnEBigObject: Int!\n wFieldOnEBigObject: Boolean!\n xFieldOnEBigObject: Float!\n yFieldOnEBigObject: String!\n zFieldOnEBigObject: Int!\n}\n\ntype FBigObject {\n aFieldOnFBigObject: String!\n bFieldOnFBigObject: Int!\n cFieldOnFBigObject: Boolean!\n dFieldOnFBigObject: Float!\n eFieldOnFBigObject: String!\n fFieldOnFBigObject: Int!\n gFieldOnFBigObject: Boolean!\n hFieldOnFBigObject: Float!\n iFieldOnFBigObject: String!\n jFieldOnFBigObject: Int!\n kFieldOnFBigObject: Boolean!\n lFieldOnFBigObject: Float!\n mFieldOnFBigObject: String!\n nFieldOnFBigObject: Int!\n oFieldOnFBigObject: Boolean!\n pFieldOnFBigObject: Float!\n qFieldOnFBigObject: String!\n rFieldOnFBigObject: Int!\n sFieldOnFBigObject: Boolean!\n tFieldOnFBigObject: Float!\n uFieldOnFBigObject: String!\n vFieldOnFBigObject: Int!\n wFieldOnFBigObject: Boolean!\n xFieldOnFBigObject: Float!\n yFieldOnFBigObject: String!\n zFieldOnFBigObject: Int!\n}\n\ntype GBigObject {\n aFieldOnGBigObject: String!\n bFieldOnGBigObject: Int!\n cFieldOnGBigObject: Boolean!\n dFieldOnGBigObject: Float!\n eFieldOnGBigObject: String!\n fFieldOnGBigObject: Int!\n gFieldOnGBigObject: Boolean!\n hFieldOnGBigObject: Float!\n iFieldOnGBigObject: String!\n jFieldOnGBigObject: Int!\n kFieldOnGBigObject: Boolean!\n lFieldOnGBigObject: Float!\n mFieldOnGBigObject: String!\n nFieldOnGBigObject: Int!\n oFieldOnGBigObject: Boolean!\n pFieldOnGBigObject: Float!\n qFieldOnGBigObject: String!\n rFieldOnGBigObject: Int!\n sFieldOnGBigObject: Boolean!\n tFieldOnGBigObject: Float!\n uFieldOnGBigObject: String!\n vFieldOnGBigObject: Int!\n wFieldOnGBigObject: Boolean!\n xFieldOnGBigObject: Float!\n yFieldOnGBigObject: String!\n zFieldOnGBigObject: Int!\n}\n\ntype HBigObject {\n aFieldOnHBigObject: String!\n bFieldOnHBigObject: Int!\n cFieldOnHBigObject: Boolean!\n dFieldOnHBigObject: Float!\n eFieldOnHBigObject: String!\n fFieldOnHBigObject: Int!\n gFieldOnHBigObject: Boolean!\n hFieldOnHBigObject: Float!\n iFieldOnHBigObject: String!\n jFieldOnHBigObject: Int!\n kFieldOnHBigObject: Boolean!\n lFieldOnHBigObject: Float!\n mFieldOnHBigObject: String!\n nFieldOnHBigObject: Int!\n oFieldOnHBigObject: Boolean!\n pFieldOnHBigObject: Float!\n qFieldOnHBigObject: String!\n rFieldOnHBigObject: Int!\n sFieldOnHBigObject: Boolean!\n tFieldOnHBigObject: Float!\n uFieldOnHBigObject: String!\n vFieldOnHBigObject: Int!\n wFieldOnHBigObject: Boolean!\n xFieldOnHBigObject: Float!\n yFieldOnHBigObject: String!\n zFieldOnHBigObject: Int!\n}\n\ntype IBigObject {\n aFieldOnIBigObject: String!\n bFieldOnIBigObject: Int!\n cFieldOnIBigObject: Boolean!\n dFieldOnIBigObject: Float!\n eFieldOnIBigObject: String!\n fFieldOnIBigObject: Int!\n gFieldOnIBigObject: Boolean!\n hFieldOnIBigObject: Float!\n iFieldOnIBigObject: String!\n jFieldOnIBigObject: Int!\n kFieldOnIBigObject: Boolean!\n lFieldOnIBigObject: Float!\n mFieldOnIBigObject: String!\n nFieldOnIBigObject: Int!\n oFieldOnIBigObject: Boolean!\n pFieldOnIBigObject: Float!\n qFieldOnIBigObject: String!\n rFieldOnIBigObject: Int!\n sFieldOnIBigObject: Boolean!\n tFieldOnIBigObject: Float!\n uFieldOnIBigObject: String!\n vFieldOnIBigObject: Int!\n wFieldOnIBigObject: Boolean!\n xFieldOnIBigObject: Float!\n yFieldOnIBigObject: String!\n zFieldOnIBigObject: Int!\n}\n\ntype JBigObject {\n aFieldOnJBigObject: String!\n bFieldOnJBigObject: Int!\n cFieldOnJBigObject: Boolean!\n dFieldOnJBigObject: Float!\n eFieldOnJBigObject: String!\n fFieldOnJBigObject: Int!\n gFieldOnJBigObject: Boolean!\n hFieldOnJBigObject: Float!\n iFieldOnJBigObject: String!\n jFieldOnJBigObject: Int!\n kFieldOnJBigObject: Boolean!\n lFieldOnJBigObject: Float!\n mFieldOnJBigObject: String!\n nFieldOnJBigObject: Int!\n oFieldOnJBigObject: Boolean!\n pFieldOnJBigObject: Float!\n qFieldOnJBigObject: String!\n rFieldOnJBigObject: Int!\n sFieldOnJBigObject: Boolean!\n tFieldOnJBigObject: Float!\n uFieldOnJBigObject: String!\n vFieldOnJBigObject: Int!\n wFieldOnJBigObject: Boolean!\n xFieldOnJBigObject: Float!\n yFieldOnJBigObject: String!\n zFieldOnJBigObject: Int!\n}\n\ntype KBigObject {\n aFieldOnKBigObject: String!\n bFieldOnKBigObject: Int!\n cFieldOnKBigObject: Boolean!\n dFieldOnKBigObject: Float!\n eFieldOnKBigObject: String!\n fFieldOnKBigObject: Int!\n gFieldOnKBigObject: Boolean!\n hFieldOnKBigObject: Float!\n iFieldOnKBigObject: String!\n jFieldOnKBigObject: Int!\n kFieldOnKBigObject: Boolean!\n lFieldOnKBigObject: Float!\n mFieldOnKBigObject: String!\n nFieldOnKBigObject: Int!\n oFieldOnKBigObject: Boolean!\n pFieldOnKBigObject: Float!\n qFieldOnKBigObject: String!\n rFieldOnKBigObject: Int!\n sFieldOnKBigObject: Boolean!\n tFieldOnKBigObject: Float!\n uFieldOnKBigObject: String!\n vFieldOnKBigObject: Int!\n wFieldOnKBigObject: Boolean!\n xFieldOnKBigObject: Float!\n yFieldOnKBigObject: String!\n zFieldOnKBigObject: Int!\n}\n\ntype LBigObject {\n aFieldOnLBigObject: String!\n bFieldOnLBigObject: Int!\n cFieldOnLBigObject: Boolean!\n dFieldOnLBigObject: Float!\n eFieldOnLBigObject: String!\n fFieldOnLBigObject: Int!\n gFieldOnLBigObject: Boolean!\n hFieldOnLBigObject: Float!\n iFieldOnLBigObject: String!\n jFieldOnLBigObject: Int!\n kFieldOnLBigObject: Boolean!\n lFieldOnLBigObject: Float!\n mFieldOnLBigObject: String!\n nFieldOnLBigObject: Int!\n oFieldOnLBigObject: Boolean!\n pFieldOnLBigObject: Float!\n qFieldOnLBigObject: String!\n rFieldOnLBigObject: Int!\n sFieldOnLBigObject: Boolean!\n tFieldOnLBigObject: Float!\n uFieldOnLBigObject: String!\n vFieldOnLBigObject: Int!\n wFieldOnLBigObject: Boolean!\n xFieldOnLBigObject: Float!\n yFieldOnLBigObject: String!\n zFieldOnLBigObject: Int!\n}\n\ntype MBigObject {\n aFieldOnMBigObject: String!\n bFieldOnMBigObject: Int!\n cFieldOnMBigObject: Boolean!\n dFieldOnMBigObject: Float!\n eFieldOnMBigObject: String!\n fFieldOnMBigObject: Int!\n gFieldOnMBigObject: Boolean!\n hFieldOnMBigObject: Float!\n iFieldOnMBigObject: String!\n jFieldOnMBigObject: Int!\n kFieldOnMBigObject: Boolean!\n lFieldOnMBigObject: Float!\n mFieldOnMBigObject: String!\n nFieldOnMBigObject: Int!\n oFieldOnMBigObject: Boolean!\n pFieldOnMBigObject: Float!\n qFieldOnMBigObject: String!\n rFieldOnMBigObject: Int!\n sFieldOnMBigObject: Boolean!\n tFieldOnMBigObject: Float!\n uFieldOnMBigObject: String!\n vFieldOnMBigObject: Int!\n wFieldOnMBigObject: Boolean!\n xFieldOnMBigObject: Float!\n yFieldOnMBigObject: String!\n zFieldOnMBigObject: Int!\n}\n\ntype NBigObject {\n aFieldOnNBigObject: String!\n bFieldOnNBigObject: Int!\n cFieldOnNBigObject: Boolean!\n dFieldOnNBigObject: Float!\n eFieldOnNBigObject: String!\n fFieldOnNBigObject: Int!\n gFieldOnNBigObject: Boolean!\n hFieldOnNBigObject: Float!\n iFieldOnNBigObject: String!\n jFieldOnNBigObject: Int!\n kFieldOnNBigObject: Boolean!\n lFieldOnNBigObject: Float!\n mFieldOnNBigObject: String!\n nFieldOnNBigObject: Int!\n oFieldOnNBigObject: Boolean!\n pFieldOnNBigObject: Float!\n qFieldOnNBigObject: String!\n rFieldOnNBigObject: Int!\n sFieldOnNBigObject: Boolean!\n tFieldOnNBigObject: Float!\n uFieldOnNBigObject: String!\n vFieldOnNBigObject: Int!\n wFieldOnNBigObject: Boolean!\n xFieldOnNBigObject: Float!\n yFieldOnNBigObject: String!\n zFieldOnNBigObject: Int!\n}\n\ntype OBigObject {\n aFieldOnOBigObject: String!\n bFieldOnOBigObject: Int!\n cFieldOnOBigObject: Boolean!\n dFieldOnOBigObject: Float!\n eFieldOnOBigObject: String!\n fFieldOnOBigObject: Int!\n gFieldOnOBigObject: Boolean!\n hFieldOnOBigObject: Float!\n iFieldOnOBigObject: String!\n jFieldOnOBigObject: Int!\n kFieldOnOBigObject: Boolean!\n lFieldOnOBigObject: Float!\n mFieldOnOBigObject: String!\n nFieldOnOBigObject: Int!\n oFieldOnOBigObject: Boolean!\n pFieldOnOBigObject: Float!\n qFieldOnOBigObject: String!\n rFieldOnOBigObject: Int!\n sFieldOnOBigObject: Boolean!\n tFieldOnOBigObject: Float!\n uFieldOnOBigObject: String!\n vFieldOnOBigObject: Int!\n wFieldOnOBigObject: Boolean!\n xFieldOnOBigObject: Float!\n yFieldOnOBigObject: String!\n zFieldOnOBigObject: Int!\n}\n\ntype PBigObject {\n aFieldOnPBigObject: String!\n bFieldOnPBigObject: Int!\n cFieldOnPBigObject: Boolean!\n dFieldOnPBigObject: Float!\n eFieldOnPBigObject: String!\n fFieldOnPBigObject: Int!\n gFieldOnPBigObject: Boolean!\n hFieldOnPBigObject: Float!\n iFieldOnPBigObject: String!\n jFieldOnPBigObject: Int!\n kFieldOnPBigObject: Boolean!\n lFieldOnPBigObject: Float!\n mFieldOnPBigObject: String!\n nFieldOnPBigObject: Int!\n oFieldOnPBigObject: Boolean!\n pFieldOnPBigObject: Float!\n qFieldOnPBigObject: String!\n rFieldOnPBigObject: Int!\n sFieldOnPBigObject: Boolean!\n tFieldOnPBigObject: Float!\n uFieldOnPBigObject: String!\n vFieldOnPBigObject: Int!\n wFieldOnPBigObject: Boolean!\n xFieldOnPBigObject: Float!\n yFieldOnPBigObject: String!\n zFieldOnPBigObject: Int!\n}\n\ntype QBigObject {\n aFieldOnQBigObject: String!\n bFieldOnQBigObject: Int!\n cFieldOnQBigObject: Boolean!\n dFieldOnQBigObject: Float!\n eFieldOnQBigObject: String!\n fFieldOnQBigObject: Int!\n gFieldOnQBigObject: Boolean!\n hFieldOnQBigObject: Float!\n iFieldOnQBigObject: String!\n jFieldOnQBigObject: Int!\n kFieldOnQBigObject: Boolean!\n lFieldOnQBigObject: Float!\n mFieldOnQBigObject: String!\n nFieldOnQBigObject: Int!\n oFieldOnQBigObject: Boolean!\n pFieldOnQBigObject: Float!\n qFieldOnQBigObject: String!\n rFieldOnQBigObject: Int!\n sFieldOnQBigObject: Boolean!\n tFieldOnQBigObject: Float!\n uFieldOnQBigObject: String!\n vFieldOnQBigObject: Int!\n wFieldOnQBigObject: Boolean!\n xFieldOnQBigObject: Float!\n yFieldOnQBigObject: String!\n zFieldOnQBigObject: Int!\n}\n\ntype RBigObject {\n aFieldOnRBigObject: String!\n bFieldOnRBigObject: Int!\n cFieldOnRBigObject: Boolean!\n dFieldOnRBigObject: Float!\n eFieldOnRBigObject: String!\n fFieldOnRBigObject: Int!\n gFieldOnRBigObject: Boolean!\n hFieldOnRBigObject: Float!\n iFieldOnRBigObject: String!\n jFieldOnRBigObject: Int!\n kFieldOnRBigObject: Boolean!\n lFieldOnRBigObject: Float!\n mFieldOnRBigObject: String!\n nFieldOnRBigObject: Int!\n oFieldOnRBigObject: Boolean!\n pFieldOnRBigObject: Float!\n qFieldOnRBigObject: String!\n rFieldOnRBigObject: Int!\n sFieldOnRBigObject: Boolean!\n tFieldOnRBigObject: Float!\n uFieldOnRBigObject: String!\n vFieldOnRBigObject: Int!\n wFieldOnRBigObject: Boolean!\n xFieldOnRBigObject: Float!\n yFieldOnRBigObject: String!\n zFieldOnRBigObject: Int!\n}\n\ntype SBigObject {\n aFieldOnSBigObject: String!\n bFieldOnSBigObject: Int!\n cFieldOnSBigObject: Boolean!\n dFieldOnSBigObject: Float!\n eFieldOnSBigObject: String!\n fFieldOnSBigObject: Int!\n gFieldOnSBigObject: Boolean!\n hFieldOnSBigObject: Float!\n iFieldOnSBigObject: String!\n jFieldOnSBigObject: Int!\n kFieldOnSBigObject: Boolean!\n lFieldOnSBigObject: Float!\n mFieldOnSBigObject: String!\n nFieldOnSBigObject: Int!\n oFieldOnSBigObject: Boolean!\n pFieldOnSBigObject: Float!\n qFieldOnSBigObject: String!\n rFieldOnSBigObject: Int!\n sFieldOnSBigObject: Boolean!\n tFieldOnSBigObject: Float!\n uFieldOnSBigObject: String!\n vFieldOnSBigObject: Int!\n wFieldOnSBigObject: Boolean!\n xFieldOnSBigObject: Float!\n yFieldOnSBigObject: String!\n zFieldOnSBigObject: Int!\n}\n\ntype TBigObject {\n aFieldOnTBigObject: String!\n bFieldOnTBigObject: Int!\n cFieldOnTBigObject: Boolean!\n dFieldOnTBigObject: Float!\n eFieldOnTBigObject: String!\n fFieldOnTBigObject: Int!\n gFieldOnTBigObject: Boolean!\n hFieldOnTBigObject: Float!\n iFieldOnTBigObject: String!\n jFieldOnTBigObject: Int!\n kFieldOnTBigObject: Boolean!\n lFieldOnTBigObject: Float!\n mFieldOnTBigObject: String!\n nFieldOnTBigObject: Int!\n oFieldOnTBigObject: Boolean!\n pFieldOnTBigObject: Float!\n qFieldOnTBigObject: String!\n rFieldOnTBigObject: Int!\n sFieldOnTBigObject: Boolean!\n tFieldOnTBigObject: Float!\n uFieldOnTBigObject: String!\n vFieldOnTBigObject: Int!\n wFieldOnTBigObject: Boolean!\n xFieldOnTBigObject: Float!\n yFieldOnTBigObject: String!\n zFieldOnTBigObject: Int!\n}\n\ntype UBigObject {\n aFieldOnUBigObject: String!\n bFieldOnUBigObject: Int!\n cFieldOnUBigObject: Boolean!\n dFieldOnUBigObject: Float!\n eFieldOnUBigObject: String!\n fFieldOnUBigObject: Int!\n gFieldOnUBigObject: Boolean!\n hFieldOnUBigObject: Float!\n iFieldOnUBigObject: String!\n jFieldOnUBigObject: Int!\n kFieldOnUBigObject: Boolean!\n lFieldOnUBigObject: Float!\n mFieldOnUBigObject: String!\n nFieldOnUBigObject: Int!\n oFieldOnUBigObject: Boolean!\n pFieldOnUBigObject: Float!\n qFieldOnUBigObject: String!\n rFieldOnUBigObject: Int!\n sFieldOnUBigObject: Boolean!\n tFieldOnUBigObject: Float!\n uFieldOnUBigObject: String!\n vFieldOnUBigObject: Int!\n wFieldOnUBigObject: Boolean!\n xFieldOnUBigObject: Float!\n yFieldOnUBigObject: String!\n zFieldOnUBigObject: Int!\n}\n\ntype VBigObject {\n aFieldOnVBigObject: String!\n bFieldOnVBigObject: Int!\n cFieldOnVBigObject: Boolean!\n dFieldOnVBigObject: Float!\n eFieldOnVBigObject: String!\n fFieldOnVBigObject: Int!\n gFieldOnVBigObject: Boolean!\n hFieldOnVBigObject: Float!\n iFieldOnVBigObject: String!\n jFieldOnVBigObject: Int!\n kFieldOnVBigObject: Boolean!\n lFieldOnVBigObject: Float!\n mFieldOnVBigObject: String!\n nFieldOnVBigObject: Int!\n oFieldOnVBigObject: Boolean!\n pFieldOnVBigObject: Float!\n qFieldOnVBigObject: String!\n rFieldOnVBigObject: Int!\n sFieldOnVBigObject: Boolean!\n tFieldOnVBigObject: Float!\n uFieldOnVBigObject: String!\n vFieldOnVBigObject: Int!\n wFieldOnVBigObject: Boolean!\n xFieldOnVBigObject: Float!\n yFieldOnVBigObject: String!\n zFieldOnVBigObject: Int!\n}\n\ntype WBigObject {\n aFieldOnWBigObject: String!\n bFieldOnWBigObject: Int!\n cFieldOnWBigObject: Boolean!\n dFieldOnWBigObject: Float!\n eFieldOnWBigObject: String!\n fFieldOnWBigObject: Int!\n gFieldOnWBigObject: Boolean!\n hFieldOnWBigObject: Float!\n iFieldOnWBigObject: String!\n jFieldOnWBigObject: Int!\n kFieldOnWBigObject: Boolean!\n lFieldOnWBigObject: Float!\n mFieldOnWBigObject: String!\n nFieldOnWBigObject: Int!\n oFieldOnWBigObject: Boolean!\n pFieldOnWBigObject: Float!\n qFieldOnWBigObject: String!\n rFieldOnWBigObject: Int!\n sFieldOnWBigObject: Boolean!\n tFieldOnWBigObject: Float!\n uFieldOnWBigObject: String!\n vFieldOnWBigObject: Int!\n wFieldOnWBigObject: Boolean!\n xFieldOnWBigObject: Float!\n yFieldOnWBigObject: String!\n zFieldOnWBigObject: Int!\n}\n\ntype XBigObject {\n aFieldOnXBigObject: String!\n bFieldOnXBigObject: Int!\n cFieldOnXBigObject: Boolean!\n dFieldOnXBigObject: Float!\n eFieldOnXBigObject: String!\n fFieldOnXBigObject: Int!\n gFieldOnXBigObject: Boolean!\n hFieldOnXBigObject: Float!\n iFieldOnXBigObject: String!\n jFieldOnXBigObject: Int!\n kFieldOnXBigObject: Boolean!\n lFieldOnXBigObject: Float!\n mFieldOnXBigObject: String!\n nFieldOnXBigObject: Int!\n oFieldOnXBigObject: Boolean!\n pFieldOnXBigObject: Float!\n qFieldOnXBigObject: String!\n rFieldOnXBigObject: Int!\n sFieldOnXBigObject: Boolean!\n tFieldOnXBigObject: Float!\n uFieldOnXBigObject: String!\n vFieldOnXBigObject: Int!\n wFieldOnXBigObject: Boolean!\n xFieldOnXBigObject: Float!\n yFieldOnXBigObject: String!\n zFieldOnXBigObject: Int!\n}\n\ntype YBigObject {\n aFieldOnYBigObject: String!\n bFieldOnYBigObject: Int!\n cFieldOnYBigObject: Boolean!\n dFieldOnYBigObject: Float!\n eFieldOnYBigObject: String!\n fFieldOnYBigObject: Int!\n gFieldOnYBigObject: Boolean!\n hFieldOnYBigObject: Float!\n iFieldOnYBigObject: String!\n jFieldOnYBigObject: Int!\n kFieldOnYBigObject: Boolean!\n lFieldOnYBigObject: Float!\n mFieldOnYBigObject: String!\n nFieldOnYBigObject: Int!\n oFieldOnYBigObject: Boolean!\n pFieldOnYBigObject: Float!\n qFieldOnYBigObject: String!\n rFieldOnYBigObject: Int!\n sFieldOnYBigObject: Boolean!\n tFieldOnYBigObject: Float!\n uFieldOnYBigObject: String!\n vFieldOnYBigObject: Int!\n wFieldOnYBigObject: Boolean!\n xFieldOnYBigObject: Float!\n yFieldOnYBigObject: String!\n zFieldOnYBigObject: Int!\n}\n\ntype ZBigObject {\n aFieldOnZBigObject: String!\n bFieldOnZBigObject: Int!\n cFieldOnZBigObject: Boolean!\n dFieldOnZBigObject: Float!\n eFieldOnZBigObject: String!\n fFieldOnZBigObject: Int!\n gFieldOnZBigObject: Boolean!\n hFieldOnZBigObject: Float!\n iFieldOnZBigObject: String!\n jFieldOnZBigObject: Int!\n kFieldOnZBigObject: Boolean!\n lFieldOnZBigObject: Float!\n mFieldOnZBigObject: String!\n nFieldOnZBigObject: Int!\n oFieldOnZBigObject: Boolean!\n pFieldOnZBigObject: Float!\n qFieldOnZBigObject: String!\n rFieldOnZBigObject: Int!\n sFieldOnZBigObject: Boolean!\n tFieldOnZBigObject: Float!\n uFieldOnZBigObject: String!\n vFieldOnZBigObject: Int!\n wFieldOnZBigObject: Boolean!\n xFieldOnZBigObject: Float!\n yFieldOnZBigObject: String!\n zFieldOnZBigObject: Int!\n}\n"
},
"upstreamSchema": {
- "key": "5c5a237ac1f0c1d67ae52534584ee8116d4cc474"
+ "key": "c8d8fe56b658fa642dbb31c0fc3d6f024f4aff10"
}
},
"requestTimeoutSeconds": "10",
@@ -4979,6 +5007,16 @@
}
]
},
+ {
+ "typeName": "Subscription",
+ "fieldName": "metadata",
+ "argumentsConfiguration": [
+ {
+ "name": "repeat",
+ "sourceType": "FIELD_ARGUMENT"
+ }
+ ]
+ },
{
"typeName": "Documentation",
"fieldName": "url",
@@ -5248,18 +5286,18 @@
}
}
],
- "graphqlSchema": "schema {\n query: Query\n mutation: Mutation\n subscription: Subscription\n}\n\ndirective @tag(name: String!) repeatable on ARGUMENT_DEFINITION | ENUM | ENUM_VALUE | FIELD_DEFINITION | INPUT_FIELD_DEFINITION | INPUT_OBJECT | INTERFACE | OBJECT | SCALAR | UNION\n\ndirective @requiresScopes(scopes: [[openfed__Scope!]!]!) on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR\n\ndirective @authenticated on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR\n\ndirective @inaccessible on ARGUMENT_DEFINITION | ENUM | ENUM_VALUE | FIELD_DEFINITION | INPUT_FIELD_DEFINITION | INPUT_OBJECT | INTERFACE | OBJECT | SCALAR | UNION\n\nscalar openfed__Scope\n\ntype Query {\n employee(id: Int!): Employee\n employeeAsList(id: Int!): [Employee]\n employees: [Employee]\n products: [Products!]!\n teammates(team: Department!): [Employee!]!\n firstEmployee: Employee! @tag(name: \"internal\")\n findEmployeesBy(criteria: FindEmployeeCriteria!): [Employee!]!\n \"\"\" This is a GraphQL query that retrieves a list of employees.\"\"\"\n findEmployees(criteria: SearchInput): [Employee!]!\n productTypes: [Products!]!\n topSecretFederationFacts: [TopSecretFact!]! @requiresScopes(scopes: [[\"read:fact\"], [\"read:all\"]])\n factTypes: [TopSecretFactType!]\n \"\"\"Returns the value of the received HTTP header.\"\"\"\n headerValue(name: String!): String!\n \"\"\"Returns the value of the given key in the WS initial payload.\"\"\"\n initPayloadValue(key: String!): String!\n initialPayload: Map\n \"\"\"Returns response after the given delay\"\"\"\n delay(response: String!, ms: Int!): String!\n bigResponse(artificialDelay: Int! = 0, bigObjects: Int! = 100, nestedObjects: Int! = 100, deeplyNestedObjects: Int! = 100): [BigObject!]!\n longResponse(artificialDelay: Int! = 0, bytes: Int!): String\n bigAbstractResponse: BigAbstractResponse\n rootFieldWithListArg(arg: [String!]!): [String!]!\n rootFieldWithNestedListArg(arg: [[String!]!]!): [[String!]!]!\n rootFieldWithListOfInputArg(arg: [InputType!]!): [InputResponse!]!\n rootFieldWithListOfEnumArg(arg: [EnumType!]!): [EnumType!]!\n rootFieldWithInput(arg: InputArg!): String!\n floatField(arg: Float): Float\n sharedThings(numOfA: Int!, numOfB: Int!): [Thing!]!\n secret: Secret @requiresScopes(scopes: [[\"read:secret\"]])\n}\n\nscalar Upload\n\ntype Mutation {\n updateEmployeeTag(id: Int!, tag: String!): Employee\n singleUpload(file: Upload!): Boolean!\n singleUploadWithInput(arg: FileUpload!): Boolean!\n multipleUpload(files: [Upload!]!): Boolean!\n addFact(fact: TopSecretFactInput!): TopSecretFact! @requiresScopes(scopes: [[\"write:fact\"], [\"write:all\"]])\n \"\"\" This mutation updates the availability status of an employee in the system.\n \"\"\"\n updateAvailability(employeeID: Int!, isAvailable: Boolean!): Employee!\n \"\"\" This mutation update the mood of an employee. \"\"\"\n updateMood(employeeID: Int!, mood: Mood!): Employee!\n}\n\ninput FileUpload {\n nested: DeeplyNestedFileUpload\n nestedList: [Upload!]\n}\n\ninput DeeplyNestedFileUpload {\n file: Upload!\n}\n\ntype Subscription {\n \"\"\"`currentTime` will return a stream of `Time` objects.\"\"\"\n currentTime: Time!\n countEmp(max: Int!, intervalMilliseconds: Int!): Int!\n countEmp2(max: Int!, intervalMilliseconds: Int!): Int!\n countFor(count: Int!): Int!\n countHob(max: Int!, intervalMilliseconds: Int!): Int!\n \"\"\"Returns a stream with the value of the received HTTP header.\"\"\"\n headerValue(name: String!, repeat: Int): TimestampedString!\n \"\"\"\n Returns a stream with the value of value of the given key in the WS initial payload.\n \"\"\"\n initPayloadValue(key: String!, repeat: Int): TimestampedString!\n \"\"\"Returns a stream with the value of the WS initial payload.\"\"\"\n initialPayload(repeat: Int): Map\n returnsError: String\n}\n\nenum Department {\n ENGINEERING\n MARKETING\n OPERATIONS\n}\n\ninterface RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n}\n\nenum EngineerType {\n BACKEND\n FRONTEND\n FULLSTACK\n}\n\ninterface Identifiable {\n id: Int!\n}\n\nenum OperationType {\n FINANCE\n HUMAN_RESOURCES\n}\n\ntype Details {\n forename: String!\n location: Country!\n surname: String!\n pastLocations: [City!]!\n middlename: String @deprecated(reason: \"No longer supported\")\n hasChildren: Boolean!\n maritalStatus: MaritalStatus\n nationality: Nationality!\n pets: [Pet]\n}\n\ntype City {\n type: String!\n name: String!\n country: Country\n}\n\ntype Country {\n key: CountryKey!\n language: String\n}\n\ntype CountryKey {\n name: String!\n}\n\nenum Mood {\n HAPPY\n SAD\n APATHETIC @inaccessible\n}\n\ntype ErrorWrapper {\n okField: String\n errorField: String\n}\n\ntype Time {\n unixTime: Int!\n timeStamp: String!\n}\n\nunion Products = Consultancy | Cosmo | SDK | Documentation\n\ninterface IProduct {\n upc: ID!\n engineers: [Employee!]!\n}\n\ntype Consultancy {\n upc: ID!\n lead: Employee!\n isLeadAvailable: Boolean\n name: ProductName!\n}\n\ninterface EmployeeWorkItem {\n name: String!\n priority: Int!\n}\n\ntype WorkItemHandler {\n name: String!\n assignedItem: EmployeeWorkItem!\n}\n\ntype TechnicalSpecs {\n name: String!\n complexity: Float!\n metrics: WorkMetrics!\n}\n\ntype ManagementSpecs {\n name: String!\n scope: Float!\n metrics: WorkMetrics!\n}\n\ntype WorkMetrics {\n score: Float!\n efficiency: Float!\n}\n\nunion WorkReviewResult = WorkApproval | WorkRejection\n\ntype WorkApproval {\n comment: String!\n approvedAt: String!\n}\n\ntype WorkRejection {\n reason: String!\n rejectionCode: String!\n}\n\ntype WorkSetup {\n priority: String!\n primaryItem: EmployeeWorkItem!\n}\n\ninput FindEmployeeCriteria @oneOf {\n id: Int\n department: Department\n title: String\n}\n\nenum Class {\n FISH\n MAMMAL\n REPTILE\n}\n\nenum Gender {\n FEMALE\n MALE\n UNKNOWN\n}\n\ninterface Animal {\n class: Class!\n gender: Gender!\n}\n\nenum CatType {\n HOME\n STREET\n}\n\nenum DogBreed {\n GOLDEN_RETRIEVER\n POODLE\n ROTTWEILER\n YORKSHIRE_TERRIER\n}\n\nenum MaritalStatus {\n ENGAGED\n MARRIED\n}\n\nenum Nationality {\n AMERICAN\n DUTCH\n ENGLISH\n GERMAN\n INDIAN\n SPANISH\n UKRAINIAN\n}\n\n\"\"\" Allows to filter employees by their details. \"\"\"\ninput SearchInput {\n hasPets: Boolean\n nationality: Nationality\n nested: NestedSearchInput\n}\n\ninput NestedSearchInput {\n maritalStatus: MaritalStatus\n hasChildren: Boolean\n}\n\nenum ExerciseType {\n CALISTHENICS\n HIKING\n SPORT\n STRENGTH_TRAINING\n}\n\ninterface Experience {\n yearsOfExperience: Float!\n}\n\nenum GameGenre {\n ADVENTURE\n BOARD\n FPS\n CARD\n RPG\n ROGUELITE\n SIMULATION\n STRATEGY\n}\n\nenum ProgrammingLanguage {\n CSHARP\n GO\n RUST\n TYPESCRIPT\n}\n\ninterface Hobby {\n employees: [Employee!]!\n}\n\ninput TopSecretFactInput {\n title: String!\n description: FactContent!\n factType: TopSecretFactType!\n}\n\nenum TopSecretFactType @authenticated {\n DIRECTIVE\n ENTITY\n MISCELLANEOUS\n}\n\ninterface TopSecretFact @authenticated {\n description: FactContent!\n factType: TopSecretFactType\n}\n\nscalar FactContent @requiresScopes(scopes: [[\"read:scalar\"], [\"read:all\"]])\n\nenum ProductName {\n CONSULTANCY\n COSMO\n ENGINE\n FINANCE\n HUMAN_RESOURCES\n MARKETING\n SDK\n}\n\ntype Documentation {\n url(product: ProductName!): String!\n urls(products: [ProductName!]!): [String!]!\n}\n\ntype Secret {\n value: String\n}\n\ntype Thing {\n b: String!\n}\n\ninput InputArg {\n enums: [EnumType!]\n enum: EnumType\n string: String\n strings: [String!]\n}\n\nenum EnumType {\n A\n B\n C\n}\n\ninput InputType {\n arg: String!\n}\n\ntype InputResponse {\n arg: String!\n}\n\nscalar Map\n\ntype TimestampedString {\n \"\"\"The value of the string.\"\"\"\n value: String!\n \"\"\"The timestamp when the response was generated.\"\"\"\n unixTime: Int!\n \"\"\"Sequence number\"\"\"\n seq: Int!\n \"\"\"Total number of responses to be sent\"\"\"\n total: Int!\n initialPayload: Map\n}\n\ntype BigObject {\n nestedObjects: [NestedObject!]!\n}\n\ntype NestedObject {\n deeplyNestedObjects: [DeeplyNestedObject!]!\n}\n\ntype DeeplyNestedObject {\n aFieldOnDeeplyNestedObject: String!\n bFieldOnDeeplyNestedObject: Int!\n cFieldOnDeeplyNestedObject: Boolean!\n dFieldOnDeeplyNestedObject: Float!\n eFieldOnDeeplyNestedObject: String!\n fFieldOnDeeplyNestedObject: Int!\n gFieldOnDeeplyNestedObject: Boolean!\n hFieldOnDeeplyNestedObject: Float!\n iFieldOnDeeplyNestedObject: String!\n jFieldOnDeeplyNestedObject: Int!\n kFieldOnDeeplyNestedObject: Boolean!\n lFieldOnDeeplyNestedObject: Float!\n mFieldOnDeeplyNestedObject: String!\n nFieldOnDeeplyNestedObject: Int!\n oFieldOnDeeplyNestedObject: Boolean!\n pFieldOnDeeplyNestedObject: Float!\n qFieldOnDeeplyNestedObject: String!\n rFieldOnDeeplyNestedObject: Int!\n sFieldOnDeeplyNestedObject: Boolean!\n tFieldOnDeeplyNestedObject: Float!\n uFieldOnDeeplyNestedObject: String!\n vFieldOnDeeplyNestedObject: Int!\n wFieldOnDeeplyNestedObject: Boolean!\n xFieldOnDeeplyNestedObject: Float!\n yFieldOnDeeplyNestedObject: String!\n zFieldOnDeeplyNestedObject: Int!\n}\n\nunion BigAbstractResponse = ABigObject | BBigObject | CBigObject | DBigObject | EBigObject | FBigObject | GBigObject | HBigObject | IBigObject | JBigObject | KBigObject | LBigObject | MBigObject | NBigObject | OBigObject | PBigObject | QBigObject | RBigObject | SBigObject | TBigObject | UBigObject | VBigObject | WBigObject | XBigObject | YBigObject | ZBigObject\n\ntype ABigObject {\n aFieldOnABigObject: String!\n bFieldOnABigObject: Int!\n cFieldOnABigObject: Boolean!\n dFieldOnABigObject: Float!\n eFieldOnABigObject: String!\n fFieldOnABigObject: Int!\n gFieldOnABigObject: Boolean!\n hFieldOnABigObject: Float!\n iFieldOnABigObject: String!\n jFieldOnABigObject: Int!\n kFieldOnABigObject: Boolean!\n lFieldOnABigObject: Float!\n mFieldOnABigObject: String!\n nFieldOnABigObject: Int!\n oFieldOnABigObject: Boolean!\n pFieldOnABigObject: Float!\n qFieldOnABigObject: String!\n rFieldOnABigObject: Int!\n sFieldOnABigObject: Boolean!\n tFieldOnABigObject: Float!\n uFieldOnABigObject: String!\n vFieldOnABigObject: Int!\n wFieldOnABigObject: Boolean!\n xFieldOnABigObject: Float!\n yFieldOnABigObject: String!\n zFieldOnABigObject: Int!\n}\n\ntype BBigObject {\n aFieldOnBBigObject: String!\n bFieldOnBBigObject: Int!\n cFieldOnBBigObject: Boolean!\n dFieldOnBBigObject: Float!\n eFieldOnBBigObject: String!\n fFieldOnBBigObject: Int!\n gFieldOnBBigObject: Boolean!\n hFieldOnBBigObject: Float!\n iFieldOnBBigObject: String!\n jFieldOnBBigObject: Int!\n kFieldOnBBigObject: Boolean!\n lFieldOnBBigObject: Float!\n mFieldOnBBigObject: String!\n nFieldOnBBigObject: Int!\n oFieldOnBBigObject: Boolean!\n pFieldOnBBigObject: Float!\n qFieldOnBBigObject: String!\n rFieldOnBBigObject: Int!\n sFieldOnBBigObject: Boolean!\n tFieldOnBBigObject: Float!\n uFieldOnBBigObject: String!\n vFieldOnBBigObject: Int!\n wFieldOnBBigObject: Boolean!\n xFieldOnBBigObject: Float!\n yFieldOnBBigObject: String!\n zFieldOnBBigObject: Int!\n}\n\ntype CBigObject {\n aFieldOnCBigObject: String!\n bFieldOnCBigObject: Int!\n cFieldOnCBigObject: Boolean!\n dFieldOnCBigObject: Float!\n eFieldOnCBigObject: String!\n fFieldOnCBigObject: Int!\n gFieldOnCBigObject: Boolean!\n hFieldOnCBigObject: Float!\n iFieldOnCBigObject: String!\n jFieldOnCBigObject: Int!\n kFieldOnCBigObject: Boolean!\n lFieldOnCBigObject: Float!\n mFieldOnCBigObject: String!\n nFieldOnCBigObject: Int!\n oFieldOnCBigObject: Boolean!\n pFieldOnCBigObject: Float!\n qFieldOnCBigObject: String!\n rFieldOnCBigObject: Int!\n sFieldOnCBigObject: Boolean!\n tFieldOnCBigObject: Float!\n uFieldOnCBigObject: String!\n vFieldOnCBigObject: Int!\n wFieldOnCBigObject: Boolean!\n xFieldOnCBigObject: Float!\n yFieldOnCBigObject: String!\n zFieldOnCBigObject: Int!\n}\n\ntype DBigObject {\n aFieldOnDBigObject: String!\n bFieldOnDBigObject: Int!\n cFieldOnDBigObject: Boolean!\n dFieldOnDBigObject: Float!\n eFieldOnDBigObject: String!\n fFieldOnDBigObject: Int!\n gFieldOnDBigObject: Boolean!\n hFieldOnDBigObject: Float!\n iFieldOnDBigObject: String!\n jFieldOnDBigObject: Int!\n kFieldOnDBigObject: Boolean!\n lFieldOnDBigObject: Float!\n mFieldOnDBigObject: String!\n nFieldOnDBigObject: Int!\n oFieldOnDBigObject: Boolean!\n pFieldOnDBigObject: Float!\n qFieldOnDBigObject: String!\n rFieldOnDBigObject: Int!\n sFieldOnDBigObject: Boolean!\n tFieldOnDBigObject: Float!\n uFieldOnDBigObject: String!\n vFieldOnDBigObject: Int!\n wFieldOnDBigObject: Boolean!\n xFieldOnDBigObject: Float!\n yFieldOnDBigObject: String!\n zFieldOnDBigObject: Int!\n}\n\ntype EBigObject {\n aFieldOnEBigObject: String!\n bFieldOnEBigObject: Int!\n cFieldOnEBigObject: Boolean!\n dFieldOnEBigObject: Float!\n eFieldOnEBigObject: String!\n fFieldOnEBigObject: Int!\n gFieldOnEBigObject: Boolean!\n hFieldOnEBigObject: Float!\n iFieldOnEBigObject: String!\n jFieldOnEBigObject: Int!\n kFieldOnEBigObject: Boolean!\n lFieldOnEBigObject: Float!\n mFieldOnEBigObject: String!\n nFieldOnEBigObject: Int!\n oFieldOnEBigObject: Boolean!\n pFieldOnEBigObject: Float!\n qFieldOnEBigObject: String!\n rFieldOnEBigObject: Int!\n sFieldOnEBigObject: Boolean!\n tFieldOnEBigObject: Float!\n uFieldOnEBigObject: String!\n vFieldOnEBigObject: Int!\n wFieldOnEBigObject: Boolean!\n xFieldOnEBigObject: Float!\n yFieldOnEBigObject: String!\n zFieldOnEBigObject: Int!\n}\n\ntype FBigObject {\n aFieldOnFBigObject: String!\n bFieldOnFBigObject: Int!\n cFieldOnFBigObject: Boolean!\n dFieldOnFBigObject: Float!\n eFieldOnFBigObject: String!\n fFieldOnFBigObject: Int!\n gFieldOnFBigObject: Boolean!\n hFieldOnFBigObject: Float!\n iFieldOnFBigObject: String!\n jFieldOnFBigObject: Int!\n kFieldOnFBigObject: Boolean!\n lFieldOnFBigObject: Float!\n mFieldOnFBigObject: String!\n nFieldOnFBigObject: Int!\n oFieldOnFBigObject: Boolean!\n pFieldOnFBigObject: Float!\n qFieldOnFBigObject: String!\n rFieldOnFBigObject: Int!\n sFieldOnFBigObject: Boolean!\n tFieldOnFBigObject: Float!\n uFieldOnFBigObject: String!\n vFieldOnFBigObject: Int!\n wFieldOnFBigObject: Boolean!\n xFieldOnFBigObject: Float!\n yFieldOnFBigObject: String!\n zFieldOnFBigObject: Int!\n}\n\ntype GBigObject {\n aFieldOnGBigObject: String!\n bFieldOnGBigObject: Int!\n cFieldOnGBigObject: Boolean!\n dFieldOnGBigObject: Float!\n eFieldOnGBigObject: String!\n fFieldOnGBigObject: Int!\n gFieldOnGBigObject: Boolean!\n hFieldOnGBigObject: Float!\n iFieldOnGBigObject: String!\n jFieldOnGBigObject: Int!\n kFieldOnGBigObject: Boolean!\n lFieldOnGBigObject: Float!\n mFieldOnGBigObject: String!\n nFieldOnGBigObject: Int!\n oFieldOnGBigObject: Boolean!\n pFieldOnGBigObject: Float!\n qFieldOnGBigObject: String!\n rFieldOnGBigObject: Int!\n sFieldOnGBigObject: Boolean!\n tFieldOnGBigObject: Float!\n uFieldOnGBigObject: String!\n vFieldOnGBigObject: Int!\n wFieldOnGBigObject: Boolean!\n xFieldOnGBigObject: Float!\n yFieldOnGBigObject: String!\n zFieldOnGBigObject: Int!\n}\n\ntype HBigObject {\n aFieldOnHBigObject: String!\n bFieldOnHBigObject: Int!\n cFieldOnHBigObject: Boolean!\n dFieldOnHBigObject: Float!\n eFieldOnHBigObject: String!\n fFieldOnHBigObject: Int!\n gFieldOnHBigObject: Boolean!\n hFieldOnHBigObject: Float!\n iFieldOnHBigObject: String!\n jFieldOnHBigObject: Int!\n kFieldOnHBigObject: Boolean!\n lFieldOnHBigObject: Float!\n mFieldOnHBigObject: String!\n nFieldOnHBigObject: Int!\n oFieldOnHBigObject: Boolean!\n pFieldOnHBigObject: Float!\n qFieldOnHBigObject: String!\n rFieldOnHBigObject: Int!\n sFieldOnHBigObject: Boolean!\n tFieldOnHBigObject: Float!\n uFieldOnHBigObject: String!\n vFieldOnHBigObject: Int!\n wFieldOnHBigObject: Boolean!\n xFieldOnHBigObject: Float!\n yFieldOnHBigObject: String!\n zFieldOnHBigObject: Int!\n}\n\ntype IBigObject {\n aFieldOnIBigObject: String!\n bFieldOnIBigObject: Int!\n cFieldOnIBigObject: Boolean!\n dFieldOnIBigObject: Float!\n eFieldOnIBigObject: String!\n fFieldOnIBigObject: Int!\n gFieldOnIBigObject: Boolean!\n hFieldOnIBigObject: Float!\n iFieldOnIBigObject: String!\n jFieldOnIBigObject: Int!\n kFieldOnIBigObject: Boolean!\n lFieldOnIBigObject: Float!\n mFieldOnIBigObject: String!\n nFieldOnIBigObject: Int!\n oFieldOnIBigObject: Boolean!\n pFieldOnIBigObject: Float!\n qFieldOnIBigObject: String!\n rFieldOnIBigObject: Int!\n sFieldOnIBigObject: Boolean!\n tFieldOnIBigObject: Float!\n uFieldOnIBigObject: String!\n vFieldOnIBigObject: Int!\n wFieldOnIBigObject: Boolean!\n xFieldOnIBigObject: Float!\n yFieldOnIBigObject: String!\n zFieldOnIBigObject: Int!\n}\n\ntype JBigObject {\n aFieldOnJBigObject: String!\n bFieldOnJBigObject: Int!\n cFieldOnJBigObject: Boolean!\n dFieldOnJBigObject: Float!\n eFieldOnJBigObject: String!\n fFieldOnJBigObject: Int!\n gFieldOnJBigObject: Boolean!\n hFieldOnJBigObject: Float!\n iFieldOnJBigObject: String!\n jFieldOnJBigObject: Int!\n kFieldOnJBigObject: Boolean!\n lFieldOnJBigObject: Float!\n mFieldOnJBigObject: String!\n nFieldOnJBigObject: Int!\n oFieldOnJBigObject: Boolean!\n pFieldOnJBigObject: Float!\n qFieldOnJBigObject: String!\n rFieldOnJBigObject: Int!\n sFieldOnJBigObject: Boolean!\n tFieldOnJBigObject: Float!\n uFieldOnJBigObject: String!\n vFieldOnJBigObject: Int!\n wFieldOnJBigObject: Boolean!\n xFieldOnJBigObject: Float!\n yFieldOnJBigObject: String!\n zFieldOnJBigObject: Int!\n}\n\ntype KBigObject {\n aFieldOnKBigObject: String!\n bFieldOnKBigObject: Int!\n cFieldOnKBigObject: Boolean!\n dFieldOnKBigObject: Float!\n eFieldOnKBigObject: String!\n fFieldOnKBigObject: Int!\n gFieldOnKBigObject: Boolean!\n hFieldOnKBigObject: Float!\n iFieldOnKBigObject: String!\n jFieldOnKBigObject: Int!\n kFieldOnKBigObject: Boolean!\n lFieldOnKBigObject: Float!\n mFieldOnKBigObject: String!\n nFieldOnKBigObject: Int!\n oFieldOnKBigObject: Boolean!\n pFieldOnKBigObject: Float!\n qFieldOnKBigObject: String!\n rFieldOnKBigObject: Int!\n sFieldOnKBigObject: Boolean!\n tFieldOnKBigObject: Float!\n uFieldOnKBigObject: String!\n vFieldOnKBigObject: Int!\n wFieldOnKBigObject: Boolean!\n xFieldOnKBigObject: Float!\n yFieldOnKBigObject: String!\n zFieldOnKBigObject: Int!\n}\n\ntype LBigObject {\n aFieldOnLBigObject: String!\n bFieldOnLBigObject: Int!\n cFieldOnLBigObject: Boolean!\n dFieldOnLBigObject: Float!\n eFieldOnLBigObject: String!\n fFieldOnLBigObject: Int!\n gFieldOnLBigObject: Boolean!\n hFieldOnLBigObject: Float!\n iFieldOnLBigObject: String!\n jFieldOnLBigObject: Int!\n kFieldOnLBigObject: Boolean!\n lFieldOnLBigObject: Float!\n mFieldOnLBigObject: String!\n nFieldOnLBigObject: Int!\n oFieldOnLBigObject: Boolean!\n pFieldOnLBigObject: Float!\n qFieldOnLBigObject: String!\n rFieldOnLBigObject: Int!\n sFieldOnLBigObject: Boolean!\n tFieldOnLBigObject: Float!\n uFieldOnLBigObject: String!\n vFieldOnLBigObject: Int!\n wFieldOnLBigObject: Boolean!\n xFieldOnLBigObject: Float!\n yFieldOnLBigObject: String!\n zFieldOnLBigObject: Int!\n}\n\ntype MBigObject {\n aFieldOnMBigObject: String!\n bFieldOnMBigObject: Int!\n cFieldOnMBigObject: Boolean!\n dFieldOnMBigObject: Float!\n eFieldOnMBigObject: String!\n fFieldOnMBigObject: Int!\n gFieldOnMBigObject: Boolean!\n hFieldOnMBigObject: Float!\n iFieldOnMBigObject: String!\n jFieldOnMBigObject: Int!\n kFieldOnMBigObject: Boolean!\n lFieldOnMBigObject: Float!\n mFieldOnMBigObject: String!\n nFieldOnMBigObject: Int!\n oFieldOnMBigObject: Boolean!\n pFieldOnMBigObject: Float!\n qFieldOnMBigObject: String!\n rFieldOnMBigObject: Int!\n sFieldOnMBigObject: Boolean!\n tFieldOnMBigObject: Float!\n uFieldOnMBigObject: String!\n vFieldOnMBigObject: Int!\n wFieldOnMBigObject: Boolean!\n xFieldOnMBigObject: Float!\n yFieldOnMBigObject: String!\n zFieldOnMBigObject: Int!\n}\n\ntype NBigObject {\n aFieldOnNBigObject: String!\n bFieldOnNBigObject: Int!\n cFieldOnNBigObject: Boolean!\n dFieldOnNBigObject: Float!\n eFieldOnNBigObject: String!\n fFieldOnNBigObject: Int!\n gFieldOnNBigObject: Boolean!\n hFieldOnNBigObject: Float!\n iFieldOnNBigObject: String!\n jFieldOnNBigObject: Int!\n kFieldOnNBigObject: Boolean!\n lFieldOnNBigObject: Float!\n mFieldOnNBigObject: String!\n nFieldOnNBigObject: Int!\n oFieldOnNBigObject: Boolean!\n pFieldOnNBigObject: Float!\n qFieldOnNBigObject: String!\n rFieldOnNBigObject: Int!\n sFieldOnNBigObject: Boolean!\n tFieldOnNBigObject: Float!\n uFieldOnNBigObject: String!\n vFieldOnNBigObject: Int!\n wFieldOnNBigObject: Boolean!\n xFieldOnNBigObject: Float!\n yFieldOnNBigObject: String!\n zFieldOnNBigObject: Int!\n}\n\ntype OBigObject {\n aFieldOnOBigObject: String!\n bFieldOnOBigObject: Int!\n cFieldOnOBigObject: Boolean!\n dFieldOnOBigObject: Float!\n eFieldOnOBigObject: String!\n fFieldOnOBigObject: Int!\n gFieldOnOBigObject: Boolean!\n hFieldOnOBigObject: Float!\n iFieldOnOBigObject: String!\n jFieldOnOBigObject: Int!\n kFieldOnOBigObject: Boolean!\n lFieldOnOBigObject: Float!\n mFieldOnOBigObject: String!\n nFieldOnOBigObject: Int!\n oFieldOnOBigObject: Boolean!\n pFieldOnOBigObject: Float!\n qFieldOnOBigObject: String!\n rFieldOnOBigObject: Int!\n sFieldOnOBigObject: Boolean!\n tFieldOnOBigObject: Float!\n uFieldOnOBigObject: String!\n vFieldOnOBigObject: Int!\n wFieldOnOBigObject: Boolean!\n xFieldOnOBigObject: Float!\n yFieldOnOBigObject: String!\n zFieldOnOBigObject: Int!\n}\n\ntype PBigObject {\n aFieldOnPBigObject: String!\n bFieldOnPBigObject: Int!\n cFieldOnPBigObject: Boolean!\n dFieldOnPBigObject: Float!\n eFieldOnPBigObject: String!\n fFieldOnPBigObject: Int!\n gFieldOnPBigObject: Boolean!\n hFieldOnPBigObject: Float!\n iFieldOnPBigObject: String!\n jFieldOnPBigObject: Int!\n kFieldOnPBigObject: Boolean!\n lFieldOnPBigObject: Float!\n mFieldOnPBigObject: String!\n nFieldOnPBigObject: Int!\n oFieldOnPBigObject: Boolean!\n pFieldOnPBigObject: Float!\n qFieldOnPBigObject: String!\n rFieldOnPBigObject: Int!\n sFieldOnPBigObject: Boolean!\n tFieldOnPBigObject: Float!\n uFieldOnPBigObject: String!\n vFieldOnPBigObject: Int!\n wFieldOnPBigObject: Boolean!\n xFieldOnPBigObject: Float!\n yFieldOnPBigObject: String!\n zFieldOnPBigObject: Int!\n}\n\ntype QBigObject {\n aFieldOnQBigObject: String!\n bFieldOnQBigObject: Int!\n cFieldOnQBigObject: Boolean!\n dFieldOnQBigObject: Float!\n eFieldOnQBigObject: String!\n fFieldOnQBigObject: Int!\n gFieldOnQBigObject: Boolean!\n hFieldOnQBigObject: Float!\n iFieldOnQBigObject: String!\n jFieldOnQBigObject: Int!\n kFieldOnQBigObject: Boolean!\n lFieldOnQBigObject: Float!\n mFieldOnQBigObject: String!\n nFieldOnQBigObject: Int!\n oFieldOnQBigObject: Boolean!\n pFieldOnQBigObject: Float!\n qFieldOnQBigObject: String!\n rFieldOnQBigObject: Int!\n sFieldOnQBigObject: Boolean!\n tFieldOnQBigObject: Float!\n uFieldOnQBigObject: String!\n vFieldOnQBigObject: Int!\n wFieldOnQBigObject: Boolean!\n xFieldOnQBigObject: Float!\n yFieldOnQBigObject: String!\n zFieldOnQBigObject: Int!\n}\n\ntype RBigObject {\n aFieldOnRBigObject: String!\n bFieldOnRBigObject: Int!\n cFieldOnRBigObject: Boolean!\n dFieldOnRBigObject: Float!\n eFieldOnRBigObject: String!\n fFieldOnRBigObject: Int!\n gFieldOnRBigObject: Boolean!\n hFieldOnRBigObject: Float!\n iFieldOnRBigObject: String!\n jFieldOnRBigObject: Int!\n kFieldOnRBigObject: Boolean!\n lFieldOnRBigObject: Float!\n mFieldOnRBigObject: String!\n nFieldOnRBigObject: Int!\n oFieldOnRBigObject: Boolean!\n pFieldOnRBigObject: Float!\n qFieldOnRBigObject: String!\n rFieldOnRBigObject: Int!\n sFieldOnRBigObject: Boolean!\n tFieldOnRBigObject: Float!\n uFieldOnRBigObject: String!\n vFieldOnRBigObject: Int!\n wFieldOnRBigObject: Boolean!\n xFieldOnRBigObject: Float!\n yFieldOnRBigObject: String!\n zFieldOnRBigObject: Int!\n}\n\ntype SBigObject {\n aFieldOnSBigObject: String!\n bFieldOnSBigObject: Int!\n cFieldOnSBigObject: Boolean!\n dFieldOnSBigObject: Float!\n eFieldOnSBigObject: String!\n fFieldOnSBigObject: Int!\n gFieldOnSBigObject: Boolean!\n hFieldOnSBigObject: Float!\n iFieldOnSBigObject: String!\n jFieldOnSBigObject: Int!\n kFieldOnSBigObject: Boolean!\n lFieldOnSBigObject: Float!\n mFieldOnSBigObject: String!\n nFieldOnSBigObject: Int!\n oFieldOnSBigObject: Boolean!\n pFieldOnSBigObject: Float!\n qFieldOnSBigObject: String!\n rFieldOnSBigObject: Int!\n sFieldOnSBigObject: Boolean!\n tFieldOnSBigObject: Float!\n uFieldOnSBigObject: String!\n vFieldOnSBigObject: Int!\n wFieldOnSBigObject: Boolean!\n xFieldOnSBigObject: Float!\n yFieldOnSBigObject: String!\n zFieldOnSBigObject: Int!\n}\n\ntype TBigObject {\n aFieldOnTBigObject: String!\n bFieldOnTBigObject: Int!\n cFieldOnTBigObject: Boolean!\n dFieldOnTBigObject: Float!\n eFieldOnTBigObject: String!\n fFieldOnTBigObject: Int!\n gFieldOnTBigObject: Boolean!\n hFieldOnTBigObject: Float!\n iFieldOnTBigObject: String!\n jFieldOnTBigObject: Int!\n kFieldOnTBigObject: Boolean!\n lFieldOnTBigObject: Float!\n mFieldOnTBigObject: String!\n nFieldOnTBigObject: Int!\n oFieldOnTBigObject: Boolean!\n pFieldOnTBigObject: Float!\n qFieldOnTBigObject: String!\n rFieldOnTBigObject: Int!\n sFieldOnTBigObject: Boolean!\n tFieldOnTBigObject: Float!\n uFieldOnTBigObject: String!\n vFieldOnTBigObject: Int!\n wFieldOnTBigObject: Boolean!\n xFieldOnTBigObject: Float!\n yFieldOnTBigObject: String!\n zFieldOnTBigObject: Int!\n}\n\ntype UBigObject {\n aFieldOnUBigObject: String!\n bFieldOnUBigObject: Int!\n cFieldOnUBigObject: Boolean!\n dFieldOnUBigObject: Float!\n eFieldOnUBigObject: String!\n fFieldOnUBigObject: Int!\n gFieldOnUBigObject: Boolean!\n hFieldOnUBigObject: Float!\n iFieldOnUBigObject: String!\n jFieldOnUBigObject: Int!\n kFieldOnUBigObject: Boolean!\n lFieldOnUBigObject: Float!\n mFieldOnUBigObject: String!\n nFieldOnUBigObject: Int!\n oFieldOnUBigObject: Boolean!\n pFieldOnUBigObject: Float!\n qFieldOnUBigObject: String!\n rFieldOnUBigObject: Int!\n sFieldOnUBigObject: Boolean!\n tFieldOnUBigObject: Float!\n uFieldOnUBigObject: String!\n vFieldOnUBigObject: Int!\n wFieldOnUBigObject: Boolean!\n xFieldOnUBigObject: Float!\n yFieldOnUBigObject: String!\n zFieldOnUBigObject: Int!\n}\n\ntype VBigObject {\n aFieldOnVBigObject: String!\n bFieldOnVBigObject: Int!\n cFieldOnVBigObject: Boolean!\n dFieldOnVBigObject: Float!\n eFieldOnVBigObject: String!\n fFieldOnVBigObject: Int!\n gFieldOnVBigObject: Boolean!\n hFieldOnVBigObject: Float!\n iFieldOnVBigObject: String!\n jFieldOnVBigObject: Int!\n kFieldOnVBigObject: Boolean!\n lFieldOnVBigObject: Float!\n mFieldOnVBigObject: String!\n nFieldOnVBigObject: Int!\n oFieldOnVBigObject: Boolean!\n pFieldOnVBigObject: Float!\n qFieldOnVBigObject: String!\n rFieldOnVBigObject: Int!\n sFieldOnVBigObject: Boolean!\n tFieldOnVBigObject: Float!\n uFieldOnVBigObject: String!\n vFieldOnVBigObject: Int!\n wFieldOnVBigObject: Boolean!\n xFieldOnVBigObject: Float!\n yFieldOnVBigObject: String!\n zFieldOnVBigObject: Int!\n}\n\ntype WBigObject {\n aFieldOnWBigObject: String!\n bFieldOnWBigObject: Int!\n cFieldOnWBigObject: Boolean!\n dFieldOnWBigObject: Float!\n eFieldOnWBigObject: String!\n fFieldOnWBigObject: Int!\n gFieldOnWBigObject: Boolean!\n hFieldOnWBigObject: Float!\n iFieldOnWBigObject: String!\n jFieldOnWBigObject: Int!\n kFieldOnWBigObject: Boolean!\n lFieldOnWBigObject: Float!\n mFieldOnWBigObject: String!\n nFieldOnWBigObject: Int!\n oFieldOnWBigObject: Boolean!\n pFieldOnWBigObject: Float!\n qFieldOnWBigObject: String!\n rFieldOnWBigObject: Int!\n sFieldOnWBigObject: Boolean!\n tFieldOnWBigObject: Float!\n uFieldOnWBigObject: String!\n vFieldOnWBigObject: Int!\n wFieldOnWBigObject: Boolean!\n xFieldOnWBigObject: Float!\n yFieldOnWBigObject: String!\n zFieldOnWBigObject: Int!\n}\n\ntype XBigObject {\n aFieldOnXBigObject: String!\n bFieldOnXBigObject: Int!\n cFieldOnXBigObject: Boolean!\n dFieldOnXBigObject: Float!\n eFieldOnXBigObject: String!\n fFieldOnXBigObject: Int!\n gFieldOnXBigObject: Boolean!\n hFieldOnXBigObject: Float!\n iFieldOnXBigObject: String!\n jFieldOnXBigObject: Int!\n kFieldOnXBigObject: Boolean!\n lFieldOnXBigObject: Float!\n mFieldOnXBigObject: String!\n nFieldOnXBigObject: Int!\n oFieldOnXBigObject: Boolean!\n pFieldOnXBigObject: Float!\n qFieldOnXBigObject: String!\n rFieldOnXBigObject: Int!\n sFieldOnXBigObject: Boolean!\n tFieldOnXBigObject: Float!\n uFieldOnXBigObject: String!\n vFieldOnXBigObject: Int!\n wFieldOnXBigObject: Boolean!\n xFieldOnXBigObject: Float!\n yFieldOnXBigObject: String!\n zFieldOnXBigObject: Int!\n}\n\ntype YBigObject {\n aFieldOnYBigObject: String!\n bFieldOnYBigObject: Int!\n cFieldOnYBigObject: Boolean!\n dFieldOnYBigObject: Float!\n eFieldOnYBigObject: String!\n fFieldOnYBigObject: Int!\n gFieldOnYBigObject: Boolean!\n hFieldOnYBigObject: Float!\n iFieldOnYBigObject: String!\n jFieldOnYBigObject: Int!\n kFieldOnYBigObject: Boolean!\n lFieldOnYBigObject: Float!\n mFieldOnYBigObject: String!\n nFieldOnYBigObject: Int!\n oFieldOnYBigObject: Boolean!\n pFieldOnYBigObject: Float!\n qFieldOnYBigObject: String!\n rFieldOnYBigObject: Int!\n sFieldOnYBigObject: Boolean!\n tFieldOnYBigObject: Float!\n uFieldOnYBigObject: String!\n vFieldOnYBigObject: Int!\n wFieldOnYBigObject: Boolean!\n xFieldOnYBigObject: Float!\n yFieldOnYBigObject: String!\n zFieldOnYBigObject: Int!\n}\n\ntype ZBigObject {\n aFieldOnZBigObject: String!\n bFieldOnZBigObject: Int!\n cFieldOnZBigObject: Boolean!\n dFieldOnZBigObject: Float!\n eFieldOnZBigObject: String!\n fFieldOnZBigObject: Int!\n gFieldOnZBigObject: Boolean!\n hFieldOnZBigObject: Float!\n iFieldOnZBigObject: String!\n jFieldOnZBigObject: Int!\n kFieldOnZBigObject: Boolean!\n lFieldOnZBigObject: Float!\n mFieldOnZBigObject: String!\n nFieldOnZBigObject: Int!\n oFieldOnZBigObject: Boolean!\n pFieldOnZBigObject: Float!\n qFieldOnZBigObject: String!\n rFieldOnZBigObject: Int!\n sFieldOnZBigObject: Boolean!\n tFieldOnZBigObject: Float!\n uFieldOnZBigObject: String!\n vFieldOnZBigObject: Int!\n wFieldOnZBigObject: Boolean!\n xFieldOnZBigObject: Float!\n yFieldOnZBigObject: String!\n zFieldOnZBigObject: Int!\n}\n\ntype Engineer implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n engineerType: EngineerType!\n}\n\ntype Marketer implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n}\n\ntype Operator implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n operatorType: [OperationType!]!\n}\n\ntype Employee implements Identifiable {\n details: Details\n id: Int!\n tag: String!\n expertise: String!\n role: RoleType!\n notes: String\n updatedAt: String!\n startDate: String! @requiresScopes(scopes: [[\"read:employee\", \"read:private\"], [\"read:all\"]])\n currentMood: Mood!\n derivedMood: Mood!\n isAvailable: Boolean\n rootFieldThrowsError: String\n rootFieldErrorWrapper: ErrorWrapper\n primaryWorkItem: EmployeeWorkItem\n lastWorkReview: WorkReviewResult\n workSetup: WorkSetup\n hobbies: [Hobby!]\n products: [ProductName!]!\n productCount: Int!\n fieldThrowsError: String\n}\n\ntype Cosmo implements IProduct {\n upc: ID!\n engineers: [Employee!]!\n lead: Employee!\n isLeadAvailable: Boolean\n name: ProductName!\n repositoryURL: String!\n}\n\ntype SDK implements IProduct {\n upc: ID!\n engineers: [Employee!]!\n owner: Employee!\n unicode: String!\n clientLanguages: [ProgrammingLanguage!]!\n}\n\ntype TechnicalWorkItem implements EmployeeWorkItem {\n name: String!\n priority: Int!\n codeCount: Int!\n handler: WorkItemHandler!\n specs: TechnicalSpecs!\n}\n\ntype ManagementWorkItem implements EmployeeWorkItem {\n name: String!\n priority: Int!\n teamSize: String!\n handler: WorkItemHandler!\n specs: ManagementSpecs!\n}\n\ninterface Pet implements Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Alligator implements Pet & Animal {\n class: Class!\n dangerous: String!\n gender: Gender!\n name: String!\n}\n\ntype Cat implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n type: CatType!\n}\n\ntype Dog implements Pet & Animal {\n breed: DogBreed!\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Mouse implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Pony implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Exercise implements Hobby {\n employees: [Employee!]!\n category: ExerciseType!\n}\n\ntype Flying implements Experience & Hobby {\n employees: [Employee!]!\n planeModels: [String!]!\n yearsOfExperience: Float!\n}\n\ntype Gaming implements Experience & Hobby {\n employees: [Employee!]!\n genres: [GameGenre!]!\n name: String!\n yearsOfExperience: Float!\n}\n\ntype Other implements Hobby {\n employees: [Employee!]!\n name: String!\n}\n\ntype Programming implements Hobby {\n employees: [Employee!]!\n languages: [ProgrammingLanguage!]!\n}\n\ntype Travelling implements Hobby {\n employees: [Employee!]!\n countriesLived: [Country!]!\n}\n\ntype DirectiveFact implements TopSecretFact @authenticated {\n title: String!\n description: FactContent!\n factType: TopSecretFactType\n}\n\ntype EntityFact implements TopSecretFact @requiresScopes(scopes: [[\"read:entity\"]]) {\n title: String!\n description: FactContent!\n factType: TopSecretFactType\n}\n\ntype MiscellaneousFact implements TopSecretFact {\n title: String!\n description: FactContent! @requiresScopes(scopes: [[\"read:miscellaneous\"]])\n factType: TopSecretFactType\n}",
+ "graphqlSchema": "schema {\n query: Query\n mutation: Mutation\n subscription: Subscription\n}\n\ndirective @tag(name: String!) repeatable on ARGUMENT_DEFINITION | ENUM | ENUM_VALUE | FIELD_DEFINITION | INPUT_FIELD_DEFINITION | INPUT_OBJECT | INTERFACE | OBJECT | SCALAR | UNION\n\ndirective @requiresScopes(scopes: [[openfed__Scope!]!]!) on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR\n\ndirective @authenticated on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR\n\ndirective @inaccessible on ARGUMENT_DEFINITION | ENUM | ENUM_VALUE | FIELD_DEFINITION | INPUT_FIELD_DEFINITION | INPUT_OBJECT | INTERFACE | OBJECT | SCALAR | UNION\n\nscalar openfed__Scope\n\ntype Query {\n employee(id: Int!): Employee\n employeeAsList(id: Int!): [Employee]\n employees: [Employee]\n products: [Products!]!\n teammates(team: Department!): [Employee!]!\n firstEmployee: Employee! @tag(name: \"internal\")\n findEmployeesBy(criteria: FindEmployeeCriteria!): [Employee!]!\n \"\"\" This is a GraphQL query that retrieves a list of employees.\"\"\"\n findEmployees(criteria: SearchInput): [Employee!]!\n productTypes: [Products!]!\n topSecretFederationFacts: [TopSecretFact!]! @requiresScopes(scopes: [[\"read:fact\"], [\"read:all\"]])\n factTypes: [TopSecretFactType!]\n \"\"\"Returns the value of the received HTTP header.\"\"\"\n headerValue(name: String!): String!\n \"\"\"Returns the value of the given key in the WS initial payload.\"\"\"\n initPayloadValue(key: String!): String!\n initialPayload: Map\n \"\"\"Returns response after the given delay\"\"\"\n delay(response: String!, ms: Int!): String!\n bigResponse(artificialDelay: Int! = 0, bigObjects: Int! = 100, nestedObjects: Int! = 100, deeplyNestedObjects: Int! = 100): [BigObject!]!\n longResponse(artificialDelay: Int! = 0, bytes: Int!): String\n bigAbstractResponse: BigAbstractResponse\n rootFieldWithListArg(arg: [String!]!): [String!]!\n rootFieldWithNestedListArg(arg: [[String!]!]!): [[String!]!]!\n rootFieldWithListOfInputArg(arg: [InputType!]!): [InputResponse!]!\n rootFieldWithListOfEnumArg(arg: [EnumType!]!): [EnumType!]!\n rootFieldWithInput(arg: InputArg!): String!\n floatField(arg: Float): Float\n sharedThings(numOfA: Int!, numOfB: Int!): [Thing!]!\n secret: Secret @requiresScopes(scopes: [[\"read:secret\"]])\n}\n\nscalar Upload\n\ntype Mutation {\n updateEmployeeTag(id: Int!, tag: String!): Employee\n singleUpload(file: Upload!): Boolean!\n singleUploadWithInput(arg: FileUpload!): Boolean!\n multipleUpload(files: [Upload!]!): Boolean!\n addFact(fact: TopSecretFactInput!): TopSecretFact! @requiresScopes(scopes: [[\"write:fact\"], [\"write:all\"]])\n \"\"\" This mutation updates the availability status of an employee in the system.\n \"\"\"\n updateAvailability(employeeID: Int!, isAvailable: Boolean!): Employee!\n \"\"\" This mutation update the mood of an employee. \"\"\"\n updateMood(employeeID: Int!, mood: Mood!): Employee!\n}\n\ninput FileUpload {\n nested: DeeplyNestedFileUpload\n nestedList: [Upload!]\n}\n\ninput DeeplyNestedFileUpload {\n file: Upload!\n}\n\ntype Subscription {\n \"\"\"`currentTime` will return a stream of `Time` objects.\"\"\"\n currentTime: Time!\n countEmp(max: Int!, intervalMilliseconds: Int!): Int!\n countEmp2(max: Int!, intervalMilliseconds: Int!): Int!\n countFor(count: Int!): Int!\n countHob(max: Int!, intervalMilliseconds: Int!): Int!\n \"\"\"Returns a stream with the value of the received HTTP header.\"\"\"\n headerValue(name: String!, repeat: Int): TimestampedString!\n \"\"\"\n Returns a stream with the value of value of the given key in the WS initial payload.\n \"\"\"\n initPayloadValue(key: String!, repeat: Int): TimestampedString!\n \"\"\"Returns a stream with the value of the WS initial payload.\"\"\"\n initialPayload(repeat: Int): Map\n returnsError: String!\n \"\"\"\n Returns a stream with the values of the WS initial payload and subscribe extensions\n \"\"\"\n metadata(repeat: Int! = 1): SubscribeMetadata!\n}\n\nenum Department {\n ENGINEERING\n MARKETING\n OPERATIONS\n}\n\ninterface RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n}\n\nenum EngineerType {\n BACKEND\n FRONTEND\n FULLSTACK\n}\n\ninterface Identifiable {\n id: Int!\n}\n\nenum OperationType {\n FINANCE\n HUMAN_RESOURCES\n}\n\ntype Details {\n forename: String!\n location: Country!\n surname: String!\n pastLocations: [City!]!\n middlename: String @deprecated(reason: \"No longer supported\")\n hasChildren: Boolean!\n maritalStatus: MaritalStatus\n nationality: Nationality!\n pets: [Pet]\n}\n\ntype City {\n type: String!\n name: String!\n country: Country\n}\n\ntype Country {\n key: CountryKey!\n language: String\n}\n\ntype CountryKey {\n name: String!\n}\n\nenum Mood {\n HAPPY\n SAD\n APATHETIC @inaccessible\n}\n\ntype ErrorWrapper {\n okField: String\n errorField: String\n}\n\ntype Time {\n unixTime: Int!\n timeStamp: String!\n}\n\nunion Products = Consultancy | Cosmo | SDK | Documentation\n\ninterface IProduct {\n upc: ID!\n engineers: [Employee!]!\n}\n\ntype Consultancy {\n upc: ID!\n lead: Employee!\n isLeadAvailable: Boolean\n name: ProductName!\n}\n\ninterface EmployeeWorkItem {\n name: String!\n priority: Int!\n}\n\ntype WorkItemHandler {\n name: String!\n assignedItem: EmployeeWorkItem!\n}\n\ntype TechnicalSpecs {\n name: String!\n complexity: Float!\n metrics: WorkMetrics!\n}\n\ntype ManagementSpecs {\n name: String!\n scope: Float!\n metrics: WorkMetrics!\n}\n\ntype WorkMetrics {\n score: Float!\n efficiency: Float!\n}\n\nunion WorkReviewResult = WorkApproval | WorkRejection\n\ntype WorkApproval {\n comment: String!\n approvedAt: String!\n}\n\ntype WorkRejection {\n reason: String!\n rejectionCode: String!\n}\n\ntype WorkSetup {\n priority: String!\n primaryItem: EmployeeWorkItem!\n}\n\ninput FindEmployeeCriteria @oneOf {\n id: Int\n department: Department\n title: String\n}\n\nenum Class {\n FISH\n MAMMAL\n REPTILE\n}\n\nenum Gender {\n FEMALE\n MALE\n UNKNOWN\n}\n\ninterface Animal {\n class: Class!\n gender: Gender!\n}\n\nenum CatType {\n HOME\n STREET\n}\n\nenum DogBreed {\n GOLDEN_RETRIEVER\n POODLE\n ROTTWEILER\n YORKSHIRE_TERRIER\n}\n\nenum MaritalStatus {\n ENGAGED\n MARRIED\n}\n\nenum Nationality {\n AMERICAN\n DUTCH\n ENGLISH\n GERMAN\n INDIAN\n SPANISH\n UKRAINIAN\n}\n\n\"\"\" Allows to filter employees by their details. \"\"\"\ninput SearchInput {\n hasPets: Boolean\n nationality: Nationality\n nested: NestedSearchInput\n}\n\ninput NestedSearchInput {\n maritalStatus: MaritalStatus\n hasChildren: Boolean\n}\n\nenum ExerciseType {\n CALISTHENICS\n HIKING\n SPORT\n STRENGTH_TRAINING\n}\n\ninterface Experience {\n yearsOfExperience: Float!\n}\n\nenum GameGenre {\n ADVENTURE\n BOARD\n FPS\n CARD\n RPG\n ROGUELITE\n SIMULATION\n STRATEGY\n}\n\nenum ProgrammingLanguage {\n CSHARP\n GO\n RUST\n TYPESCRIPT\n}\n\ninterface Hobby {\n employees: [Employee!]!\n}\n\ninput TopSecretFactInput {\n title: String!\n description: FactContent!\n factType: TopSecretFactType!\n}\n\nenum TopSecretFactType @authenticated {\n DIRECTIVE\n ENTITY\n MISCELLANEOUS\n}\n\ninterface TopSecretFact @authenticated {\n description: FactContent!\n factType: TopSecretFactType\n}\n\nscalar FactContent @requiresScopes(scopes: [[\"read:scalar\"], [\"read:all\"]])\n\nenum ProductName {\n CONSULTANCY\n COSMO\n ENGINE\n FINANCE\n HUMAN_RESOURCES\n MARKETING\n SDK\n}\n\ntype Documentation {\n url(product: ProductName!): String!\n urls(products: [ProductName!]!): [String!]!\n}\n\ntype Secret {\n value: String\n}\n\ntype Thing {\n b: String!\n}\n\ninput InputArg {\n enums: [EnumType!]\n enum: EnumType\n string: String\n strings: [String!]\n}\n\nenum EnumType {\n A\n B\n C\n}\n\ninput InputType {\n arg: String!\n}\n\ntype InputResponse {\n arg: String!\n}\n\nscalar Map\n\ntype TimestampedString {\n \"\"\"The value of the string.\"\"\"\n value: String!\n \"\"\"The timestamp when the response was generated.\"\"\"\n unixTime: Int!\n \"\"\"Sequence number\"\"\"\n seq: Int!\n \"\"\"Total number of responses to be sent\"\"\"\n total: Int!\n initialPayload: Map\n extensions: Map\n}\n\ntype SubscribeMetadata {\n initialPayload: Map\n subscribeExtensions: Map\n}\n\ntype BigObject {\n nestedObjects: [NestedObject!]!\n}\n\ntype NestedObject {\n deeplyNestedObjects: [DeeplyNestedObject!]!\n}\n\ntype DeeplyNestedObject {\n aFieldOnDeeplyNestedObject: String!\n bFieldOnDeeplyNestedObject: Int!\n cFieldOnDeeplyNestedObject: Boolean!\n dFieldOnDeeplyNestedObject: Float!\n eFieldOnDeeplyNestedObject: String!\n fFieldOnDeeplyNestedObject: Int!\n gFieldOnDeeplyNestedObject: Boolean!\n hFieldOnDeeplyNestedObject: Float!\n iFieldOnDeeplyNestedObject: String!\n jFieldOnDeeplyNestedObject: Int!\n kFieldOnDeeplyNestedObject: Boolean!\n lFieldOnDeeplyNestedObject: Float!\n mFieldOnDeeplyNestedObject: String!\n nFieldOnDeeplyNestedObject: Int!\n oFieldOnDeeplyNestedObject: Boolean!\n pFieldOnDeeplyNestedObject: Float!\n qFieldOnDeeplyNestedObject: String!\n rFieldOnDeeplyNestedObject: Int!\n sFieldOnDeeplyNestedObject: Boolean!\n tFieldOnDeeplyNestedObject: Float!\n uFieldOnDeeplyNestedObject: String!\n vFieldOnDeeplyNestedObject: Int!\n wFieldOnDeeplyNestedObject: Boolean!\n xFieldOnDeeplyNestedObject: Float!\n yFieldOnDeeplyNestedObject: String!\n zFieldOnDeeplyNestedObject: Int!\n}\n\nunion BigAbstractResponse = ABigObject | BBigObject | CBigObject | DBigObject | EBigObject | FBigObject | GBigObject | HBigObject | IBigObject | JBigObject | KBigObject | LBigObject | MBigObject | NBigObject | OBigObject | PBigObject | QBigObject | RBigObject | SBigObject | TBigObject | UBigObject | VBigObject | WBigObject | XBigObject | YBigObject | ZBigObject\n\ntype ABigObject {\n aFieldOnABigObject: String!\n bFieldOnABigObject: Int!\n cFieldOnABigObject: Boolean!\n dFieldOnABigObject: Float!\n eFieldOnABigObject: String!\n fFieldOnABigObject: Int!\n gFieldOnABigObject: Boolean!\n hFieldOnABigObject: Float!\n iFieldOnABigObject: String!\n jFieldOnABigObject: Int!\n kFieldOnABigObject: Boolean!\n lFieldOnABigObject: Float!\n mFieldOnABigObject: String!\n nFieldOnABigObject: Int!\n oFieldOnABigObject: Boolean!\n pFieldOnABigObject: Float!\n qFieldOnABigObject: String!\n rFieldOnABigObject: Int!\n sFieldOnABigObject: Boolean!\n tFieldOnABigObject: Float!\n uFieldOnABigObject: String!\n vFieldOnABigObject: Int!\n wFieldOnABigObject: Boolean!\n xFieldOnABigObject: Float!\n yFieldOnABigObject: String!\n zFieldOnABigObject: Int!\n}\n\ntype BBigObject {\n aFieldOnBBigObject: String!\n bFieldOnBBigObject: Int!\n cFieldOnBBigObject: Boolean!\n dFieldOnBBigObject: Float!\n eFieldOnBBigObject: String!\n fFieldOnBBigObject: Int!\n gFieldOnBBigObject: Boolean!\n hFieldOnBBigObject: Float!\n iFieldOnBBigObject: String!\n jFieldOnBBigObject: Int!\n kFieldOnBBigObject: Boolean!\n lFieldOnBBigObject: Float!\n mFieldOnBBigObject: String!\n nFieldOnBBigObject: Int!\n oFieldOnBBigObject: Boolean!\n pFieldOnBBigObject: Float!\n qFieldOnBBigObject: String!\n rFieldOnBBigObject: Int!\n sFieldOnBBigObject: Boolean!\n tFieldOnBBigObject: Float!\n uFieldOnBBigObject: String!\n vFieldOnBBigObject: Int!\n wFieldOnBBigObject: Boolean!\n xFieldOnBBigObject: Float!\n yFieldOnBBigObject: String!\n zFieldOnBBigObject: Int!\n}\n\ntype CBigObject {\n aFieldOnCBigObject: String!\n bFieldOnCBigObject: Int!\n cFieldOnCBigObject: Boolean!\n dFieldOnCBigObject: Float!\n eFieldOnCBigObject: String!\n fFieldOnCBigObject: Int!\n gFieldOnCBigObject: Boolean!\n hFieldOnCBigObject: Float!\n iFieldOnCBigObject: String!\n jFieldOnCBigObject: Int!\n kFieldOnCBigObject: Boolean!\n lFieldOnCBigObject: Float!\n mFieldOnCBigObject: String!\n nFieldOnCBigObject: Int!\n oFieldOnCBigObject: Boolean!\n pFieldOnCBigObject: Float!\n qFieldOnCBigObject: String!\n rFieldOnCBigObject: Int!\n sFieldOnCBigObject: Boolean!\n tFieldOnCBigObject: Float!\n uFieldOnCBigObject: String!\n vFieldOnCBigObject: Int!\n wFieldOnCBigObject: Boolean!\n xFieldOnCBigObject: Float!\n yFieldOnCBigObject: String!\n zFieldOnCBigObject: Int!\n}\n\ntype DBigObject {\n aFieldOnDBigObject: String!\n bFieldOnDBigObject: Int!\n cFieldOnDBigObject: Boolean!\n dFieldOnDBigObject: Float!\n eFieldOnDBigObject: String!\n fFieldOnDBigObject: Int!\n gFieldOnDBigObject: Boolean!\n hFieldOnDBigObject: Float!\n iFieldOnDBigObject: String!\n jFieldOnDBigObject: Int!\n kFieldOnDBigObject: Boolean!\n lFieldOnDBigObject: Float!\n mFieldOnDBigObject: String!\n nFieldOnDBigObject: Int!\n oFieldOnDBigObject: Boolean!\n pFieldOnDBigObject: Float!\n qFieldOnDBigObject: String!\n rFieldOnDBigObject: Int!\n sFieldOnDBigObject: Boolean!\n tFieldOnDBigObject: Float!\n uFieldOnDBigObject: String!\n vFieldOnDBigObject: Int!\n wFieldOnDBigObject: Boolean!\n xFieldOnDBigObject: Float!\n yFieldOnDBigObject: String!\n zFieldOnDBigObject: Int!\n}\n\ntype EBigObject {\n aFieldOnEBigObject: String!\n bFieldOnEBigObject: Int!\n cFieldOnEBigObject: Boolean!\n dFieldOnEBigObject: Float!\n eFieldOnEBigObject: String!\n fFieldOnEBigObject: Int!\n gFieldOnEBigObject: Boolean!\n hFieldOnEBigObject: Float!\n iFieldOnEBigObject: String!\n jFieldOnEBigObject: Int!\n kFieldOnEBigObject: Boolean!\n lFieldOnEBigObject: Float!\n mFieldOnEBigObject: String!\n nFieldOnEBigObject: Int!\n oFieldOnEBigObject: Boolean!\n pFieldOnEBigObject: Float!\n qFieldOnEBigObject: String!\n rFieldOnEBigObject: Int!\n sFieldOnEBigObject: Boolean!\n tFieldOnEBigObject: Float!\n uFieldOnEBigObject: String!\n vFieldOnEBigObject: Int!\n wFieldOnEBigObject: Boolean!\n xFieldOnEBigObject: Float!\n yFieldOnEBigObject: String!\n zFieldOnEBigObject: Int!\n}\n\ntype FBigObject {\n aFieldOnFBigObject: String!\n bFieldOnFBigObject: Int!\n cFieldOnFBigObject: Boolean!\n dFieldOnFBigObject: Float!\n eFieldOnFBigObject: String!\n fFieldOnFBigObject: Int!\n gFieldOnFBigObject: Boolean!\n hFieldOnFBigObject: Float!\n iFieldOnFBigObject: String!\n jFieldOnFBigObject: Int!\n kFieldOnFBigObject: Boolean!\n lFieldOnFBigObject: Float!\n mFieldOnFBigObject: String!\n nFieldOnFBigObject: Int!\n oFieldOnFBigObject: Boolean!\n pFieldOnFBigObject: Float!\n qFieldOnFBigObject: String!\n rFieldOnFBigObject: Int!\n sFieldOnFBigObject: Boolean!\n tFieldOnFBigObject: Float!\n uFieldOnFBigObject: String!\n vFieldOnFBigObject: Int!\n wFieldOnFBigObject: Boolean!\n xFieldOnFBigObject: Float!\n yFieldOnFBigObject: String!\n zFieldOnFBigObject: Int!\n}\n\ntype GBigObject {\n aFieldOnGBigObject: String!\n bFieldOnGBigObject: Int!\n cFieldOnGBigObject: Boolean!\n dFieldOnGBigObject: Float!\n eFieldOnGBigObject: String!\n fFieldOnGBigObject: Int!\n gFieldOnGBigObject: Boolean!\n hFieldOnGBigObject: Float!\n iFieldOnGBigObject: String!\n jFieldOnGBigObject: Int!\n kFieldOnGBigObject: Boolean!\n lFieldOnGBigObject: Float!\n mFieldOnGBigObject: String!\n nFieldOnGBigObject: Int!\n oFieldOnGBigObject: Boolean!\n pFieldOnGBigObject: Float!\n qFieldOnGBigObject: String!\n rFieldOnGBigObject: Int!\n sFieldOnGBigObject: Boolean!\n tFieldOnGBigObject: Float!\n uFieldOnGBigObject: String!\n vFieldOnGBigObject: Int!\n wFieldOnGBigObject: Boolean!\n xFieldOnGBigObject: Float!\n yFieldOnGBigObject: String!\n zFieldOnGBigObject: Int!\n}\n\ntype HBigObject {\n aFieldOnHBigObject: String!\n bFieldOnHBigObject: Int!\n cFieldOnHBigObject: Boolean!\n dFieldOnHBigObject: Float!\n eFieldOnHBigObject: String!\n fFieldOnHBigObject: Int!\n gFieldOnHBigObject: Boolean!\n hFieldOnHBigObject: Float!\n iFieldOnHBigObject: String!\n jFieldOnHBigObject: Int!\n kFieldOnHBigObject: Boolean!\n lFieldOnHBigObject: Float!\n mFieldOnHBigObject: String!\n nFieldOnHBigObject: Int!\n oFieldOnHBigObject: Boolean!\n pFieldOnHBigObject: Float!\n qFieldOnHBigObject: String!\n rFieldOnHBigObject: Int!\n sFieldOnHBigObject: Boolean!\n tFieldOnHBigObject: Float!\n uFieldOnHBigObject: String!\n vFieldOnHBigObject: Int!\n wFieldOnHBigObject: Boolean!\n xFieldOnHBigObject: Float!\n yFieldOnHBigObject: String!\n zFieldOnHBigObject: Int!\n}\n\ntype IBigObject {\n aFieldOnIBigObject: String!\n bFieldOnIBigObject: Int!\n cFieldOnIBigObject: Boolean!\n dFieldOnIBigObject: Float!\n eFieldOnIBigObject: String!\n fFieldOnIBigObject: Int!\n gFieldOnIBigObject: Boolean!\n hFieldOnIBigObject: Float!\n iFieldOnIBigObject: String!\n jFieldOnIBigObject: Int!\n kFieldOnIBigObject: Boolean!\n lFieldOnIBigObject: Float!\n mFieldOnIBigObject: String!\n nFieldOnIBigObject: Int!\n oFieldOnIBigObject: Boolean!\n pFieldOnIBigObject: Float!\n qFieldOnIBigObject: String!\n rFieldOnIBigObject: Int!\n sFieldOnIBigObject: Boolean!\n tFieldOnIBigObject: Float!\n uFieldOnIBigObject: String!\n vFieldOnIBigObject: Int!\n wFieldOnIBigObject: Boolean!\n xFieldOnIBigObject: Float!\n yFieldOnIBigObject: String!\n zFieldOnIBigObject: Int!\n}\n\ntype JBigObject {\n aFieldOnJBigObject: String!\n bFieldOnJBigObject: Int!\n cFieldOnJBigObject: Boolean!\n dFieldOnJBigObject: Float!\n eFieldOnJBigObject: String!\n fFieldOnJBigObject: Int!\n gFieldOnJBigObject: Boolean!\n hFieldOnJBigObject: Float!\n iFieldOnJBigObject: String!\n jFieldOnJBigObject: Int!\n kFieldOnJBigObject: Boolean!\n lFieldOnJBigObject: Float!\n mFieldOnJBigObject: String!\n nFieldOnJBigObject: Int!\n oFieldOnJBigObject: Boolean!\n pFieldOnJBigObject: Float!\n qFieldOnJBigObject: String!\n rFieldOnJBigObject: Int!\n sFieldOnJBigObject: Boolean!\n tFieldOnJBigObject: Float!\n uFieldOnJBigObject: String!\n vFieldOnJBigObject: Int!\n wFieldOnJBigObject: Boolean!\n xFieldOnJBigObject: Float!\n yFieldOnJBigObject: String!\n zFieldOnJBigObject: Int!\n}\n\ntype KBigObject {\n aFieldOnKBigObject: String!\n bFieldOnKBigObject: Int!\n cFieldOnKBigObject: Boolean!\n dFieldOnKBigObject: Float!\n eFieldOnKBigObject: String!\n fFieldOnKBigObject: Int!\n gFieldOnKBigObject: Boolean!\n hFieldOnKBigObject: Float!\n iFieldOnKBigObject: String!\n jFieldOnKBigObject: Int!\n kFieldOnKBigObject: Boolean!\n lFieldOnKBigObject: Float!\n mFieldOnKBigObject: String!\n nFieldOnKBigObject: Int!\n oFieldOnKBigObject: Boolean!\n pFieldOnKBigObject: Float!\n qFieldOnKBigObject: String!\n rFieldOnKBigObject: Int!\n sFieldOnKBigObject: Boolean!\n tFieldOnKBigObject: Float!\n uFieldOnKBigObject: String!\n vFieldOnKBigObject: Int!\n wFieldOnKBigObject: Boolean!\n xFieldOnKBigObject: Float!\n yFieldOnKBigObject: String!\n zFieldOnKBigObject: Int!\n}\n\ntype LBigObject {\n aFieldOnLBigObject: String!\n bFieldOnLBigObject: Int!\n cFieldOnLBigObject: Boolean!\n dFieldOnLBigObject: Float!\n eFieldOnLBigObject: String!\n fFieldOnLBigObject: Int!\n gFieldOnLBigObject: Boolean!\n hFieldOnLBigObject: Float!\n iFieldOnLBigObject: String!\n jFieldOnLBigObject: Int!\n kFieldOnLBigObject: Boolean!\n lFieldOnLBigObject: Float!\n mFieldOnLBigObject: String!\n nFieldOnLBigObject: Int!\n oFieldOnLBigObject: Boolean!\n pFieldOnLBigObject: Float!\n qFieldOnLBigObject: String!\n rFieldOnLBigObject: Int!\n sFieldOnLBigObject: Boolean!\n tFieldOnLBigObject: Float!\n uFieldOnLBigObject: String!\n vFieldOnLBigObject: Int!\n wFieldOnLBigObject: Boolean!\n xFieldOnLBigObject: Float!\n yFieldOnLBigObject: String!\n zFieldOnLBigObject: Int!\n}\n\ntype MBigObject {\n aFieldOnMBigObject: String!\n bFieldOnMBigObject: Int!\n cFieldOnMBigObject: Boolean!\n dFieldOnMBigObject: Float!\n eFieldOnMBigObject: String!\n fFieldOnMBigObject: Int!\n gFieldOnMBigObject: Boolean!\n hFieldOnMBigObject: Float!\n iFieldOnMBigObject: String!\n jFieldOnMBigObject: Int!\n kFieldOnMBigObject: Boolean!\n lFieldOnMBigObject: Float!\n mFieldOnMBigObject: String!\n nFieldOnMBigObject: Int!\n oFieldOnMBigObject: Boolean!\n pFieldOnMBigObject: Float!\n qFieldOnMBigObject: String!\n rFieldOnMBigObject: Int!\n sFieldOnMBigObject: Boolean!\n tFieldOnMBigObject: Float!\n uFieldOnMBigObject: String!\n vFieldOnMBigObject: Int!\n wFieldOnMBigObject: Boolean!\n xFieldOnMBigObject: Float!\n yFieldOnMBigObject: String!\n zFieldOnMBigObject: Int!\n}\n\ntype NBigObject {\n aFieldOnNBigObject: String!\n bFieldOnNBigObject: Int!\n cFieldOnNBigObject: Boolean!\n dFieldOnNBigObject: Float!\n eFieldOnNBigObject: String!\n fFieldOnNBigObject: Int!\n gFieldOnNBigObject: Boolean!\n hFieldOnNBigObject: Float!\n iFieldOnNBigObject: String!\n jFieldOnNBigObject: Int!\n kFieldOnNBigObject: Boolean!\n lFieldOnNBigObject: Float!\n mFieldOnNBigObject: String!\n nFieldOnNBigObject: Int!\n oFieldOnNBigObject: Boolean!\n pFieldOnNBigObject: Float!\n qFieldOnNBigObject: String!\n rFieldOnNBigObject: Int!\n sFieldOnNBigObject: Boolean!\n tFieldOnNBigObject: Float!\n uFieldOnNBigObject: String!\n vFieldOnNBigObject: Int!\n wFieldOnNBigObject: Boolean!\n xFieldOnNBigObject: Float!\n yFieldOnNBigObject: String!\n zFieldOnNBigObject: Int!\n}\n\ntype OBigObject {\n aFieldOnOBigObject: String!\n bFieldOnOBigObject: Int!\n cFieldOnOBigObject: Boolean!\n dFieldOnOBigObject: Float!\n eFieldOnOBigObject: String!\n fFieldOnOBigObject: Int!\n gFieldOnOBigObject: Boolean!\n hFieldOnOBigObject: Float!\n iFieldOnOBigObject: String!\n jFieldOnOBigObject: Int!\n kFieldOnOBigObject: Boolean!\n lFieldOnOBigObject: Float!\n mFieldOnOBigObject: String!\n nFieldOnOBigObject: Int!\n oFieldOnOBigObject: Boolean!\n pFieldOnOBigObject: Float!\n qFieldOnOBigObject: String!\n rFieldOnOBigObject: Int!\n sFieldOnOBigObject: Boolean!\n tFieldOnOBigObject: Float!\n uFieldOnOBigObject: String!\n vFieldOnOBigObject: Int!\n wFieldOnOBigObject: Boolean!\n xFieldOnOBigObject: Float!\n yFieldOnOBigObject: String!\n zFieldOnOBigObject: Int!\n}\n\ntype PBigObject {\n aFieldOnPBigObject: String!\n bFieldOnPBigObject: Int!\n cFieldOnPBigObject: Boolean!\n dFieldOnPBigObject: Float!\n eFieldOnPBigObject: String!\n fFieldOnPBigObject: Int!\n gFieldOnPBigObject: Boolean!\n hFieldOnPBigObject: Float!\n iFieldOnPBigObject: String!\n jFieldOnPBigObject: Int!\n kFieldOnPBigObject: Boolean!\n lFieldOnPBigObject: Float!\n mFieldOnPBigObject: String!\n nFieldOnPBigObject: Int!\n oFieldOnPBigObject: Boolean!\n pFieldOnPBigObject: Float!\n qFieldOnPBigObject: String!\n rFieldOnPBigObject: Int!\n sFieldOnPBigObject: Boolean!\n tFieldOnPBigObject: Float!\n uFieldOnPBigObject: String!\n vFieldOnPBigObject: Int!\n wFieldOnPBigObject: Boolean!\n xFieldOnPBigObject: Float!\n yFieldOnPBigObject: String!\n zFieldOnPBigObject: Int!\n}\n\ntype QBigObject {\n aFieldOnQBigObject: String!\n bFieldOnQBigObject: Int!\n cFieldOnQBigObject: Boolean!\n dFieldOnQBigObject: Float!\n eFieldOnQBigObject: String!\n fFieldOnQBigObject: Int!\n gFieldOnQBigObject: Boolean!\n hFieldOnQBigObject: Float!\n iFieldOnQBigObject: String!\n jFieldOnQBigObject: Int!\n kFieldOnQBigObject: Boolean!\n lFieldOnQBigObject: Float!\n mFieldOnQBigObject: String!\n nFieldOnQBigObject: Int!\n oFieldOnQBigObject: Boolean!\n pFieldOnQBigObject: Float!\n qFieldOnQBigObject: String!\n rFieldOnQBigObject: Int!\n sFieldOnQBigObject: Boolean!\n tFieldOnQBigObject: Float!\n uFieldOnQBigObject: String!\n vFieldOnQBigObject: Int!\n wFieldOnQBigObject: Boolean!\n xFieldOnQBigObject: Float!\n yFieldOnQBigObject: String!\n zFieldOnQBigObject: Int!\n}\n\ntype RBigObject {\n aFieldOnRBigObject: String!\n bFieldOnRBigObject: Int!\n cFieldOnRBigObject: Boolean!\n dFieldOnRBigObject: Float!\n eFieldOnRBigObject: String!\n fFieldOnRBigObject: Int!\n gFieldOnRBigObject: Boolean!\n hFieldOnRBigObject: Float!\n iFieldOnRBigObject: String!\n jFieldOnRBigObject: Int!\n kFieldOnRBigObject: Boolean!\n lFieldOnRBigObject: Float!\n mFieldOnRBigObject: String!\n nFieldOnRBigObject: Int!\n oFieldOnRBigObject: Boolean!\n pFieldOnRBigObject: Float!\n qFieldOnRBigObject: String!\n rFieldOnRBigObject: Int!\n sFieldOnRBigObject: Boolean!\n tFieldOnRBigObject: Float!\n uFieldOnRBigObject: String!\n vFieldOnRBigObject: Int!\n wFieldOnRBigObject: Boolean!\n xFieldOnRBigObject: Float!\n yFieldOnRBigObject: String!\n zFieldOnRBigObject: Int!\n}\n\ntype SBigObject {\n aFieldOnSBigObject: String!\n bFieldOnSBigObject: Int!\n cFieldOnSBigObject: Boolean!\n dFieldOnSBigObject: Float!\n eFieldOnSBigObject: String!\n fFieldOnSBigObject: Int!\n gFieldOnSBigObject: Boolean!\n hFieldOnSBigObject: Float!\n iFieldOnSBigObject: String!\n jFieldOnSBigObject: Int!\n kFieldOnSBigObject: Boolean!\n lFieldOnSBigObject: Float!\n mFieldOnSBigObject: String!\n nFieldOnSBigObject: Int!\n oFieldOnSBigObject: Boolean!\n pFieldOnSBigObject: Float!\n qFieldOnSBigObject: String!\n rFieldOnSBigObject: Int!\n sFieldOnSBigObject: Boolean!\n tFieldOnSBigObject: Float!\n uFieldOnSBigObject: String!\n vFieldOnSBigObject: Int!\n wFieldOnSBigObject: Boolean!\n xFieldOnSBigObject: Float!\n yFieldOnSBigObject: String!\n zFieldOnSBigObject: Int!\n}\n\ntype TBigObject {\n aFieldOnTBigObject: String!\n bFieldOnTBigObject: Int!\n cFieldOnTBigObject: Boolean!\n dFieldOnTBigObject: Float!\n eFieldOnTBigObject: String!\n fFieldOnTBigObject: Int!\n gFieldOnTBigObject: Boolean!\n hFieldOnTBigObject: Float!\n iFieldOnTBigObject: String!\n jFieldOnTBigObject: Int!\n kFieldOnTBigObject: Boolean!\n lFieldOnTBigObject: Float!\n mFieldOnTBigObject: String!\n nFieldOnTBigObject: Int!\n oFieldOnTBigObject: Boolean!\n pFieldOnTBigObject: Float!\n qFieldOnTBigObject: String!\n rFieldOnTBigObject: Int!\n sFieldOnTBigObject: Boolean!\n tFieldOnTBigObject: Float!\n uFieldOnTBigObject: String!\n vFieldOnTBigObject: Int!\n wFieldOnTBigObject: Boolean!\n xFieldOnTBigObject: Float!\n yFieldOnTBigObject: String!\n zFieldOnTBigObject: Int!\n}\n\ntype UBigObject {\n aFieldOnUBigObject: String!\n bFieldOnUBigObject: Int!\n cFieldOnUBigObject: Boolean!\n dFieldOnUBigObject: Float!\n eFieldOnUBigObject: String!\n fFieldOnUBigObject: Int!\n gFieldOnUBigObject: Boolean!\n hFieldOnUBigObject: Float!\n iFieldOnUBigObject: String!\n jFieldOnUBigObject: Int!\n kFieldOnUBigObject: Boolean!\n lFieldOnUBigObject: Float!\n mFieldOnUBigObject: String!\n nFieldOnUBigObject: Int!\n oFieldOnUBigObject: Boolean!\n pFieldOnUBigObject: Float!\n qFieldOnUBigObject: String!\n rFieldOnUBigObject: Int!\n sFieldOnUBigObject: Boolean!\n tFieldOnUBigObject: Float!\n uFieldOnUBigObject: String!\n vFieldOnUBigObject: Int!\n wFieldOnUBigObject: Boolean!\n xFieldOnUBigObject: Float!\n yFieldOnUBigObject: String!\n zFieldOnUBigObject: Int!\n}\n\ntype VBigObject {\n aFieldOnVBigObject: String!\n bFieldOnVBigObject: Int!\n cFieldOnVBigObject: Boolean!\n dFieldOnVBigObject: Float!\n eFieldOnVBigObject: String!\n fFieldOnVBigObject: Int!\n gFieldOnVBigObject: Boolean!\n hFieldOnVBigObject: Float!\n iFieldOnVBigObject: String!\n jFieldOnVBigObject: Int!\n kFieldOnVBigObject: Boolean!\n lFieldOnVBigObject: Float!\n mFieldOnVBigObject: String!\n nFieldOnVBigObject: Int!\n oFieldOnVBigObject: Boolean!\n pFieldOnVBigObject: Float!\n qFieldOnVBigObject: String!\n rFieldOnVBigObject: Int!\n sFieldOnVBigObject: Boolean!\n tFieldOnVBigObject: Float!\n uFieldOnVBigObject: String!\n vFieldOnVBigObject: Int!\n wFieldOnVBigObject: Boolean!\n xFieldOnVBigObject: Float!\n yFieldOnVBigObject: String!\n zFieldOnVBigObject: Int!\n}\n\ntype WBigObject {\n aFieldOnWBigObject: String!\n bFieldOnWBigObject: Int!\n cFieldOnWBigObject: Boolean!\n dFieldOnWBigObject: Float!\n eFieldOnWBigObject: String!\n fFieldOnWBigObject: Int!\n gFieldOnWBigObject: Boolean!\n hFieldOnWBigObject: Float!\n iFieldOnWBigObject: String!\n jFieldOnWBigObject: Int!\n kFieldOnWBigObject: Boolean!\n lFieldOnWBigObject: Float!\n mFieldOnWBigObject: String!\n nFieldOnWBigObject: Int!\n oFieldOnWBigObject: Boolean!\n pFieldOnWBigObject: Float!\n qFieldOnWBigObject: String!\n rFieldOnWBigObject: Int!\n sFieldOnWBigObject: Boolean!\n tFieldOnWBigObject: Float!\n uFieldOnWBigObject: String!\n vFieldOnWBigObject: Int!\n wFieldOnWBigObject: Boolean!\n xFieldOnWBigObject: Float!\n yFieldOnWBigObject: String!\n zFieldOnWBigObject: Int!\n}\n\ntype XBigObject {\n aFieldOnXBigObject: String!\n bFieldOnXBigObject: Int!\n cFieldOnXBigObject: Boolean!\n dFieldOnXBigObject: Float!\n eFieldOnXBigObject: String!\n fFieldOnXBigObject: Int!\n gFieldOnXBigObject: Boolean!\n hFieldOnXBigObject: Float!\n iFieldOnXBigObject: String!\n jFieldOnXBigObject: Int!\n kFieldOnXBigObject: Boolean!\n lFieldOnXBigObject: Float!\n mFieldOnXBigObject: String!\n nFieldOnXBigObject: Int!\n oFieldOnXBigObject: Boolean!\n pFieldOnXBigObject: Float!\n qFieldOnXBigObject: String!\n rFieldOnXBigObject: Int!\n sFieldOnXBigObject: Boolean!\n tFieldOnXBigObject: Float!\n uFieldOnXBigObject: String!\n vFieldOnXBigObject: Int!\n wFieldOnXBigObject: Boolean!\n xFieldOnXBigObject: Float!\n yFieldOnXBigObject: String!\n zFieldOnXBigObject: Int!\n}\n\ntype YBigObject {\n aFieldOnYBigObject: String!\n bFieldOnYBigObject: Int!\n cFieldOnYBigObject: Boolean!\n dFieldOnYBigObject: Float!\n eFieldOnYBigObject: String!\n fFieldOnYBigObject: Int!\n gFieldOnYBigObject: Boolean!\n hFieldOnYBigObject: Float!\n iFieldOnYBigObject: String!\n jFieldOnYBigObject: Int!\n kFieldOnYBigObject: Boolean!\n lFieldOnYBigObject: Float!\n mFieldOnYBigObject: String!\n nFieldOnYBigObject: Int!\n oFieldOnYBigObject: Boolean!\n pFieldOnYBigObject: Float!\n qFieldOnYBigObject: String!\n rFieldOnYBigObject: Int!\n sFieldOnYBigObject: Boolean!\n tFieldOnYBigObject: Float!\n uFieldOnYBigObject: String!\n vFieldOnYBigObject: Int!\n wFieldOnYBigObject: Boolean!\n xFieldOnYBigObject: Float!\n yFieldOnYBigObject: String!\n zFieldOnYBigObject: Int!\n}\n\ntype ZBigObject {\n aFieldOnZBigObject: String!\n bFieldOnZBigObject: Int!\n cFieldOnZBigObject: Boolean!\n dFieldOnZBigObject: Float!\n eFieldOnZBigObject: String!\n fFieldOnZBigObject: Int!\n gFieldOnZBigObject: Boolean!\n hFieldOnZBigObject: Float!\n iFieldOnZBigObject: String!\n jFieldOnZBigObject: Int!\n kFieldOnZBigObject: Boolean!\n lFieldOnZBigObject: Float!\n mFieldOnZBigObject: String!\n nFieldOnZBigObject: Int!\n oFieldOnZBigObject: Boolean!\n pFieldOnZBigObject: Float!\n qFieldOnZBigObject: String!\n rFieldOnZBigObject: Int!\n sFieldOnZBigObject: Boolean!\n tFieldOnZBigObject: Float!\n uFieldOnZBigObject: String!\n vFieldOnZBigObject: Int!\n wFieldOnZBigObject: Boolean!\n xFieldOnZBigObject: Float!\n yFieldOnZBigObject: String!\n zFieldOnZBigObject: Int!\n}\n\ntype Engineer implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n engineerType: EngineerType!\n}\n\ntype Marketer implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n}\n\ntype Operator implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n operatorType: [OperationType!]!\n}\n\ntype Employee implements Identifiable {\n details: Details\n id: Int!\n tag: String!\n expertise: String!\n role: RoleType!\n notes: String\n updatedAt: String!\n startDate: String! @requiresScopes(scopes: [[\"read:employee\", \"read:private\"], [\"read:all\"]])\n currentMood: Mood!\n derivedMood: Mood!\n isAvailable: Boolean\n rootFieldThrowsError: String\n rootFieldErrorWrapper: ErrorWrapper\n primaryWorkItem: EmployeeWorkItem\n lastWorkReview: WorkReviewResult\n workSetup: WorkSetup\n hobbies: [Hobby!]\n products: [ProductName!]!\n productCount: Int!\n fieldThrowsError: String\n}\n\ntype Cosmo implements IProduct {\n upc: ID!\n engineers: [Employee!]!\n lead: Employee!\n isLeadAvailable: Boolean\n name: ProductName!\n repositoryURL: String!\n}\n\ntype SDK implements IProduct {\n upc: ID!\n engineers: [Employee!]!\n owner: Employee!\n unicode: String!\n clientLanguages: [ProgrammingLanguage!]!\n}\n\ntype TechnicalWorkItem implements EmployeeWorkItem {\n name: String!\n priority: Int!\n codeCount: Int!\n handler: WorkItemHandler!\n specs: TechnicalSpecs!\n}\n\ntype ManagementWorkItem implements EmployeeWorkItem {\n name: String!\n priority: Int!\n teamSize: String!\n handler: WorkItemHandler!\n specs: ManagementSpecs!\n}\n\ninterface Pet implements Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Alligator implements Pet & Animal {\n class: Class!\n dangerous: String!\n gender: Gender!\n name: String!\n}\n\ntype Cat implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n type: CatType!\n}\n\ntype Dog implements Pet & Animal {\n breed: DogBreed!\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Mouse implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Pony implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Exercise implements Hobby {\n employees: [Employee!]!\n category: ExerciseType!\n}\n\ntype Flying implements Experience & Hobby {\n employees: [Employee!]!\n planeModels: [String!]!\n yearsOfExperience: Float!\n}\n\ntype Gaming implements Experience & Hobby {\n employees: [Employee!]!\n genres: [GameGenre!]!\n name: String!\n yearsOfExperience: Float!\n}\n\ntype Other implements Hobby {\n employees: [Employee!]!\n name: String!\n}\n\ntype Programming implements Hobby {\n employees: [Employee!]!\n languages: [ProgrammingLanguage!]!\n}\n\ntype Travelling implements Hobby {\n employees: [Employee!]!\n countriesLived: [Country!]!\n}\n\ntype DirectiveFact implements TopSecretFact @authenticated {\n title: String!\n description: FactContent!\n factType: TopSecretFactType\n}\n\ntype EntityFact implements TopSecretFact @requiresScopes(scopes: [[\"read:entity\"]]) {\n title: String!\n description: FactContent!\n factType: TopSecretFactType\n}\n\ntype MiscellaneousFact implements TopSecretFact {\n title: String!\n description: FactContent! @requiresScopes(scopes: [[\"read:miscellaneous\"]])\n factType: TopSecretFactType\n}",
"stringStorage": {
"221e61d62e6d082d089288aefc5a14bcd3719bb0": "schema {\n query: Query\n mutation: Mutation\n subscription: Subscription\n}\n\ndirective @cost(weight: Int!) on ARGUMENT_DEFINITION | ENUM | FIELD_DEFINITION | INPUT_FIELD_DEFINITION | OBJECT | SCALAR\n\ndirective @expensiveOp(coefficient: Int = 2 @cost(weight: 22)) on FIELD_DEFINITION\n\ndirective @external on FIELD_DEFINITION | OBJECT\n\ndirective @goField(forceResolver: Boolean, name: String, omittable: Boolean) on FIELD_DEFINITION | INPUT_FIELD_DEFINITION\n\ndirective @key(fields: openfed__FieldSet!, resolvable: Boolean = true) repeatable on INTERFACE | OBJECT\n\ndirective @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA\n\ndirective @listSize(assumedSize: Int, requireOneSlicingArgument: Boolean = true, sizedFields: [String!], slicingArguments: [String!]) on FIELD_DEFINITION\n\ndirective @openfed__requireFetchReasons repeatable on FIELD_DEFINITION | INTERFACE | OBJECT\n\ndirective @requires(fields: openfed__FieldSet!) on FIELD_DEFINITION\n\ndirective @requiresScopes(scopes: [[openfed__Scope!]!]!) on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR\n\ndirective @shareable repeatable on FIELD_DEFINITION | OBJECT\n\ndirective @tag(name: String!) repeatable on ARGUMENT_DEFINITION | ENUM | ENUM_VALUE | FIELD_DEFINITION | INPUT_FIELD_DEFINITION | INPUT_OBJECT | INTERFACE | OBJECT | SCALAR | UNION\n\ntype City {\n country: Country\n name: String!\n type: String!\n}\n\ntype Consultancy @key(fields: \"upc\") {\n isLeadAvailable: Boolean @requires(fields: \"lead { isAvailable }\")\n lead: Employee!\n upc: ID!\n}\n\ntype Cosmo implements IProduct @key(fields: \"upc\") @cost(weight: 5) {\n engineers: [Employee!]!\n isLeadAvailable: Boolean @requires(fields: \"lead { isAvailable }\")\n lead: Employee!\n upc: ID!\n}\n\ntype Country @key(fields: \"key { name }\", resolvable: false) {\n key: CountryKey!\n}\n\ntype CountryKey {\n name: String!\n}\n\ninput DeeplyNestedFileUpload {\n file: Upload!\n}\n\nenum Department @cost(weight: 1) {\n ENGINEERING\n MARKETING\n OPERATIONS\n}\n\ntype Details {\n forename: String! @shareable\n location: Country!\n pastLocations: [City!]!\n surname: String! @shareable\n}\n\ntype Employee implements Identifiable @key(fields: \"id\") {\n currentMood: Mood! @external\n derivedMood: Mood! @requires(fields: \"currentMood\")\n details: Details! @shareable\n expertise: String!\n id: Int!\n isAvailable: Boolean @external\n lastWorkReview: WorkReviewResult\n notes: String @shareable\n primaryWorkItem: EmployeeWorkItem\n role: RoleType! @listSize(assumedSize: 3, sizedFields: [\"departments\"])\n rootFieldErrorWrapper: ErrorWrapper @goField(forceResolver: true)\n rootFieldThrowsError: String @goField(forceResolver: true)\n startDate: String! @requiresScopes(scopes: [[\"read:employee\", \"read:private\"], [\"read:all\"]])\n tag: String!\n updatedAt: String!\n workSetup: WorkSetup\n}\n\ninterface EmployeeWorkItem {\n name: String!\n priority: Int!\n}\n\ntype Engineer implements RoleType {\n departments: [Department!]!\n employees: [Employee!]! @goField(forceResolver: true) @expensiveOp\n engineerType: EngineerType!\n title: [String!]!\n}\n\nenum EngineerType {\n BACKEND\n FRONTEND\n FULLSTACK\n}\n\ntype ErrorWrapper {\n errorField: String @goField(forceResolver: true)\n okField: String\n}\n\ninput FileUpload {\n nested: DeeplyNestedFileUpload\n nestedList: [Upload!]\n}\n\ninput FindEmployeeCriteria @oneOf {\n department: Department @cost(weight: 17)\n id: Int\n title: String @cost(weight: -3)\n}\n\ninterface IProduct {\n engineers: [Employee!]!\n upc: ID!\n}\n\ninterface Identifiable {\n id: Int! @openfed__requireFetchReasons\n}\n\ntype ManagementSpecs {\n metrics: WorkMetrics! @shareable\n name: String! @shareable\n scope: Float! @shareable\n}\n\ntype ManagementWorkItem implements EmployeeWorkItem {\n handler: WorkItemHandler! @shareable\n name: String! @shareable\n priority: Int! @shareable\n specs: ManagementSpecs! @shareable\n teamSize: String! @shareable\n}\n\ntype Marketer implements RoleType {\n departments: [Department!]!\n employees: [Employee!]! @goField(forceResolver: true) @expensiveOp\n title: [String!]!\n}\n\nenum Mood {\n HAPPY\n SAD\n}\n\ntype Mutation {\n multipleUpload(files: [Upload!]!): Boolean!\n singleUpload(file: Upload!): Boolean!\n singleUploadWithInput(arg: FileUpload!): Boolean!\n updateEmployeeTag(id: Int!, tag: String!): Employee\n}\n\nenum OperationType {\n FINANCE\n HUMAN_RESOURCES\n}\n\ntype Operator implements RoleType {\n departments: [Department!]!\n employees: [Employee!]! @goField(forceResolver: true) @expensiveOp\n operatorType: [OperationType!]!\n title: [String!]!\n}\n\nunion Products = Consultancy | Cosmo | SDK\n\ntype Query {\n employee(id: Int! @cost(weight: 2)): Employee @cost(weight: 5) @openfed__requireFetchReasons\n employeeAsList(id: Int!): [Employee]\n employees: [Employee] @listSize(assumedSize: 50)\n findEmployeesBy(criteria: FindEmployeeCriteria!): [Employee!]! @expensiveOp(coefficient: null)\n firstEmployee: Employee! @tag(name: \"internal\")\n products: [Products!]!\n teammates(team: Department!): [Employee!]!\n}\n\ninterface RoleType {\n departments: [Department!]!\n employees: [Employee!]! @goField(forceResolver: true)\n title: [String!]!\n}\n\ntype SDK implements IProduct @key(fields: \"upc\") {\n engineers: [Employee!]!\n owner: Employee!\n unicode: String!\n upc: ID!\n}\n\ntype Subscription {\n countEmp(intervalMilliseconds: Int!, max: Int!): Int!\n countEmp2(intervalMilliseconds: Int!, max: Int!): Int!\n countFor(count: Int!): Int!\n \"\"\"`currentTime` will return a stream of `Time` objects.\"\"\"\n currentTime: Time!\n}\n\ntype TechnicalSpecs {\n complexity: Float! @shareable\n metrics: WorkMetrics! @shareable\n name: String! @shareable\n}\n\ntype TechnicalWorkItem implements EmployeeWorkItem {\n codeCount: Int! @shareable\n handler: WorkItemHandler! @shareable\n name: String! @shareable\n priority: Int! @shareable\n specs: TechnicalSpecs! @shareable\n}\n\ntype Time {\n timeStamp: String!\n unixTime: Int!\n}\n\nscalar Upload\n\ntype WorkApproval {\n approvedAt: String! @shareable\n comment: String! @shareable\n}\n\ntype WorkItemHandler {\n assignedItem: EmployeeWorkItem! @shareable\n name: String! @shareable\n}\n\ntype WorkMetrics {\n efficiency: Float! @shareable\n score: Float! @shareable\n}\n\ntype WorkRejection {\n reason: String! @shareable\n rejectionCode: String! @shareable\n}\n\nunion WorkReviewResult = WorkApproval | WorkRejection\n\ntype WorkSetup {\n primaryItem: EmployeeWorkItem! @shareable\n priority: String! @shareable\n}\n\nscalar link__Import\n\nenum link__Purpose {\n EXECUTION\n SECURITY\n}\n\nscalar openfed__FieldSet\n\nscalar openfed__Scope",
"2265a44afac63dcf9da5f7ee5ff35c7a6dc8adff": "schema {\n query: Query\n}\n\ndirective @key(fields: openfed__FieldSet!, resolvable: Boolean = true) repeatable on INTERFACE | OBJECT\n\ndirective @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA\n\ndirective @shareable repeatable on FIELD_DEFINITION | OBJECT\n\ntype Alligator implements Animal & Pet {\n class: Class!\n dangerous: String!\n gender: Gender!\n name: String!\n}\n\ninterface Animal {\n class: Class!\n gender: Gender!\n}\n\ntype Cat implements Animal & Pet {\n class: Class!\n gender: Gender!\n name: String!\n type: CatType!\n}\n\nenum CatType {\n HOME\n STREET\n}\n\nenum Class {\n FISH\n MAMMAL\n REPTILE\n}\n\ntype Details {\n forename: String! @shareable\n hasChildren: Boolean!\n maritalStatus: MaritalStatus\n middlename: String @deprecated(reason: \"No longer supported\")\n nationality: Nationality!\n pets: [Pet]\n surname: String! @shareable\n}\n\ntype Dog implements Animal & Pet {\n breed: DogBreed!\n class: Class!\n gender: Gender!\n name: String!\n}\n\nenum DogBreed {\n GOLDEN_RETRIEVER\n POODLE\n ROTTWEILER\n YORKSHIRE_TERRIER\n}\n\ntype Employee @key(fields: \"id\") {\n details: Details @shareable\n id: Int!\n}\n\nenum Gender {\n FEMALE\n MALE\n UNKNOWN\n}\n\nenum MaritalStatus {\n ENGAGED\n MARRIED\n}\n\ntype Mouse implements Animal & Pet {\n class: Class!\n gender: Gender!\n name: String!\n}\n\nenum Nationality {\n AMERICAN\n DUTCH\n ENGLISH\n GERMAN\n INDIAN\n SPANISH\n UKRAINIAN\n}\n\ninput NestedSearchInput {\n hasChildren: Boolean\n maritalStatus: MaritalStatus\n}\n\ninterface Pet implements Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Pony implements Animal & Pet {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Query {\n \"\"\" This is a GraphQL query that retrieves a list of employees.\"\"\"\n findEmployees(criteria: SearchInput): [Employee!]!\n}\n\n\"\"\" Allows to filter employees by their details. \"\"\"\ninput SearchInput {\n hasPets: Boolean\n nationality: Nationality\n nested: NestedSearchInput\n}\n\nscalar link__Import\n\nenum link__Purpose {\n EXECUTION\n SECURITY\n}\n\nscalar openfed__FieldSet",
"6f2131dd12f912ee7f5a965938039527994be676": "schema {\n subscription: Subscription\n}\n\ndirective @goField(forceResolver: Boolean, name: String, omittable: Boolean) on FIELD_DEFINITION | INPUT_FIELD_DEFINITION\n\ndirective @key(fields: openfed__FieldSet!, resolvable: Boolean = true) repeatable on INTERFACE | OBJECT\n\ndirective @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA\n\ntype Country @key(fields: \"key { name }\", resolvable: false) {\n key: CountryKey!\n}\n\ntype CountryKey {\n name: String!\n}\n\ntype Employee @key(fields: \"id\") {\n hobbies: [Hobby!]\n id: Int!\n}\n\ntype Exercise implements Hobby {\n category: ExerciseType!\n employees: [Employee!]! @goField(forceResolver: true)\n}\n\nenum ExerciseType {\n CALISTHENICS\n HIKING\n SPORT\n STRENGTH_TRAINING\n}\n\ninterface Experience {\n yearsOfExperience: Float!\n}\n\ntype Flying implements Experience & Hobby {\n employees: [Employee!]! @goField(forceResolver: true)\n planeModels: [String!]!\n yearsOfExperience: Float!\n}\n\nenum GameGenre {\n ADVENTURE\n BOARD\n CARD\n FPS\n ROGUELITE\n RPG\n SIMULATION\n STRATEGY\n}\n\ntype Gaming implements Experience & Hobby {\n employees: [Employee!]! @goField(forceResolver: true)\n genres: [GameGenre!]!\n name: String!\n yearsOfExperience: Float!\n}\n\ninterface Hobby {\n employees: [Employee!]! @goField(forceResolver: true)\n}\n\ntype Other implements Hobby {\n employees: [Employee!]! @goField(forceResolver: true)\n name: String!\n}\n\ntype Programming implements Hobby {\n employees: [Employee!]! @goField(forceResolver: true)\n languages: [ProgrammingLanguage!]!\n}\n\nenum ProgrammingLanguage {\n CSHARP\n GO\n RUST\n TYPESCRIPT\n}\n\ntype SDK @key(fields: \"upc\") {\n clientLanguages: [ProgrammingLanguage!]!\n upc: ID!\n}\n\ntype Subscription {\n countHob(intervalMilliseconds: Int!, max: Int!): Int!\n}\n\ntype Travelling implements Hobby {\n countriesLived: [Country!]!\n employees: [Employee!]! @goField(forceResolver: true)\n}\n\nscalar link__Import\n\nenum link__Purpose {\n EXECUTION\n SECURITY\n}\n\nscalar openfed__FieldSet",
"ae2f1af7c0ba46587f3fd229d25cb8e78212f91f": "schema @link(url: \"https://specs.apollo.dev/federation/v2.5\", import: [\"@authenticated\", \"@composeDirective\", \"@external\", \"@extends\", \"@inaccessible\", \"@interfaceObject\", \"@override\", \"@provides\", \"@key\", \"@requires\", \"@requiresScopes\", \"@shareable\", \"@tag\"]) {\n query: Queries\n mutation: Mutation\n}\n\ndirective @authenticated on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR\n\ndirective @key(fields: openfed__FieldSet!, resolvable: Boolean = true) repeatable on INTERFACE | OBJECT\n\ndirective @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA\n\ndirective @override(from: String!) on FIELD_DEFINITION\n\ndirective @requiresScopes(scopes: [[openfed__Scope!]!]!) on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR\n\ntype Consultancy @key(fields: \"upc\") {\n name: ProductName!\n upc: ID!\n}\n\ntype Cosmo @key(fields: \"upc\") {\n name: ProductName!\n repositoryURL: String!\n upc: ID!\n}\n\ntype DirectiveFact implements TopSecretFact @authenticated {\n description: FactContent!\n factType: TopSecretFactType\n title: String!\n}\n\ntype Documentation {\n url(product: ProductName!): String!\n urls(products: [ProductName!]!): [String!]!\n}\n\ntype Employee @key(fields: \"id\") {\n id: Int!\n notes: String @override(from: \"employees\")\n productCount: Int!\n products: [ProductName!]!\n}\n\ntype EntityFact implements TopSecretFact @requiresScopes(scopes: [[\"read:entity\"]]) {\n description: FactContent!\n factType: TopSecretFactType\n title: String!\n}\n\nscalar FactContent @requiresScopes(scopes: [[\"read:scalar\"], [\"read:all\"]])\n\ntype MiscellaneousFact implements TopSecretFact {\n description: FactContent! @requiresScopes(scopes: [[\"read:miscellaneous\"]])\n factType: TopSecretFactType\n title: String!\n}\n\ntype Mutation {\n addFact(fact: TopSecretFactInput!): TopSecretFact! @requiresScopes(scopes: [[\"write:fact\"], [\"write:all\"]])\n}\n\nenum ProductName {\n CONSULTANCY\n COSMO\n ENGINE\n FINANCE\n HUMAN_RESOURCES\n MARKETING\n SDK\n}\n\nunion Products = Consultancy | Cosmo | Documentation\n\ntype Queries {\n factTypes: [TopSecretFactType!]\n productTypes: [Products!]!\n topSecretFederationFacts: [TopSecretFact!]! @requiresScopes(scopes: [[\"read:fact\"], [\"read:all\"]])\n}\n\ninterface TopSecretFact @authenticated {\n description: FactContent!\n factType: TopSecretFactType\n}\n\ninput TopSecretFactInput {\n description: FactContent!\n factType: TopSecretFactType!\n title: String!\n}\n\nenum TopSecretFactType @authenticated {\n DIRECTIVE\n ENTITY\n MISCELLANEOUS\n}\n\nscalar link__Import\n\nenum link__Purpose {\n EXECUTION\n SECURITY\n}\n\nscalar openfed__FieldSet\n\nscalar openfed__Scope",
- "5c5a237ac1f0c1d67ae52534584ee8116d4cc474": "schema {\n query: Query\n subscription: Subscription\n}\n\ndirective @key(fields: openfed__FieldSet!, resolvable: Boolean = true) repeatable on INTERFACE | OBJECT\n\ndirective @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA\n\ndirective @requiresScopes(scopes: [[openfed__Scope!]!]!) on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR\n\ndirective @shareable repeatable on FIELD_DEFINITION | OBJECT\n\ntype ABigObject {\n aFieldOnABigObject: String!\n bFieldOnABigObject: Int!\n cFieldOnABigObject: Boolean!\n dFieldOnABigObject: Float!\n eFieldOnABigObject: String!\n fFieldOnABigObject: Int!\n gFieldOnABigObject: Boolean!\n hFieldOnABigObject: Float!\n iFieldOnABigObject: String!\n jFieldOnABigObject: Int!\n kFieldOnABigObject: Boolean!\n lFieldOnABigObject: Float!\n mFieldOnABigObject: String!\n nFieldOnABigObject: Int!\n oFieldOnABigObject: Boolean!\n pFieldOnABigObject: Float!\n qFieldOnABigObject: String!\n rFieldOnABigObject: Int!\n sFieldOnABigObject: Boolean!\n tFieldOnABigObject: Float!\n uFieldOnABigObject: String!\n vFieldOnABigObject: Int!\n wFieldOnABigObject: Boolean!\n xFieldOnABigObject: Float!\n yFieldOnABigObject: String!\n zFieldOnABigObject: Int!\n}\n\ntype BBigObject {\n aFieldOnBBigObject: String!\n bFieldOnBBigObject: Int!\n cFieldOnBBigObject: Boolean!\n dFieldOnBBigObject: Float!\n eFieldOnBBigObject: String!\n fFieldOnBBigObject: Int!\n gFieldOnBBigObject: Boolean!\n hFieldOnBBigObject: Float!\n iFieldOnBBigObject: String!\n jFieldOnBBigObject: Int!\n kFieldOnBBigObject: Boolean!\n lFieldOnBBigObject: Float!\n mFieldOnBBigObject: String!\n nFieldOnBBigObject: Int!\n oFieldOnBBigObject: Boolean!\n pFieldOnBBigObject: Float!\n qFieldOnBBigObject: String!\n rFieldOnBBigObject: Int!\n sFieldOnBBigObject: Boolean!\n tFieldOnBBigObject: Float!\n uFieldOnBBigObject: String!\n vFieldOnBBigObject: Int!\n wFieldOnBBigObject: Boolean!\n xFieldOnBBigObject: Float!\n yFieldOnBBigObject: String!\n zFieldOnBBigObject: Int!\n}\n\nunion BigAbstractResponse = ABigObject | BBigObject | CBigObject | DBigObject | EBigObject | FBigObject | GBigObject | HBigObject | IBigObject | JBigObject | KBigObject | LBigObject | MBigObject | NBigObject | OBigObject | PBigObject | QBigObject | RBigObject | SBigObject | TBigObject | UBigObject | VBigObject | WBigObject | XBigObject | YBigObject | ZBigObject\n\ntype BigObject {\n nestedObjects: [NestedObject!]!\n}\n\ntype CBigObject {\n aFieldOnCBigObject: String!\n bFieldOnCBigObject: Int!\n cFieldOnCBigObject: Boolean!\n dFieldOnCBigObject: Float!\n eFieldOnCBigObject: String!\n fFieldOnCBigObject: Int!\n gFieldOnCBigObject: Boolean!\n hFieldOnCBigObject: Float!\n iFieldOnCBigObject: String!\n jFieldOnCBigObject: Int!\n kFieldOnCBigObject: Boolean!\n lFieldOnCBigObject: Float!\n mFieldOnCBigObject: String!\n nFieldOnCBigObject: Int!\n oFieldOnCBigObject: Boolean!\n pFieldOnCBigObject: Float!\n qFieldOnCBigObject: String!\n rFieldOnCBigObject: Int!\n sFieldOnCBigObject: Boolean!\n tFieldOnCBigObject: Float!\n uFieldOnCBigObject: String!\n vFieldOnCBigObject: Int!\n wFieldOnCBigObject: Boolean!\n xFieldOnCBigObject: Float!\n yFieldOnCBigObject: String!\n zFieldOnCBigObject: Int!\n}\n\ntype DBigObject {\n aFieldOnDBigObject: String!\n bFieldOnDBigObject: Int!\n cFieldOnDBigObject: Boolean!\n dFieldOnDBigObject: Float!\n eFieldOnDBigObject: String!\n fFieldOnDBigObject: Int!\n gFieldOnDBigObject: Boolean!\n hFieldOnDBigObject: Float!\n iFieldOnDBigObject: String!\n jFieldOnDBigObject: Int!\n kFieldOnDBigObject: Boolean!\n lFieldOnDBigObject: Float!\n mFieldOnDBigObject: String!\n nFieldOnDBigObject: Int!\n oFieldOnDBigObject: Boolean!\n pFieldOnDBigObject: Float!\n qFieldOnDBigObject: String!\n rFieldOnDBigObject: Int!\n sFieldOnDBigObject: Boolean!\n tFieldOnDBigObject: Float!\n uFieldOnDBigObject: String!\n vFieldOnDBigObject: Int!\n wFieldOnDBigObject: Boolean!\n xFieldOnDBigObject: Float!\n yFieldOnDBigObject: String!\n zFieldOnDBigObject: Int!\n}\n\ntype DeeplyNestedObject {\n aFieldOnDeeplyNestedObject: String!\n bFieldOnDeeplyNestedObject: Int!\n cFieldOnDeeplyNestedObject: Boolean!\n dFieldOnDeeplyNestedObject: Float!\n eFieldOnDeeplyNestedObject: String!\n fFieldOnDeeplyNestedObject: Int!\n gFieldOnDeeplyNestedObject: Boolean!\n hFieldOnDeeplyNestedObject: Float!\n iFieldOnDeeplyNestedObject: String!\n jFieldOnDeeplyNestedObject: Int!\n kFieldOnDeeplyNestedObject: Boolean!\n lFieldOnDeeplyNestedObject: Float!\n mFieldOnDeeplyNestedObject: String!\n nFieldOnDeeplyNestedObject: Int!\n oFieldOnDeeplyNestedObject: Boolean!\n pFieldOnDeeplyNestedObject: Float!\n qFieldOnDeeplyNestedObject: String!\n rFieldOnDeeplyNestedObject: Int!\n sFieldOnDeeplyNestedObject: Boolean!\n tFieldOnDeeplyNestedObject: Float!\n uFieldOnDeeplyNestedObject: String!\n vFieldOnDeeplyNestedObject: Int!\n wFieldOnDeeplyNestedObject: Boolean!\n xFieldOnDeeplyNestedObject: Float!\n yFieldOnDeeplyNestedObject: String!\n zFieldOnDeeplyNestedObject: Int!\n}\n\ntype EBigObject {\n aFieldOnEBigObject: String!\n bFieldOnEBigObject: Int!\n cFieldOnEBigObject: Boolean!\n dFieldOnEBigObject: Float!\n eFieldOnEBigObject: String!\n fFieldOnEBigObject: Int!\n gFieldOnEBigObject: Boolean!\n hFieldOnEBigObject: Float!\n iFieldOnEBigObject: String!\n jFieldOnEBigObject: Int!\n kFieldOnEBigObject: Boolean!\n lFieldOnEBigObject: Float!\n mFieldOnEBigObject: String!\n nFieldOnEBigObject: Int!\n oFieldOnEBigObject: Boolean!\n pFieldOnEBigObject: Float!\n qFieldOnEBigObject: String!\n rFieldOnEBigObject: Int!\n sFieldOnEBigObject: Boolean!\n tFieldOnEBigObject: Float!\n uFieldOnEBigObject: String!\n vFieldOnEBigObject: Int!\n wFieldOnEBigObject: Boolean!\n xFieldOnEBigObject: Float!\n yFieldOnEBigObject: String!\n zFieldOnEBigObject: Int!\n}\n\ntype Employee @key(fields: \"id\") {\n fieldThrowsError: String\n id: Int!\n}\n\nenum EnumType {\n A\n B\n C\n}\n\ntype FBigObject {\n aFieldOnFBigObject: String!\n bFieldOnFBigObject: Int!\n cFieldOnFBigObject: Boolean!\n dFieldOnFBigObject: Float!\n eFieldOnFBigObject: String!\n fFieldOnFBigObject: Int!\n gFieldOnFBigObject: Boolean!\n hFieldOnFBigObject: Float!\n iFieldOnFBigObject: String!\n jFieldOnFBigObject: Int!\n kFieldOnFBigObject: Boolean!\n lFieldOnFBigObject: Float!\n mFieldOnFBigObject: String!\n nFieldOnFBigObject: Int!\n oFieldOnFBigObject: Boolean!\n pFieldOnFBigObject: Float!\n qFieldOnFBigObject: String!\n rFieldOnFBigObject: Int!\n sFieldOnFBigObject: Boolean!\n tFieldOnFBigObject: Float!\n uFieldOnFBigObject: String!\n vFieldOnFBigObject: Int!\n wFieldOnFBigObject: Boolean!\n xFieldOnFBigObject: Float!\n yFieldOnFBigObject: String!\n zFieldOnFBigObject: Int!\n}\n\ntype GBigObject {\n aFieldOnGBigObject: String!\n bFieldOnGBigObject: Int!\n cFieldOnGBigObject: Boolean!\n dFieldOnGBigObject: Float!\n eFieldOnGBigObject: String!\n fFieldOnGBigObject: Int!\n gFieldOnGBigObject: Boolean!\n hFieldOnGBigObject: Float!\n iFieldOnGBigObject: String!\n jFieldOnGBigObject: Int!\n kFieldOnGBigObject: Boolean!\n lFieldOnGBigObject: Float!\n mFieldOnGBigObject: String!\n nFieldOnGBigObject: Int!\n oFieldOnGBigObject: Boolean!\n pFieldOnGBigObject: Float!\n qFieldOnGBigObject: String!\n rFieldOnGBigObject: Int!\n sFieldOnGBigObject: Boolean!\n tFieldOnGBigObject: Float!\n uFieldOnGBigObject: String!\n vFieldOnGBigObject: Int!\n wFieldOnGBigObject: Boolean!\n xFieldOnGBigObject: Float!\n yFieldOnGBigObject: String!\n zFieldOnGBigObject: Int!\n}\n\ntype HBigObject {\n aFieldOnHBigObject: String!\n bFieldOnHBigObject: Int!\n cFieldOnHBigObject: Boolean!\n dFieldOnHBigObject: Float!\n eFieldOnHBigObject: String!\n fFieldOnHBigObject: Int!\n gFieldOnHBigObject: Boolean!\n hFieldOnHBigObject: Float!\n iFieldOnHBigObject: String!\n jFieldOnHBigObject: Int!\n kFieldOnHBigObject: Boolean!\n lFieldOnHBigObject: Float!\n mFieldOnHBigObject: String!\n nFieldOnHBigObject: Int!\n oFieldOnHBigObject: Boolean!\n pFieldOnHBigObject: Float!\n qFieldOnHBigObject: String!\n rFieldOnHBigObject: Int!\n sFieldOnHBigObject: Boolean!\n tFieldOnHBigObject: Float!\n uFieldOnHBigObject: String!\n vFieldOnHBigObject: Int!\n wFieldOnHBigObject: Boolean!\n xFieldOnHBigObject: Float!\n yFieldOnHBigObject: String!\n zFieldOnHBigObject: Int!\n}\n\ntype IBigObject {\n aFieldOnIBigObject: String!\n bFieldOnIBigObject: Int!\n cFieldOnIBigObject: Boolean!\n dFieldOnIBigObject: Float!\n eFieldOnIBigObject: String!\n fFieldOnIBigObject: Int!\n gFieldOnIBigObject: Boolean!\n hFieldOnIBigObject: Float!\n iFieldOnIBigObject: String!\n jFieldOnIBigObject: Int!\n kFieldOnIBigObject: Boolean!\n lFieldOnIBigObject: Float!\n mFieldOnIBigObject: String!\n nFieldOnIBigObject: Int!\n oFieldOnIBigObject: Boolean!\n pFieldOnIBigObject: Float!\n qFieldOnIBigObject: String!\n rFieldOnIBigObject: Int!\n sFieldOnIBigObject: Boolean!\n tFieldOnIBigObject: Float!\n uFieldOnIBigObject: String!\n vFieldOnIBigObject: Int!\n wFieldOnIBigObject: Boolean!\n xFieldOnIBigObject: Float!\n yFieldOnIBigObject: String!\n zFieldOnIBigObject: Int!\n}\n\ninput InputArg {\n enum: EnumType\n enums: [EnumType!]\n string: String\n strings: [String!]\n}\n\ntype InputResponse {\n arg: String!\n}\n\ninput InputType {\n arg: String!\n}\n\ntype JBigObject {\n aFieldOnJBigObject: String!\n bFieldOnJBigObject: Int!\n cFieldOnJBigObject: Boolean!\n dFieldOnJBigObject: Float!\n eFieldOnJBigObject: String!\n fFieldOnJBigObject: Int!\n gFieldOnJBigObject: Boolean!\n hFieldOnJBigObject: Float!\n iFieldOnJBigObject: String!\n jFieldOnJBigObject: Int!\n kFieldOnJBigObject: Boolean!\n lFieldOnJBigObject: Float!\n mFieldOnJBigObject: String!\n nFieldOnJBigObject: Int!\n oFieldOnJBigObject: Boolean!\n pFieldOnJBigObject: Float!\n qFieldOnJBigObject: String!\n rFieldOnJBigObject: Int!\n sFieldOnJBigObject: Boolean!\n tFieldOnJBigObject: Float!\n uFieldOnJBigObject: String!\n vFieldOnJBigObject: Int!\n wFieldOnJBigObject: Boolean!\n xFieldOnJBigObject: Float!\n yFieldOnJBigObject: String!\n zFieldOnJBigObject: Int!\n}\n\ntype KBigObject {\n aFieldOnKBigObject: String!\n bFieldOnKBigObject: Int!\n cFieldOnKBigObject: Boolean!\n dFieldOnKBigObject: Float!\n eFieldOnKBigObject: String!\n fFieldOnKBigObject: Int!\n gFieldOnKBigObject: Boolean!\n hFieldOnKBigObject: Float!\n iFieldOnKBigObject: String!\n jFieldOnKBigObject: Int!\n kFieldOnKBigObject: Boolean!\n lFieldOnKBigObject: Float!\n mFieldOnKBigObject: String!\n nFieldOnKBigObject: Int!\n oFieldOnKBigObject: Boolean!\n pFieldOnKBigObject: Float!\n qFieldOnKBigObject: String!\n rFieldOnKBigObject: Int!\n sFieldOnKBigObject: Boolean!\n tFieldOnKBigObject: Float!\n uFieldOnKBigObject: String!\n vFieldOnKBigObject: Int!\n wFieldOnKBigObject: Boolean!\n xFieldOnKBigObject: Float!\n yFieldOnKBigObject: String!\n zFieldOnKBigObject: Int!\n}\n\ntype LBigObject {\n aFieldOnLBigObject: String!\n bFieldOnLBigObject: Int!\n cFieldOnLBigObject: Boolean!\n dFieldOnLBigObject: Float!\n eFieldOnLBigObject: String!\n fFieldOnLBigObject: Int!\n gFieldOnLBigObject: Boolean!\n hFieldOnLBigObject: Float!\n iFieldOnLBigObject: String!\n jFieldOnLBigObject: Int!\n kFieldOnLBigObject: Boolean!\n lFieldOnLBigObject: Float!\n mFieldOnLBigObject: String!\n nFieldOnLBigObject: Int!\n oFieldOnLBigObject: Boolean!\n pFieldOnLBigObject: Float!\n qFieldOnLBigObject: String!\n rFieldOnLBigObject: Int!\n sFieldOnLBigObject: Boolean!\n tFieldOnLBigObject: Float!\n uFieldOnLBigObject: String!\n vFieldOnLBigObject: Int!\n wFieldOnLBigObject: Boolean!\n xFieldOnLBigObject: Float!\n yFieldOnLBigObject: String!\n zFieldOnLBigObject: Int!\n}\n\ntype MBigObject {\n aFieldOnMBigObject: String!\n bFieldOnMBigObject: Int!\n cFieldOnMBigObject: Boolean!\n dFieldOnMBigObject: Float!\n eFieldOnMBigObject: String!\n fFieldOnMBigObject: Int!\n gFieldOnMBigObject: Boolean!\n hFieldOnMBigObject: Float!\n iFieldOnMBigObject: String!\n jFieldOnMBigObject: Int!\n kFieldOnMBigObject: Boolean!\n lFieldOnMBigObject: Float!\n mFieldOnMBigObject: String!\n nFieldOnMBigObject: Int!\n oFieldOnMBigObject: Boolean!\n pFieldOnMBigObject: Float!\n qFieldOnMBigObject: String!\n rFieldOnMBigObject: Int!\n sFieldOnMBigObject: Boolean!\n tFieldOnMBigObject: Float!\n uFieldOnMBigObject: String!\n vFieldOnMBigObject: Int!\n wFieldOnMBigObject: Boolean!\n xFieldOnMBigObject: Float!\n yFieldOnMBigObject: String!\n zFieldOnMBigObject: Int!\n}\n\nscalar Map\n\ntype NBigObject {\n aFieldOnNBigObject: String!\n bFieldOnNBigObject: Int!\n cFieldOnNBigObject: Boolean!\n dFieldOnNBigObject: Float!\n eFieldOnNBigObject: String!\n fFieldOnNBigObject: Int!\n gFieldOnNBigObject: Boolean!\n hFieldOnNBigObject: Float!\n iFieldOnNBigObject: String!\n jFieldOnNBigObject: Int!\n kFieldOnNBigObject: Boolean!\n lFieldOnNBigObject: Float!\n mFieldOnNBigObject: String!\n nFieldOnNBigObject: Int!\n oFieldOnNBigObject: Boolean!\n pFieldOnNBigObject: Float!\n qFieldOnNBigObject: String!\n rFieldOnNBigObject: Int!\n sFieldOnNBigObject: Boolean!\n tFieldOnNBigObject: Float!\n uFieldOnNBigObject: String!\n vFieldOnNBigObject: Int!\n wFieldOnNBigObject: Boolean!\n xFieldOnNBigObject: Float!\n yFieldOnNBigObject: String!\n zFieldOnNBigObject: Int!\n}\n\ntype NestedObject {\n deeplyNestedObjects: [DeeplyNestedObject!]!\n}\n\ntype OBigObject {\n aFieldOnOBigObject: String!\n bFieldOnOBigObject: Int!\n cFieldOnOBigObject: Boolean!\n dFieldOnOBigObject: Float!\n eFieldOnOBigObject: String!\n fFieldOnOBigObject: Int!\n gFieldOnOBigObject: Boolean!\n hFieldOnOBigObject: Float!\n iFieldOnOBigObject: String!\n jFieldOnOBigObject: Int!\n kFieldOnOBigObject: Boolean!\n lFieldOnOBigObject: Float!\n mFieldOnOBigObject: String!\n nFieldOnOBigObject: Int!\n oFieldOnOBigObject: Boolean!\n pFieldOnOBigObject: Float!\n qFieldOnOBigObject: String!\n rFieldOnOBigObject: Int!\n sFieldOnOBigObject: Boolean!\n tFieldOnOBigObject: Float!\n uFieldOnOBigObject: String!\n vFieldOnOBigObject: Int!\n wFieldOnOBigObject: Boolean!\n xFieldOnOBigObject: Float!\n yFieldOnOBigObject: String!\n zFieldOnOBigObject: Int!\n}\n\ntype PBigObject {\n aFieldOnPBigObject: String!\n bFieldOnPBigObject: Int!\n cFieldOnPBigObject: Boolean!\n dFieldOnPBigObject: Float!\n eFieldOnPBigObject: String!\n fFieldOnPBigObject: Int!\n gFieldOnPBigObject: Boolean!\n hFieldOnPBigObject: Float!\n iFieldOnPBigObject: String!\n jFieldOnPBigObject: Int!\n kFieldOnPBigObject: Boolean!\n lFieldOnPBigObject: Float!\n mFieldOnPBigObject: String!\n nFieldOnPBigObject: Int!\n oFieldOnPBigObject: Boolean!\n pFieldOnPBigObject: Float!\n qFieldOnPBigObject: String!\n rFieldOnPBigObject: Int!\n sFieldOnPBigObject: Boolean!\n tFieldOnPBigObject: Float!\n uFieldOnPBigObject: String!\n vFieldOnPBigObject: Int!\n wFieldOnPBigObject: Boolean!\n xFieldOnPBigObject: Float!\n yFieldOnPBigObject: String!\n zFieldOnPBigObject: Int!\n}\n\ntype QBigObject {\n aFieldOnQBigObject: String!\n bFieldOnQBigObject: Int!\n cFieldOnQBigObject: Boolean!\n dFieldOnQBigObject: Float!\n eFieldOnQBigObject: String!\n fFieldOnQBigObject: Int!\n gFieldOnQBigObject: Boolean!\n hFieldOnQBigObject: Float!\n iFieldOnQBigObject: String!\n jFieldOnQBigObject: Int!\n kFieldOnQBigObject: Boolean!\n lFieldOnQBigObject: Float!\n mFieldOnQBigObject: String!\n nFieldOnQBigObject: Int!\n oFieldOnQBigObject: Boolean!\n pFieldOnQBigObject: Float!\n qFieldOnQBigObject: String!\n rFieldOnQBigObject: Int!\n sFieldOnQBigObject: Boolean!\n tFieldOnQBigObject: Float!\n uFieldOnQBigObject: String!\n vFieldOnQBigObject: Int!\n wFieldOnQBigObject: Boolean!\n xFieldOnQBigObject: Float!\n yFieldOnQBigObject: String!\n zFieldOnQBigObject: Int!\n}\n\ntype Query {\n bigAbstractResponse: BigAbstractResponse\n bigResponse(artificialDelay: Int! = 0, bigObjects: Int! = 100, deeplyNestedObjects: Int! = 100, nestedObjects: Int! = 100): [BigObject!]!\n \"\"\"Returns response after the given delay\"\"\"\n delay(ms: Int!, response: String!): String!\n floatField(arg: Float): Float\n \"\"\"Returns the value of the received HTTP header.\"\"\"\n headerValue(name: String!): String!\n \"\"\"Returns the value of the given key in the WS initial payload.\"\"\"\n initPayloadValue(key: String!): String!\n initialPayload: Map\n longResponse(artificialDelay: Int! = 0, bytes: Int!): String\n rootFieldWithInput(arg: InputArg!): String!\n rootFieldWithListArg(arg: [String!]!): [String!]!\n rootFieldWithListOfEnumArg(arg: [EnumType!]!): [EnumType!]!\n rootFieldWithListOfInputArg(arg: [InputType!]!): [InputResponse!]!\n rootFieldWithNestedListArg(arg: [[String!]!]!): [[String!]!]!\n secret: Secret @requiresScopes(scopes: [[\"read:secret\"]])\n sharedThings(numOfA: Int!, numOfB: Int!): [Thing!]! @shareable\n}\n\ntype RBigObject {\n aFieldOnRBigObject: String!\n bFieldOnRBigObject: Int!\n cFieldOnRBigObject: Boolean!\n dFieldOnRBigObject: Float!\n eFieldOnRBigObject: String!\n fFieldOnRBigObject: Int!\n gFieldOnRBigObject: Boolean!\n hFieldOnRBigObject: Float!\n iFieldOnRBigObject: String!\n jFieldOnRBigObject: Int!\n kFieldOnRBigObject: Boolean!\n lFieldOnRBigObject: Float!\n mFieldOnRBigObject: String!\n nFieldOnRBigObject: Int!\n oFieldOnRBigObject: Boolean!\n pFieldOnRBigObject: Float!\n qFieldOnRBigObject: String!\n rFieldOnRBigObject: Int!\n sFieldOnRBigObject: Boolean!\n tFieldOnRBigObject: Float!\n uFieldOnRBigObject: String!\n vFieldOnRBigObject: Int!\n wFieldOnRBigObject: Boolean!\n xFieldOnRBigObject: Float!\n yFieldOnRBigObject: String!\n zFieldOnRBigObject: Int!\n}\n\ntype SBigObject {\n aFieldOnSBigObject: String!\n bFieldOnSBigObject: Int!\n cFieldOnSBigObject: Boolean!\n dFieldOnSBigObject: Float!\n eFieldOnSBigObject: String!\n fFieldOnSBigObject: Int!\n gFieldOnSBigObject: Boolean!\n hFieldOnSBigObject: Float!\n iFieldOnSBigObject: String!\n jFieldOnSBigObject: Int!\n kFieldOnSBigObject: Boolean!\n lFieldOnSBigObject: Float!\n mFieldOnSBigObject: String!\n nFieldOnSBigObject: Int!\n oFieldOnSBigObject: Boolean!\n pFieldOnSBigObject: Float!\n qFieldOnSBigObject: String!\n rFieldOnSBigObject: Int!\n sFieldOnSBigObject: Boolean!\n tFieldOnSBigObject: Float!\n uFieldOnSBigObject: String!\n vFieldOnSBigObject: Int!\n wFieldOnSBigObject: Boolean!\n xFieldOnSBigObject: Float!\n yFieldOnSBigObject: String!\n zFieldOnSBigObject: Int!\n}\n\ntype Secret {\n value: String\n}\n\ntype Subscription {\n \"\"\"Returns a stream with the value of the received HTTP header.\"\"\"\n headerValue(name: String!, repeat: Int): TimestampedString!\n \"\"\"\n Returns a stream with the value of value of the given key in the WS initial payload.\n \"\"\"\n initPayloadValue(key: String!, repeat: Int): TimestampedString!\n \"\"\"Returns a stream with the value of the WS initial payload.\"\"\"\n initialPayload(repeat: Int): Map\n returnsError: String\n}\n\ntype TBigObject {\n aFieldOnTBigObject: String!\n bFieldOnTBigObject: Int!\n cFieldOnTBigObject: Boolean!\n dFieldOnTBigObject: Float!\n eFieldOnTBigObject: String!\n fFieldOnTBigObject: Int!\n gFieldOnTBigObject: Boolean!\n hFieldOnTBigObject: Float!\n iFieldOnTBigObject: String!\n jFieldOnTBigObject: Int!\n kFieldOnTBigObject: Boolean!\n lFieldOnTBigObject: Float!\n mFieldOnTBigObject: String!\n nFieldOnTBigObject: Int!\n oFieldOnTBigObject: Boolean!\n pFieldOnTBigObject: Float!\n qFieldOnTBigObject: String!\n rFieldOnTBigObject: Int!\n sFieldOnTBigObject: Boolean!\n tFieldOnTBigObject: Float!\n uFieldOnTBigObject: String!\n vFieldOnTBigObject: Int!\n wFieldOnTBigObject: Boolean!\n xFieldOnTBigObject: Float!\n yFieldOnTBigObject: String!\n zFieldOnTBigObject: Int!\n}\n\ntype Thing {\n b: String! @shareable\n}\n\ntype TimestampedString {\n initialPayload: Map\n \"\"\"Sequence number\"\"\"\n seq: Int!\n \"\"\"Total number of responses to be sent\"\"\"\n total: Int!\n \"\"\"The timestamp when the response was generated.\"\"\"\n unixTime: Int!\n \"\"\"The value of the string.\"\"\"\n value: String!\n}\n\ntype UBigObject {\n aFieldOnUBigObject: String!\n bFieldOnUBigObject: Int!\n cFieldOnUBigObject: Boolean!\n dFieldOnUBigObject: Float!\n eFieldOnUBigObject: String!\n fFieldOnUBigObject: Int!\n gFieldOnUBigObject: Boolean!\n hFieldOnUBigObject: Float!\n iFieldOnUBigObject: String!\n jFieldOnUBigObject: Int!\n kFieldOnUBigObject: Boolean!\n lFieldOnUBigObject: Float!\n mFieldOnUBigObject: String!\n nFieldOnUBigObject: Int!\n oFieldOnUBigObject: Boolean!\n pFieldOnUBigObject: Float!\n qFieldOnUBigObject: String!\n rFieldOnUBigObject: Int!\n sFieldOnUBigObject: Boolean!\n tFieldOnUBigObject: Float!\n uFieldOnUBigObject: String!\n vFieldOnUBigObject: Int!\n wFieldOnUBigObject: Boolean!\n xFieldOnUBigObject: Float!\n yFieldOnUBigObject: String!\n zFieldOnUBigObject: Int!\n}\n\ntype VBigObject {\n aFieldOnVBigObject: String!\n bFieldOnVBigObject: Int!\n cFieldOnVBigObject: Boolean!\n dFieldOnVBigObject: Float!\n eFieldOnVBigObject: String!\n fFieldOnVBigObject: Int!\n gFieldOnVBigObject: Boolean!\n hFieldOnVBigObject: Float!\n iFieldOnVBigObject: String!\n jFieldOnVBigObject: Int!\n kFieldOnVBigObject: Boolean!\n lFieldOnVBigObject: Float!\n mFieldOnVBigObject: String!\n nFieldOnVBigObject: Int!\n oFieldOnVBigObject: Boolean!\n pFieldOnVBigObject: Float!\n qFieldOnVBigObject: String!\n rFieldOnVBigObject: Int!\n sFieldOnVBigObject: Boolean!\n tFieldOnVBigObject: Float!\n uFieldOnVBigObject: String!\n vFieldOnVBigObject: Int!\n wFieldOnVBigObject: Boolean!\n xFieldOnVBigObject: Float!\n yFieldOnVBigObject: String!\n zFieldOnVBigObject: Int!\n}\n\ntype WBigObject {\n aFieldOnWBigObject: String!\n bFieldOnWBigObject: Int!\n cFieldOnWBigObject: Boolean!\n dFieldOnWBigObject: Float!\n eFieldOnWBigObject: String!\n fFieldOnWBigObject: Int!\n gFieldOnWBigObject: Boolean!\n hFieldOnWBigObject: Float!\n iFieldOnWBigObject: String!\n jFieldOnWBigObject: Int!\n kFieldOnWBigObject: Boolean!\n lFieldOnWBigObject: Float!\n mFieldOnWBigObject: String!\n nFieldOnWBigObject: Int!\n oFieldOnWBigObject: Boolean!\n pFieldOnWBigObject: Float!\n qFieldOnWBigObject: String!\n rFieldOnWBigObject: Int!\n sFieldOnWBigObject: Boolean!\n tFieldOnWBigObject: Float!\n uFieldOnWBigObject: String!\n vFieldOnWBigObject: Int!\n wFieldOnWBigObject: Boolean!\n xFieldOnWBigObject: Float!\n yFieldOnWBigObject: String!\n zFieldOnWBigObject: Int!\n}\n\ntype XBigObject {\n aFieldOnXBigObject: String!\n bFieldOnXBigObject: Int!\n cFieldOnXBigObject: Boolean!\n dFieldOnXBigObject: Float!\n eFieldOnXBigObject: String!\n fFieldOnXBigObject: Int!\n gFieldOnXBigObject: Boolean!\n hFieldOnXBigObject: Float!\n iFieldOnXBigObject: String!\n jFieldOnXBigObject: Int!\n kFieldOnXBigObject: Boolean!\n lFieldOnXBigObject: Float!\n mFieldOnXBigObject: String!\n nFieldOnXBigObject: Int!\n oFieldOnXBigObject: Boolean!\n pFieldOnXBigObject: Float!\n qFieldOnXBigObject: String!\n rFieldOnXBigObject: Int!\n sFieldOnXBigObject: Boolean!\n tFieldOnXBigObject: Float!\n uFieldOnXBigObject: String!\n vFieldOnXBigObject: Int!\n wFieldOnXBigObject: Boolean!\n xFieldOnXBigObject: Float!\n yFieldOnXBigObject: String!\n zFieldOnXBigObject: Int!\n}\n\ntype YBigObject {\n aFieldOnYBigObject: String!\n bFieldOnYBigObject: Int!\n cFieldOnYBigObject: Boolean!\n dFieldOnYBigObject: Float!\n eFieldOnYBigObject: String!\n fFieldOnYBigObject: Int!\n gFieldOnYBigObject: Boolean!\n hFieldOnYBigObject: Float!\n iFieldOnYBigObject: String!\n jFieldOnYBigObject: Int!\n kFieldOnYBigObject: Boolean!\n lFieldOnYBigObject: Float!\n mFieldOnYBigObject: String!\n nFieldOnYBigObject: Int!\n oFieldOnYBigObject: Boolean!\n pFieldOnYBigObject: Float!\n qFieldOnYBigObject: String!\n rFieldOnYBigObject: Int!\n sFieldOnYBigObject: Boolean!\n tFieldOnYBigObject: Float!\n uFieldOnYBigObject: String!\n vFieldOnYBigObject: Int!\n wFieldOnYBigObject: Boolean!\n xFieldOnYBigObject: Float!\n yFieldOnYBigObject: String!\n zFieldOnYBigObject: Int!\n}\n\ntype ZBigObject {\n aFieldOnZBigObject: String!\n bFieldOnZBigObject: Int!\n cFieldOnZBigObject: Boolean!\n dFieldOnZBigObject: Float!\n eFieldOnZBigObject: String!\n fFieldOnZBigObject: Int!\n gFieldOnZBigObject: Boolean!\n hFieldOnZBigObject: Float!\n iFieldOnZBigObject: String!\n jFieldOnZBigObject: Int!\n kFieldOnZBigObject: Boolean!\n lFieldOnZBigObject: Float!\n mFieldOnZBigObject: String!\n nFieldOnZBigObject: Int!\n oFieldOnZBigObject: Boolean!\n pFieldOnZBigObject: Float!\n qFieldOnZBigObject: String!\n rFieldOnZBigObject: Int!\n sFieldOnZBigObject: Boolean!\n tFieldOnZBigObject: Float!\n uFieldOnZBigObject: String!\n vFieldOnZBigObject: Int!\n wFieldOnZBigObject: Boolean!\n xFieldOnZBigObject: Float!\n yFieldOnZBigObject: String!\n zFieldOnZBigObject: Int!\n}\n\nscalar link__Import\n\nenum link__Purpose {\n EXECUTION\n SECURITY\n}\n\nscalar openfed__FieldSet\n\nscalar openfed__Scope",
+ "c8d8fe56b658fa642dbb31c0fc3d6f024f4aff10": "schema {\n query: Query\n subscription: Subscription\n}\n\ndirective @key(fields: openfed__FieldSet!, resolvable: Boolean = true) repeatable on INTERFACE | OBJECT\n\ndirective @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA\n\ndirective @requiresScopes(scopes: [[openfed__Scope!]!]!) on ENUM | FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR\n\ndirective @shareable repeatable on FIELD_DEFINITION | OBJECT\n\ntype ABigObject {\n aFieldOnABigObject: String!\n bFieldOnABigObject: Int!\n cFieldOnABigObject: Boolean!\n dFieldOnABigObject: Float!\n eFieldOnABigObject: String!\n fFieldOnABigObject: Int!\n gFieldOnABigObject: Boolean!\n hFieldOnABigObject: Float!\n iFieldOnABigObject: String!\n jFieldOnABigObject: Int!\n kFieldOnABigObject: Boolean!\n lFieldOnABigObject: Float!\n mFieldOnABigObject: String!\n nFieldOnABigObject: Int!\n oFieldOnABigObject: Boolean!\n pFieldOnABigObject: Float!\n qFieldOnABigObject: String!\n rFieldOnABigObject: Int!\n sFieldOnABigObject: Boolean!\n tFieldOnABigObject: Float!\n uFieldOnABigObject: String!\n vFieldOnABigObject: Int!\n wFieldOnABigObject: Boolean!\n xFieldOnABigObject: Float!\n yFieldOnABigObject: String!\n zFieldOnABigObject: Int!\n}\n\ntype BBigObject {\n aFieldOnBBigObject: String!\n bFieldOnBBigObject: Int!\n cFieldOnBBigObject: Boolean!\n dFieldOnBBigObject: Float!\n eFieldOnBBigObject: String!\n fFieldOnBBigObject: Int!\n gFieldOnBBigObject: Boolean!\n hFieldOnBBigObject: Float!\n iFieldOnBBigObject: String!\n jFieldOnBBigObject: Int!\n kFieldOnBBigObject: Boolean!\n lFieldOnBBigObject: Float!\n mFieldOnBBigObject: String!\n nFieldOnBBigObject: Int!\n oFieldOnBBigObject: Boolean!\n pFieldOnBBigObject: Float!\n qFieldOnBBigObject: String!\n rFieldOnBBigObject: Int!\n sFieldOnBBigObject: Boolean!\n tFieldOnBBigObject: Float!\n uFieldOnBBigObject: String!\n vFieldOnBBigObject: Int!\n wFieldOnBBigObject: Boolean!\n xFieldOnBBigObject: Float!\n yFieldOnBBigObject: String!\n zFieldOnBBigObject: Int!\n}\n\nunion BigAbstractResponse = ABigObject | BBigObject | CBigObject | DBigObject | EBigObject | FBigObject | GBigObject | HBigObject | IBigObject | JBigObject | KBigObject | LBigObject | MBigObject | NBigObject | OBigObject | PBigObject | QBigObject | RBigObject | SBigObject | TBigObject | UBigObject | VBigObject | WBigObject | XBigObject | YBigObject | ZBigObject\n\ntype BigObject {\n nestedObjects: [NestedObject!]!\n}\n\ntype CBigObject {\n aFieldOnCBigObject: String!\n bFieldOnCBigObject: Int!\n cFieldOnCBigObject: Boolean!\n dFieldOnCBigObject: Float!\n eFieldOnCBigObject: String!\n fFieldOnCBigObject: Int!\n gFieldOnCBigObject: Boolean!\n hFieldOnCBigObject: Float!\n iFieldOnCBigObject: String!\n jFieldOnCBigObject: Int!\n kFieldOnCBigObject: Boolean!\n lFieldOnCBigObject: Float!\n mFieldOnCBigObject: String!\n nFieldOnCBigObject: Int!\n oFieldOnCBigObject: Boolean!\n pFieldOnCBigObject: Float!\n qFieldOnCBigObject: String!\n rFieldOnCBigObject: Int!\n sFieldOnCBigObject: Boolean!\n tFieldOnCBigObject: Float!\n uFieldOnCBigObject: String!\n vFieldOnCBigObject: Int!\n wFieldOnCBigObject: Boolean!\n xFieldOnCBigObject: Float!\n yFieldOnCBigObject: String!\n zFieldOnCBigObject: Int!\n}\n\ntype DBigObject {\n aFieldOnDBigObject: String!\n bFieldOnDBigObject: Int!\n cFieldOnDBigObject: Boolean!\n dFieldOnDBigObject: Float!\n eFieldOnDBigObject: String!\n fFieldOnDBigObject: Int!\n gFieldOnDBigObject: Boolean!\n hFieldOnDBigObject: Float!\n iFieldOnDBigObject: String!\n jFieldOnDBigObject: Int!\n kFieldOnDBigObject: Boolean!\n lFieldOnDBigObject: Float!\n mFieldOnDBigObject: String!\n nFieldOnDBigObject: Int!\n oFieldOnDBigObject: Boolean!\n pFieldOnDBigObject: Float!\n qFieldOnDBigObject: String!\n rFieldOnDBigObject: Int!\n sFieldOnDBigObject: Boolean!\n tFieldOnDBigObject: Float!\n uFieldOnDBigObject: String!\n vFieldOnDBigObject: Int!\n wFieldOnDBigObject: Boolean!\n xFieldOnDBigObject: Float!\n yFieldOnDBigObject: String!\n zFieldOnDBigObject: Int!\n}\n\ntype DeeplyNestedObject {\n aFieldOnDeeplyNestedObject: String!\n bFieldOnDeeplyNestedObject: Int!\n cFieldOnDeeplyNestedObject: Boolean!\n dFieldOnDeeplyNestedObject: Float!\n eFieldOnDeeplyNestedObject: String!\n fFieldOnDeeplyNestedObject: Int!\n gFieldOnDeeplyNestedObject: Boolean!\n hFieldOnDeeplyNestedObject: Float!\n iFieldOnDeeplyNestedObject: String!\n jFieldOnDeeplyNestedObject: Int!\n kFieldOnDeeplyNestedObject: Boolean!\n lFieldOnDeeplyNestedObject: Float!\n mFieldOnDeeplyNestedObject: String!\n nFieldOnDeeplyNestedObject: Int!\n oFieldOnDeeplyNestedObject: Boolean!\n pFieldOnDeeplyNestedObject: Float!\n qFieldOnDeeplyNestedObject: String!\n rFieldOnDeeplyNestedObject: Int!\n sFieldOnDeeplyNestedObject: Boolean!\n tFieldOnDeeplyNestedObject: Float!\n uFieldOnDeeplyNestedObject: String!\n vFieldOnDeeplyNestedObject: Int!\n wFieldOnDeeplyNestedObject: Boolean!\n xFieldOnDeeplyNestedObject: Float!\n yFieldOnDeeplyNestedObject: String!\n zFieldOnDeeplyNestedObject: Int!\n}\n\ntype EBigObject {\n aFieldOnEBigObject: String!\n bFieldOnEBigObject: Int!\n cFieldOnEBigObject: Boolean!\n dFieldOnEBigObject: Float!\n eFieldOnEBigObject: String!\n fFieldOnEBigObject: Int!\n gFieldOnEBigObject: Boolean!\n hFieldOnEBigObject: Float!\n iFieldOnEBigObject: String!\n jFieldOnEBigObject: Int!\n kFieldOnEBigObject: Boolean!\n lFieldOnEBigObject: Float!\n mFieldOnEBigObject: String!\n nFieldOnEBigObject: Int!\n oFieldOnEBigObject: Boolean!\n pFieldOnEBigObject: Float!\n qFieldOnEBigObject: String!\n rFieldOnEBigObject: Int!\n sFieldOnEBigObject: Boolean!\n tFieldOnEBigObject: Float!\n uFieldOnEBigObject: String!\n vFieldOnEBigObject: Int!\n wFieldOnEBigObject: Boolean!\n xFieldOnEBigObject: Float!\n yFieldOnEBigObject: String!\n zFieldOnEBigObject: Int!\n}\n\ntype Employee @key(fields: \"id\") {\n fieldThrowsError: String\n id: Int!\n}\n\nenum EnumType {\n A\n B\n C\n}\n\ntype FBigObject {\n aFieldOnFBigObject: String!\n bFieldOnFBigObject: Int!\n cFieldOnFBigObject: Boolean!\n dFieldOnFBigObject: Float!\n eFieldOnFBigObject: String!\n fFieldOnFBigObject: Int!\n gFieldOnFBigObject: Boolean!\n hFieldOnFBigObject: Float!\n iFieldOnFBigObject: String!\n jFieldOnFBigObject: Int!\n kFieldOnFBigObject: Boolean!\n lFieldOnFBigObject: Float!\n mFieldOnFBigObject: String!\n nFieldOnFBigObject: Int!\n oFieldOnFBigObject: Boolean!\n pFieldOnFBigObject: Float!\n qFieldOnFBigObject: String!\n rFieldOnFBigObject: Int!\n sFieldOnFBigObject: Boolean!\n tFieldOnFBigObject: Float!\n uFieldOnFBigObject: String!\n vFieldOnFBigObject: Int!\n wFieldOnFBigObject: Boolean!\n xFieldOnFBigObject: Float!\n yFieldOnFBigObject: String!\n zFieldOnFBigObject: Int!\n}\n\ntype GBigObject {\n aFieldOnGBigObject: String!\n bFieldOnGBigObject: Int!\n cFieldOnGBigObject: Boolean!\n dFieldOnGBigObject: Float!\n eFieldOnGBigObject: String!\n fFieldOnGBigObject: Int!\n gFieldOnGBigObject: Boolean!\n hFieldOnGBigObject: Float!\n iFieldOnGBigObject: String!\n jFieldOnGBigObject: Int!\n kFieldOnGBigObject: Boolean!\n lFieldOnGBigObject: Float!\n mFieldOnGBigObject: String!\n nFieldOnGBigObject: Int!\n oFieldOnGBigObject: Boolean!\n pFieldOnGBigObject: Float!\n qFieldOnGBigObject: String!\n rFieldOnGBigObject: Int!\n sFieldOnGBigObject: Boolean!\n tFieldOnGBigObject: Float!\n uFieldOnGBigObject: String!\n vFieldOnGBigObject: Int!\n wFieldOnGBigObject: Boolean!\n xFieldOnGBigObject: Float!\n yFieldOnGBigObject: String!\n zFieldOnGBigObject: Int!\n}\n\ntype HBigObject {\n aFieldOnHBigObject: String!\n bFieldOnHBigObject: Int!\n cFieldOnHBigObject: Boolean!\n dFieldOnHBigObject: Float!\n eFieldOnHBigObject: String!\n fFieldOnHBigObject: Int!\n gFieldOnHBigObject: Boolean!\n hFieldOnHBigObject: Float!\n iFieldOnHBigObject: String!\n jFieldOnHBigObject: Int!\n kFieldOnHBigObject: Boolean!\n lFieldOnHBigObject: Float!\n mFieldOnHBigObject: String!\n nFieldOnHBigObject: Int!\n oFieldOnHBigObject: Boolean!\n pFieldOnHBigObject: Float!\n qFieldOnHBigObject: String!\n rFieldOnHBigObject: Int!\n sFieldOnHBigObject: Boolean!\n tFieldOnHBigObject: Float!\n uFieldOnHBigObject: String!\n vFieldOnHBigObject: Int!\n wFieldOnHBigObject: Boolean!\n xFieldOnHBigObject: Float!\n yFieldOnHBigObject: String!\n zFieldOnHBigObject: Int!\n}\n\ntype IBigObject {\n aFieldOnIBigObject: String!\n bFieldOnIBigObject: Int!\n cFieldOnIBigObject: Boolean!\n dFieldOnIBigObject: Float!\n eFieldOnIBigObject: String!\n fFieldOnIBigObject: Int!\n gFieldOnIBigObject: Boolean!\n hFieldOnIBigObject: Float!\n iFieldOnIBigObject: String!\n jFieldOnIBigObject: Int!\n kFieldOnIBigObject: Boolean!\n lFieldOnIBigObject: Float!\n mFieldOnIBigObject: String!\n nFieldOnIBigObject: Int!\n oFieldOnIBigObject: Boolean!\n pFieldOnIBigObject: Float!\n qFieldOnIBigObject: String!\n rFieldOnIBigObject: Int!\n sFieldOnIBigObject: Boolean!\n tFieldOnIBigObject: Float!\n uFieldOnIBigObject: String!\n vFieldOnIBigObject: Int!\n wFieldOnIBigObject: Boolean!\n xFieldOnIBigObject: Float!\n yFieldOnIBigObject: String!\n zFieldOnIBigObject: Int!\n}\n\ninput InputArg {\n enum: EnumType\n enums: [EnumType!]\n string: String\n strings: [String!]\n}\n\ntype InputResponse {\n arg: String!\n}\n\ninput InputType {\n arg: String!\n}\n\ntype JBigObject {\n aFieldOnJBigObject: String!\n bFieldOnJBigObject: Int!\n cFieldOnJBigObject: Boolean!\n dFieldOnJBigObject: Float!\n eFieldOnJBigObject: String!\n fFieldOnJBigObject: Int!\n gFieldOnJBigObject: Boolean!\n hFieldOnJBigObject: Float!\n iFieldOnJBigObject: String!\n jFieldOnJBigObject: Int!\n kFieldOnJBigObject: Boolean!\n lFieldOnJBigObject: Float!\n mFieldOnJBigObject: String!\n nFieldOnJBigObject: Int!\n oFieldOnJBigObject: Boolean!\n pFieldOnJBigObject: Float!\n qFieldOnJBigObject: String!\n rFieldOnJBigObject: Int!\n sFieldOnJBigObject: Boolean!\n tFieldOnJBigObject: Float!\n uFieldOnJBigObject: String!\n vFieldOnJBigObject: Int!\n wFieldOnJBigObject: Boolean!\n xFieldOnJBigObject: Float!\n yFieldOnJBigObject: String!\n zFieldOnJBigObject: Int!\n}\n\ntype KBigObject {\n aFieldOnKBigObject: String!\n bFieldOnKBigObject: Int!\n cFieldOnKBigObject: Boolean!\n dFieldOnKBigObject: Float!\n eFieldOnKBigObject: String!\n fFieldOnKBigObject: Int!\n gFieldOnKBigObject: Boolean!\n hFieldOnKBigObject: Float!\n iFieldOnKBigObject: String!\n jFieldOnKBigObject: Int!\n kFieldOnKBigObject: Boolean!\n lFieldOnKBigObject: Float!\n mFieldOnKBigObject: String!\n nFieldOnKBigObject: Int!\n oFieldOnKBigObject: Boolean!\n pFieldOnKBigObject: Float!\n qFieldOnKBigObject: String!\n rFieldOnKBigObject: Int!\n sFieldOnKBigObject: Boolean!\n tFieldOnKBigObject: Float!\n uFieldOnKBigObject: String!\n vFieldOnKBigObject: Int!\n wFieldOnKBigObject: Boolean!\n xFieldOnKBigObject: Float!\n yFieldOnKBigObject: String!\n zFieldOnKBigObject: Int!\n}\n\ntype LBigObject {\n aFieldOnLBigObject: String!\n bFieldOnLBigObject: Int!\n cFieldOnLBigObject: Boolean!\n dFieldOnLBigObject: Float!\n eFieldOnLBigObject: String!\n fFieldOnLBigObject: Int!\n gFieldOnLBigObject: Boolean!\n hFieldOnLBigObject: Float!\n iFieldOnLBigObject: String!\n jFieldOnLBigObject: Int!\n kFieldOnLBigObject: Boolean!\n lFieldOnLBigObject: Float!\n mFieldOnLBigObject: String!\n nFieldOnLBigObject: Int!\n oFieldOnLBigObject: Boolean!\n pFieldOnLBigObject: Float!\n qFieldOnLBigObject: String!\n rFieldOnLBigObject: Int!\n sFieldOnLBigObject: Boolean!\n tFieldOnLBigObject: Float!\n uFieldOnLBigObject: String!\n vFieldOnLBigObject: Int!\n wFieldOnLBigObject: Boolean!\n xFieldOnLBigObject: Float!\n yFieldOnLBigObject: String!\n zFieldOnLBigObject: Int!\n}\n\ntype MBigObject {\n aFieldOnMBigObject: String!\n bFieldOnMBigObject: Int!\n cFieldOnMBigObject: Boolean!\n dFieldOnMBigObject: Float!\n eFieldOnMBigObject: String!\n fFieldOnMBigObject: Int!\n gFieldOnMBigObject: Boolean!\n hFieldOnMBigObject: Float!\n iFieldOnMBigObject: String!\n jFieldOnMBigObject: Int!\n kFieldOnMBigObject: Boolean!\n lFieldOnMBigObject: Float!\n mFieldOnMBigObject: String!\n nFieldOnMBigObject: Int!\n oFieldOnMBigObject: Boolean!\n pFieldOnMBigObject: Float!\n qFieldOnMBigObject: String!\n rFieldOnMBigObject: Int!\n sFieldOnMBigObject: Boolean!\n tFieldOnMBigObject: Float!\n uFieldOnMBigObject: String!\n vFieldOnMBigObject: Int!\n wFieldOnMBigObject: Boolean!\n xFieldOnMBigObject: Float!\n yFieldOnMBigObject: String!\n zFieldOnMBigObject: Int!\n}\n\nscalar Map\n\ntype NBigObject {\n aFieldOnNBigObject: String!\n bFieldOnNBigObject: Int!\n cFieldOnNBigObject: Boolean!\n dFieldOnNBigObject: Float!\n eFieldOnNBigObject: String!\n fFieldOnNBigObject: Int!\n gFieldOnNBigObject: Boolean!\n hFieldOnNBigObject: Float!\n iFieldOnNBigObject: String!\n jFieldOnNBigObject: Int!\n kFieldOnNBigObject: Boolean!\n lFieldOnNBigObject: Float!\n mFieldOnNBigObject: String!\n nFieldOnNBigObject: Int!\n oFieldOnNBigObject: Boolean!\n pFieldOnNBigObject: Float!\n qFieldOnNBigObject: String!\n rFieldOnNBigObject: Int!\n sFieldOnNBigObject: Boolean!\n tFieldOnNBigObject: Float!\n uFieldOnNBigObject: String!\n vFieldOnNBigObject: Int!\n wFieldOnNBigObject: Boolean!\n xFieldOnNBigObject: Float!\n yFieldOnNBigObject: String!\n zFieldOnNBigObject: Int!\n}\n\ntype NestedObject {\n deeplyNestedObjects: [DeeplyNestedObject!]!\n}\n\ntype OBigObject {\n aFieldOnOBigObject: String!\n bFieldOnOBigObject: Int!\n cFieldOnOBigObject: Boolean!\n dFieldOnOBigObject: Float!\n eFieldOnOBigObject: String!\n fFieldOnOBigObject: Int!\n gFieldOnOBigObject: Boolean!\n hFieldOnOBigObject: Float!\n iFieldOnOBigObject: String!\n jFieldOnOBigObject: Int!\n kFieldOnOBigObject: Boolean!\n lFieldOnOBigObject: Float!\n mFieldOnOBigObject: String!\n nFieldOnOBigObject: Int!\n oFieldOnOBigObject: Boolean!\n pFieldOnOBigObject: Float!\n qFieldOnOBigObject: String!\n rFieldOnOBigObject: Int!\n sFieldOnOBigObject: Boolean!\n tFieldOnOBigObject: Float!\n uFieldOnOBigObject: String!\n vFieldOnOBigObject: Int!\n wFieldOnOBigObject: Boolean!\n xFieldOnOBigObject: Float!\n yFieldOnOBigObject: String!\n zFieldOnOBigObject: Int!\n}\n\ntype PBigObject {\n aFieldOnPBigObject: String!\n bFieldOnPBigObject: Int!\n cFieldOnPBigObject: Boolean!\n dFieldOnPBigObject: Float!\n eFieldOnPBigObject: String!\n fFieldOnPBigObject: Int!\n gFieldOnPBigObject: Boolean!\n hFieldOnPBigObject: Float!\n iFieldOnPBigObject: String!\n jFieldOnPBigObject: Int!\n kFieldOnPBigObject: Boolean!\n lFieldOnPBigObject: Float!\n mFieldOnPBigObject: String!\n nFieldOnPBigObject: Int!\n oFieldOnPBigObject: Boolean!\n pFieldOnPBigObject: Float!\n qFieldOnPBigObject: String!\n rFieldOnPBigObject: Int!\n sFieldOnPBigObject: Boolean!\n tFieldOnPBigObject: Float!\n uFieldOnPBigObject: String!\n vFieldOnPBigObject: Int!\n wFieldOnPBigObject: Boolean!\n xFieldOnPBigObject: Float!\n yFieldOnPBigObject: String!\n zFieldOnPBigObject: Int!\n}\n\ntype QBigObject {\n aFieldOnQBigObject: String!\n bFieldOnQBigObject: Int!\n cFieldOnQBigObject: Boolean!\n dFieldOnQBigObject: Float!\n eFieldOnQBigObject: String!\n fFieldOnQBigObject: Int!\n gFieldOnQBigObject: Boolean!\n hFieldOnQBigObject: Float!\n iFieldOnQBigObject: String!\n jFieldOnQBigObject: Int!\n kFieldOnQBigObject: Boolean!\n lFieldOnQBigObject: Float!\n mFieldOnQBigObject: String!\n nFieldOnQBigObject: Int!\n oFieldOnQBigObject: Boolean!\n pFieldOnQBigObject: Float!\n qFieldOnQBigObject: String!\n rFieldOnQBigObject: Int!\n sFieldOnQBigObject: Boolean!\n tFieldOnQBigObject: Float!\n uFieldOnQBigObject: String!\n vFieldOnQBigObject: Int!\n wFieldOnQBigObject: Boolean!\n xFieldOnQBigObject: Float!\n yFieldOnQBigObject: String!\n zFieldOnQBigObject: Int!\n}\n\ntype Query {\n bigAbstractResponse: BigAbstractResponse\n bigResponse(artificialDelay: Int! = 0, bigObjects: Int! = 100, deeplyNestedObjects: Int! = 100, nestedObjects: Int! = 100): [BigObject!]!\n \"\"\"Returns response after the given delay\"\"\"\n delay(ms: Int!, response: String!): String!\n floatField(arg: Float): Float\n \"\"\"Returns the value of the received HTTP header.\"\"\"\n headerValue(name: String!): String!\n \"\"\"Returns the value of the given key in the WS initial payload.\"\"\"\n initPayloadValue(key: String!): String!\n initialPayload: Map\n longResponse(artificialDelay: Int! = 0, bytes: Int!): String\n rootFieldWithInput(arg: InputArg!): String!\n rootFieldWithListArg(arg: [String!]!): [String!]!\n rootFieldWithListOfEnumArg(arg: [EnumType!]!): [EnumType!]!\n rootFieldWithListOfInputArg(arg: [InputType!]!): [InputResponse!]!\n rootFieldWithNestedListArg(arg: [[String!]!]!): [[String!]!]!\n secret: Secret @requiresScopes(scopes: [[\"read:secret\"]])\n sharedThings(numOfA: Int!, numOfB: Int!): [Thing!]! @shareable\n}\n\ntype RBigObject {\n aFieldOnRBigObject: String!\n bFieldOnRBigObject: Int!\n cFieldOnRBigObject: Boolean!\n dFieldOnRBigObject: Float!\n eFieldOnRBigObject: String!\n fFieldOnRBigObject: Int!\n gFieldOnRBigObject: Boolean!\n hFieldOnRBigObject: Float!\n iFieldOnRBigObject: String!\n jFieldOnRBigObject: Int!\n kFieldOnRBigObject: Boolean!\n lFieldOnRBigObject: Float!\n mFieldOnRBigObject: String!\n nFieldOnRBigObject: Int!\n oFieldOnRBigObject: Boolean!\n pFieldOnRBigObject: Float!\n qFieldOnRBigObject: String!\n rFieldOnRBigObject: Int!\n sFieldOnRBigObject: Boolean!\n tFieldOnRBigObject: Float!\n uFieldOnRBigObject: String!\n vFieldOnRBigObject: Int!\n wFieldOnRBigObject: Boolean!\n xFieldOnRBigObject: Float!\n yFieldOnRBigObject: String!\n zFieldOnRBigObject: Int!\n}\n\ntype SBigObject {\n aFieldOnSBigObject: String!\n bFieldOnSBigObject: Int!\n cFieldOnSBigObject: Boolean!\n dFieldOnSBigObject: Float!\n eFieldOnSBigObject: String!\n fFieldOnSBigObject: Int!\n gFieldOnSBigObject: Boolean!\n hFieldOnSBigObject: Float!\n iFieldOnSBigObject: String!\n jFieldOnSBigObject: Int!\n kFieldOnSBigObject: Boolean!\n lFieldOnSBigObject: Float!\n mFieldOnSBigObject: String!\n nFieldOnSBigObject: Int!\n oFieldOnSBigObject: Boolean!\n pFieldOnSBigObject: Float!\n qFieldOnSBigObject: String!\n rFieldOnSBigObject: Int!\n sFieldOnSBigObject: Boolean!\n tFieldOnSBigObject: Float!\n uFieldOnSBigObject: String!\n vFieldOnSBigObject: Int!\n wFieldOnSBigObject: Boolean!\n xFieldOnSBigObject: Float!\n yFieldOnSBigObject: String!\n zFieldOnSBigObject: Int!\n}\n\ntype Secret {\n value: String\n}\n\ntype SubscribeMetadata {\n initialPayload: Map\n subscribeExtensions: Map\n}\n\ntype Subscription {\n \"\"\"Returns a stream with the value of the received HTTP header.\"\"\"\n headerValue(name: String!, repeat: Int): TimestampedString!\n \"\"\"\n Returns a stream with the value of value of the given key in the WS initial payload.\n \"\"\"\n initPayloadValue(key: String!, repeat: Int): TimestampedString!\n \"\"\"Returns a stream with the value of the WS initial payload.\"\"\"\n initialPayload(repeat: Int): Map\n \"\"\"\n Returns a stream with the values of the WS initial payload and subscribe extensions\n \"\"\"\n metadata(repeat: Int! = 1): SubscribeMetadata!\n returnsError: String!\n}\n\ntype TBigObject {\n aFieldOnTBigObject: String!\n bFieldOnTBigObject: Int!\n cFieldOnTBigObject: Boolean!\n dFieldOnTBigObject: Float!\n eFieldOnTBigObject: String!\n fFieldOnTBigObject: Int!\n gFieldOnTBigObject: Boolean!\n hFieldOnTBigObject: Float!\n iFieldOnTBigObject: String!\n jFieldOnTBigObject: Int!\n kFieldOnTBigObject: Boolean!\n lFieldOnTBigObject: Float!\n mFieldOnTBigObject: String!\n nFieldOnTBigObject: Int!\n oFieldOnTBigObject: Boolean!\n pFieldOnTBigObject: Float!\n qFieldOnTBigObject: String!\n rFieldOnTBigObject: Int!\n sFieldOnTBigObject: Boolean!\n tFieldOnTBigObject: Float!\n uFieldOnTBigObject: String!\n vFieldOnTBigObject: Int!\n wFieldOnTBigObject: Boolean!\n xFieldOnTBigObject: Float!\n yFieldOnTBigObject: String!\n zFieldOnTBigObject: Int!\n}\n\ntype Thing {\n b: String! @shareable\n}\n\ntype TimestampedString {\n extensions: Map\n initialPayload: Map\n \"\"\"Sequence number\"\"\"\n seq: Int!\n \"\"\"Total number of responses to be sent\"\"\"\n total: Int!\n \"\"\"The timestamp when the response was generated.\"\"\"\n unixTime: Int!\n \"\"\"The value of the string.\"\"\"\n value: String!\n}\n\ntype UBigObject {\n aFieldOnUBigObject: String!\n bFieldOnUBigObject: Int!\n cFieldOnUBigObject: Boolean!\n dFieldOnUBigObject: Float!\n eFieldOnUBigObject: String!\n fFieldOnUBigObject: Int!\n gFieldOnUBigObject: Boolean!\n hFieldOnUBigObject: Float!\n iFieldOnUBigObject: String!\n jFieldOnUBigObject: Int!\n kFieldOnUBigObject: Boolean!\n lFieldOnUBigObject: Float!\n mFieldOnUBigObject: String!\n nFieldOnUBigObject: Int!\n oFieldOnUBigObject: Boolean!\n pFieldOnUBigObject: Float!\n qFieldOnUBigObject: String!\n rFieldOnUBigObject: Int!\n sFieldOnUBigObject: Boolean!\n tFieldOnUBigObject: Float!\n uFieldOnUBigObject: String!\n vFieldOnUBigObject: Int!\n wFieldOnUBigObject: Boolean!\n xFieldOnUBigObject: Float!\n yFieldOnUBigObject: String!\n zFieldOnUBigObject: Int!\n}\n\ntype VBigObject {\n aFieldOnVBigObject: String!\n bFieldOnVBigObject: Int!\n cFieldOnVBigObject: Boolean!\n dFieldOnVBigObject: Float!\n eFieldOnVBigObject: String!\n fFieldOnVBigObject: Int!\n gFieldOnVBigObject: Boolean!\n hFieldOnVBigObject: Float!\n iFieldOnVBigObject: String!\n jFieldOnVBigObject: Int!\n kFieldOnVBigObject: Boolean!\n lFieldOnVBigObject: Float!\n mFieldOnVBigObject: String!\n nFieldOnVBigObject: Int!\n oFieldOnVBigObject: Boolean!\n pFieldOnVBigObject: Float!\n qFieldOnVBigObject: String!\n rFieldOnVBigObject: Int!\n sFieldOnVBigObject: Boolean!\n tFieldOnVBigObject: Float!\n uFieldOnVBigObject: String!\n vFieldOnVBigObject: Int!\n wFieldOnVBigObject: Boolean!\n xFieldOnVBigObject: Float!\n yFieldOnVBigObject: String!\n zFieldOnVBigObject: Int!\n}\n\ntype WBigObject {\n aFieldOnWBigObject: String!\n bFieldOnWBigObject: Int!\n cFieldOnWBigObject: Boolean!\n dFieldOnWBigObject: Float!\n eFieldOnWBigObject: String!\n fFieldOnWBigObject: Int!\n gFieldOnWBigObject: Boolean!\n hFieldOnWBigObject: Float!\n iFieldOnWBigObject: String!\n jFieldOnWBigObject: Int!\n kFieldOnWBigObject: Boolean!\n lFieldOnWBigObject: Float!\n mFieldOnWBigObject: String!\n nFieldOnWBigObject: Int!\n oFieldOnWBigObject: Boolean!\n pFieldOnWBigObject: Float!\n qFieldOnWBigObject: String!\n rFieldOnWBigObject: Int!\n sFieldOnWBigObject: Boolean!\n tFieldOnWBigObject: Float!\n uFieldOnWBigObject: String!\n vFieldOnWBigObject: Int!\n wFieldOnWBigObject: Boolean!\n xFieldOnWBigObject: Float!\n yFieldOnWBigObject: String!\n zFieldOnWBigObject: Int!\n}\n\ntype XBigObject {\n aFieldOnXBigObject: String!\n bFieldOnXBigObject: Int!\n cFieldOnXBigObject: Boolean!\n dFieldOnXBigObject: Float!\n eFieldOnXBigObject: String!\n fFieldOnXBigObject: Int!\n gFieldOnXBigObject: Boolean!\n hFieldOnXBigObject: Float!\n iFieldOnXBigObject: String!\n jFieldOnXBigObject: Int!\n kFieldOnXBigObject: Boolean!\n lFieldOnXBigObject: Float!\n mFieldOnXBigObject: String!\n nFieldOnXBigObject: Int!\n oFieldOnXBigObject: Boolean!\n pFieldOnXBigObject: Float!\n qFieldOnXBigObject: String!\n rFieldOnXBigObject: Int!\n sFieldOnXBigObject: Boolean!\n tFieldOnXBigObject: Float!\n uFieldOnXBigObject: String!\n vFieldOnXBigObject: Int!\n wFieldOnXBigObject: Boolean!\n xFieldOnXBigObject: Float!\n yFieldOnXBigObject: String!\n zFieldOnXBigObject: Int!\n}\n\ntype YBigObject {\n aFieldOnYBigObject: String!\n bFieldOnYBigObject: Int!\n cFieldOnYBigObject: Boolean!\n dFieldOnYBigObject: Float!\n eFieldOnYBigObject: String!\n fFieldOnYBigObject: Int!\n gFieldOnYBigObject: Boolean!\n hFieldOnYBigObject: Float!\n iFieldOnYBigObject: String!\n jFieldOnYBigObject: Int!\n kFieldOnYBigObject: Boolean!\n lFieldOnYBigObject: Float!\n mFieldOnYBigObject: String!\n nFieldOnYBigObject: Int!\n oFieldOnYBigObject: Boolean!\n pFieldOnYBigObject: Float!\n qFieldOnYBigObject: String!\n rFieldOnYBigObject: Int!\n sFieldOnYBigObject: Boolean!\n tFieldOnYBigObject: Float!\n uFieldOnYBigObject: String!\n vFieldOnYBigObject: Int!\n wFieldOnYBigObject: Boolean!\n xFieldOnYBigObject: Float!\n yFieldOnYBigObject: String!\n zFieldOnYBigObject: Int!\n}\n\ntype ZBigObject {\n aFieldOnZBigObject: String!\n bFieldOnZBigObject: Int!\n cFieldOnZBigObject: Boolean!\n dFieldOnZBigObject: Float!\n eFieldOnZBigObject: String!\n fFieldOnZBigObject: Int!\n gFieldOnZBigObject: Boolean!\n hFieldOnZBigObject: Float!\n iFieldOnZBigObject: String!\n jFieldOnZBigObject: Int!\n kFieldOnZBigObject: Boolean!\n lFieldOnZBigObject: Float!\n mFieldOnZBigObject: String!\n nFieldOnZBigObject: Int!\n oFieldOnZBigObject: Boolean!\n pFieldOnZBigObject: Float!\n qFieldOnZBigObject: String!\n rFieldOnZBigObject: Int!\n sFieldOnZBigObject: Boolean!\n tFieldOnZBigObject: Float!\n uFieldOnZBigObject: String!\n vFieldOnZBigObject: Int!\n wFieldOnZBigObject: Boolean!\n xFieldOnZBigObject: Float!\n yFieldOnZBigObject: String!\n zFieldOnZBigObject: Int!\n}\n\nscalar link__Import\n\nenum link__Purpose {\n EXECUTION\n SECURITY\n}\n\nscalar openfed__FieldSet\n\nscalar openfed__Scope",
"865e365ca4e3de8aec4ccd25e875ca9a82a7edde": "schema {\n mutation: Mutation\n}\n\ndirective @key(fields: openfed__FieldSet!, resolvable: Boolean = true) repeatable on INTERFACE | OBJECT\n\ndirective @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA\n\ntype Employee @key(fields: \"id\") {\n id: Int!\n isAvailable: Boolean\n}\n\ntype Mutation {\n \"\"\" This mutation updates the availability status of an employee in the system.\n \"\"\"\n updateAvailability(employeeID: Int!, isAvailable: Boolean!): Employee!\n}\n\nscalar link__Import\n\nenum link__Purpose {\n EXECUTION\n SECURITY\n}\n\nscalar openfed__FieldSet",
"10eccb92890a5709d24ac8c1293264d758b997c7": "schema {\n mutation: Mutation\n}\n\ndirective @inaccessible on ARGUMENT_DEFINITION | ENUM | ENUM_VALUE | FIELD_DEFINITION | INPUT_FIELD_DEFINITION | INPUT_OBJECT | INTERFACE | OBJECT | SCALAR | UNION\n\ndirective @key(fields: openfed__FieldSet!, resolvable: Boolean = true) repeatable on INTERFACE | OBJECT\n\ndirective @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA\n\ntype Employee @key(fields: \"id\") {\n currentMood: Mood!\n id: Int!\n}\n\nenum Mood {\n APATHETIC @inaccessible\n HAPPY\n SAD\n}\n\ntype Mutation {\n \"\"\" This mutation update the mood of an employee. \"\"\"\n updateMood(employeeID: Int!, mood: Mood!): Employee!\n}\n\nscalar link__Import\n\nenum link__Purpose {\n EXECUTION\n SECURITY\n}\n\nscalar openfed__FieldSet",
"0c7a814514a54c0b54af7ea5fa33730a321921e6": "directive @key(fields: openfed__FieldSet!, resolvable: Boolean = true) repeatable on INTERFACE | OBJECT\n\ndirective @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA\n\ntype Country @key(fields: \"key { name }\") {\n key: CountryKey!\n language: String\n}\n\ntype CountryKey {\n name: String!\n}\n\nscalar link__Import\n\nenum link__Purpose {\n EXECUTION\n SECURITY\n}\n\nscalar openfed__FieldSet"
},
- "graphqlClientSchema": "type Query {\n employee(id: Int!): Employee\n employeeAsList(id: Int!): [Employee]\n employees: [Employee]\n products: [Products!]!\n teammates(team: Department!): [Employee!]!\n firstEmployee: Employee!\n findEmployeesBy(criteria: FindEmployeeCriteria!): [Employee!]!\n\n \"\"\" This is a GraphQL query that retrieves a list of employees.\"\"\"\n findEmployees(criteria: SearchInput): [Employee!]!\n productTypes: [Products!]!\n topSecretFederationFacts: [TopSecretFact!]!\n factTypes: [TopSecretFactType!]\n\n \"\"\"Returns the value of the received HTTP header.\"\"\"\n headerValue(name: String!): String!\n\n \"\"\"Returns the value of the given key in the WS initial payload.\"\"\"\n initPayloadValue(key: String!): String!\n initialPayload: Map\n\n \"\"\"Returns response after the given delay\"\"\"\n delay(response: String!, ms: Int!): String!\n bigResponse(artificialDelay: Int! = 0, bigObjects: Int! = 100, nestedObjects: Int! = 100, deeplyNestedObjects: Int! = 100): [BigObject!]!\n longResponse(artificialDelay: Int! = 0, bytes: Int!): String\n bigAbstractResponse: BigAbstractResponse\n rootFieldWithListArg(arg: [String!]!): [String!]!\n rootFieldWithNestedListArg(arg: [[String!]!]!): [[String!]!]!\n rootFieldWithListOfInputArg(arg: [InputType!]!): [InputResponse!]!\n rootFieldWithListOfEnumArg(arg: [EnumType!]!): [EnumType!]!\n rootFieldWithInput(arg: InputArg!): String!\n floatField(arg: Float): Float\n sharedThings(numOfA: Int!, numOfB: Int!): [Thing!]!\n secret: Secret\n}\n\nscalar Upload\n\ntype Mutation {\n updateEmployeeTag(id: Int!, tag: String!): Employee\n singleUpload(file: Upload!): Boolean!\n singleUploadWithInput(arg: FileUpload!): Boolean!\n multipleUpload(files: [Upload!]!): Boolean!\n addFact(fact: TopSecretFactInput!): TopSecretFact!\n\n \"\"\" This mutation updates the availability status of an employee in the system.\n \"\"\"\n updateAvailability(employeeID: Int!, isAvailable: Boolean!): Employee!\n\n \"\"\" This mutation update the mood of an employee. \"\"\"\n updateMood(employeeID: Int!, mood: Mood!): Employee!\n}\n\ninput FileUpload {\n nested: DeeplyNestedFileUpload\n nestedList: [Upload!]\n}\n\ninput DeeplyNestedFileUpload {\n file: Upload!\n}\n\ntype Subscription {\n \"\"\"`currentTime` will return a stream of `Time` objects.\"\"\"\n currentTime: Time!\n countEmp(max: Int!, intervalMilliseconds: Int!): Int!\n countEmp2(max: Int!, intervalMilliseconds: Int!): Int!\n countFor(count: Int!): Int!\n countHob(max: Int!, intervalMilliseconds: Int!): Int!\n\n \"\"\"Returns a stream with the value of the received HTTP header.\"\"\"\n headerValue(name: String!, repeat: Int): TimestampedString!\n\n \"\"\"\n Returns a stream with the value of value of the given key in the WS initial payload.\n \"\"\"\n initPayloadValue(key: String!, repeat: Int): TimestampedString!\n\n \"\"\"Returns a stream with the value of the WS initial payload.\"\"\"\n initialPayload(repeat: Int): Map\n returnsError: String\n}\n\nenum Department {\n ENGINEERING\n MARKETING\n OPERATIONS\n}\n\ninterface RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n}\n\nenum EngineerType {\n BACKEND\n FRONTEND\n FULLSTACK\n}\n\ninterface Identifiable {\n id: Int!\n}\n\nenum OperationType {\n FINANCE\n HUMAN_RESOURCES\n}\n\ntype Details {\n forename: String!\n location: Country!\n surname: String!\n pastLocations: [City!]!\n middlename: String @deprecated\n hasChildren: Boolean!\n maritalStatus: MaritalStatus\n nationality: Nationality!\n pets: [Pet]\n}\n\ntype City {\n type: String!\n name: String!\n country: Country\n}\n\ntype Country {\n key: CountryKey!\n language: String\n}\n\ntype CountryKey {\n name: String!\n}\n\nenum Mood {\n HAPPY\n SAD\n}\n\ntype ErrorWrapper {\n okField: String\n errorField: String\n}\n\ntype Time {\n unixTime: Int!\n timeStamp: String!\n}\n\nunion Products = Consultancy | Cosmo | SDK | Documentation\n\ninterface IProduct {\n upc: ID!\n engineers: [Employee!]!\n}\n\ntype Consultancy {\n upc: ID!\n lead: Employee!\n isLeadAvailable: Boolean\n name: ProductName!\n}\n\ninterface EmployeeWorkItem {\n name: String!\n priority: Int!\n}\n\ntype WorkItemHandler {\n name: String!\n assignedItem: EmployeeWorkItem!\n}\n\ntype TechnicalSpecs {\n name: String!\n complexity: Float!\n metrics: WorkMetrics!\n}\n\ntype ManagementSpecs {\n name: String!\n scope: Float!\n metrics: WorkMetrics!\n}\n\ntype WorkMetrics {\n score: Float!\n efficiency: Float!\n}\n\nunion WorkReviewResult = WorkApproval | WorkRejection\n\ntype WorkApproval {\n comment: String!\n approvedAt: String!\n}\n\ntype WorkRejection {\n reason: String!\n rejectionCode: String!\n}\n\ntype WorkSetup {\n priority: String!\n primaryItem: EmployeeWorkItem!\n}\n\ninput FindEmployeeCriteria @oneOf {\n id: Int\n department: Department\n title: String\n}\n\nenum Class {\n FISH\n MAMMAL\n REPTILE\n}\n\nenum Gender {\n FEMALE\n MALE\n UNKNOWN\n}\n\ninterface Animal {\n class: Class!\n gender: Gender!\n}\n\nenum CatType {\n HOME\n STREET\n}\n\nenum DogBreed {\n GOLDEN_RETRIEVER\n POODLE\n ROTTWEILER\n YORKSHIRE_TERRIER\n}\n\nenum MaritalStatus {\n ENGAGED\n MARRIED\n}\n\nenum Nationality {\n AMERICAN\n DUTCH\n ENGLISH\n GERMAN\n INDIAN\n SPANISH\n UKRAINIAN\n}\n\n\"\"\" Allows to filter employees by their details. \"\"\"\ninput SearchInput {\n hasPets: Boolean\n nationality: Nationality\n nested: NestedSearchInput\n}\n\ninput NestedSearchInput {\n maritalStatus: MaritalStatus\n hasChildren: Boolean\n}\n\nenum ExerciseType {\n CALISTHENICS\n HIKING\n SPORT\n STRENGTH_TRAINING\n}\n\ninterface Experience {\n yearsOfExperience: Float!\n}\n\nenum GameGenre {\n ADVENTURE\n BOARD\n FPS\n CARD\n RPG\n ROGUELITE\n SIMULATION\n STRATEGY\n}\n\nenum ProgrammingLanguage {\n CSHARP\n GO\n RUST\n TYPESCRIPT\n}\n\ninterface Hobby {\n employees: [Employee!]!\n}\n\ninput TopSecretFactInput {\n title: String!\n description: FactContent!\n factType: TopSecretFactType!\n}\n\nenum TopSecretFactType {\n DIRECTIVE\n ENTITY\n MISCELLANEOUS\n}\n\ninterface TopSecretFact {\n description: FactContent!\n factType: TopSecretFactType\n}\n\nscalar FactContent\n\nenum ProductName {\n CONSULTANCY\n COSMO\n ENGINE\n FINANCE\n HUMAN_RESOURCES\n MARKETING\n SDK\n}\n\ntype Documentation {\n url(product: ProductName!): String!\n urls(products: [ProductName!]!): [String!]!\n}\n\ntype Secret {\n value: String\n}\n\ntype Thing {\n b: String!\n}\n\ninput InputArg {\n enums: [EnumType!]\n enum: EnumType\n string: String\n strings: [String!]\n}\n\nenum EnumType {\n A\n B\n C\n}\n\ninput InputType {\n arg: String!\n}\n\ntype InputResponse {\n arg: String!\n}\n\nscalar Map\n\ntype TimestampedString {\n \"\"\"The value of the string.\"\"\"\n value: String!\n\n \"\"\"The timestamp when the response was generated.\"\"\"\n unixTime: Int!\n\n \"\"\"Sequence number\"\"\"\n seq: Int!\n\n \"\"\"Total number of responses to be sent\"\"\"\n total: Int!\n initialPayload: Map\n}\n\ntype BigObject {\n nestedObjects: [NestedObject!]!\n}\n\ntype NestedObject {\n deeplyNestedObjects: [DeeplyNestedObject!]!\n}\n\ntype DeeplyNestedObject {\n aFieldOnDeeplyNestedObject: String!\n bFieldOnDeeplyNestedObject: Int!\n cFieldOnDeeplyNestedObject: Boolean!\n dFieldOnDeeplyNestedObject: Float!\n eFieldOnDeeplyNestedObject: String!\n fFieldOnDeeplyNestedObject: Int!\n gFieldOnDeeplyNestedObject: Boolean!\n hFieldOnDeeplyNestedObject: Float!\n iFieldOnDeeplyNestedObject: String!\n jFieldOnDeeplyNestedObject: Int!\n kFieldOnDeeplyNestedObject: Boolean!\n lFieldOnDeeplyNestedObject: Float!\n mFieldOnDeeplyNestedObject: String!\n nFieldOnDeeplyNestedObject: Int!\n oFieldOnDeeplyNestedObject: Boolean!\n pFieldOnDeeplyNestedObject: Float!\n qFieldOnDeeplyNestedObject: String!\n rFieldOnDeeplyNestedObject: Int!\n sFieldOnDeeplyNestedObject: Boolean!\n tFieldOnDeeplyNestedObject: Float!\n uFieldOnDeeplyNestedObject: String!\n vFieldOnDeeplyNestedObject: Int!\n wFieldOnDeeplyNestedObject: Boolean!\n xFieldOnDeeplyNestedObject: Float!\n yFieldOnDeeplyNestedObject: String!\n zFieldOnDeeplyNestedObject: Int!\n}\n\nunion BigAbstractResponse = ABigObject | BBigObject | CBigObject | DBigObject | EBigObject | FBigObject | GBigObject | HBigObject | IBigObject | JBigObject | KBigObject | LBigObject | MBigObject | NBigObject | OBigObject | PBigObject | QBigObject | RBigObject | SBigObject | TBigObject | UBigObject | VBigObject | WBigObject | XBigObject | YBigObject | ZBigObject\n\ntype ABigObject {\n aFieldOnABigObject: String!\n bFieldOnABigObject: Int!\n cFieldOnABigObject: Boolean!\n dFieldOnABigObject: Float!\n eFieldOnABigObject: String!\n fFieldOnABigObject: Int!\n gFieldOnABigObject: Boolean!\n hFieldOnABigObject: Float!\n iFieldOnABigObject: String!\n jFieldOnABigObject: Int!\n kFieldOnABigObject: Boolean!\n lFieldOnABigObject: Float!\n mFieldOnABigObject: String!\n nFieldOnABigObject: Int!\n oFieldOnABigObject: Boolean!\n pFieldOnABigObject: Float!\n qFieldOnABigObject: String!\n rFieldOnABigObject: Int!\n sFieldOnABigObject: Boolean!\n tFieldOnABigObject: Float!\n uFieldOnABigObject: String!\n vFieldOnABigObject: Int!\n wFieldOnABigObject: Boolean!\n xFieldOnABigObject: Float!\n yFieldOnABigObject: String!\n zFieldOnABigObject: Int!\n}\n\ntype BBigObject {\n aFieldOnBBigObject: String!\n bFieldOnBBigObject: Int!\n cFieldOnBBigObject: Boolean!\n dFieldOnBBigObject: Float!\n eFieldOnBBigObject: String!\n fFieldOnBBigObject: Int!\n gFieldOnBBigObject: Boolean!\n hFieldOnBBigObject: Float!\n iFieldOnBBigObject: String!\n jFieldOnBBigObject: Int!\n kFieldOnBBigObject: Boolean!\n lFieldOnBBigObject: Float!\n mFieldOnBBigObject: String!\n nFieldOnBBigObject: Int!\n oFieldOnBBigObject: Boolean!\n pFieldOnBBigObject: Float!\n qFieldOnBBigObject: String!\n rFieldOnBBigObject: Int!\n sFieldOnBBigObject: Boolean!\n tFieldOnBBigObject: Float!\n uFieldOnBBigObject: String!\n vFieldOnBBigObject: Int!\n wFieldOnBBigObject: Boolean!\n xFieldOnBBigObject: Float!\n yFieldOnBBigObject: String!\n zFieldOnBBigObject: Int!\n}\n\ntype CBigObject {\n aFieldOnCBigObject: String!\n bFieldOnCBigObject: Int!\n cFieldOnCBigObject: Boolean!\n dFieldOnCBigObject: Float!\n eFieldOnCBigObject: String!\n fFieldOnCBigObject: Int!\n gFieldOnCBigObject: Boolean!\n hFieldOnCBigObject: Float!\n iFieldOnCBigObject: String!\n jFieldOnCBigObject: Int!\n kFieldOnCBigObject: Boolean!\n lFieldOnCBigObject: Float!\n mFieldOnCBigObject: String!\n nFieldOnCBigObject: Int!\n oFieldOnCBigObject: Boolean!\n pFieldOnCBigObject: Float!\n qFieldOnCBigObject: String!\n rFieldOnCBigObject: Int!\n sFieldOnCBigObject: Boolean!\n tFieldOnCBigObject: Float!\n uFieldOnCBigObject: String!\n vFieldOnCBigObject: Int!\n wFieldOnCBigObject: Boolean!\n xFieldOnCBigObject: Float!\n yFieldOnCBigObject: String!\n zFieldOnCBigObject: Int!\n}\n\ntype DBigObject {\n aFieldOnDBigObject: String!\n bFieldOnDBigObject: Int!\n cFieldOnDBigObject: Boolean!\n dFieldOnDBigObject: Float!\n eFieldOnDBigObject: String!\n fFieldOnDBigObject: Int!\n gFieldOnDBigObject: Boolean!\n hFieldOnDBigObject: Float!\n iFieldOnDBigObject: String!\n jFieldOnDBigObject: Int!\n kFieldOnDBigObject: Boolean!\n lFieldOnDBigObject: Float!\n mFieldOnDBigObject: String!\n nFieldOnDBigObject: Int!\n oFieldOnDBigObject: Boolean!\n pFieldOnDBigObject: Float!\n qFieldOnDBigObject: String!\n rFieldOnDBigObject: Int!\n sFieldOnDBigObject: Boolean!\n tFieldOnDBigObject: Float!\n uFieldOnDBigObject: String!\n vFieldOnDBigObject: Int!\n wFieldOnDBigObject: Boolean!\n xFieldOnDBigObject: Float!\n yFieldOnDBigObject: String!\n zFieldOnDBigObject: Int!\n}\n\ntype EBigObject {\n aFieldOnEBigObject: String!\n bFieldOnEBigObject: Int!\n cFieldOnEBigObject: Boolean!\n dFieldOnEBigObject: Float!\n eFieldOnEBigObject: String!\n fFieldOnEBigObject: Int!\n gFieldOnEBigObject: Boolean!\n hFieldOnEBigObject: Float!\n iFieldOnEBigObject: String!\n jFieldOnEBigObject: Int!\n kFieldOnEBigObject: Boolean!\n lFieldOnEBigObject: Float!\n mFieldOnEBigObject: String!\n nFieldOnEBigObject: Int!\n oFieldOnEBigObject: Boolean!\n pFieldOnEBigObject: Float!\n qFieldOnEBigObject: String!\n rFieldOnEBigObject: Int!\n sFieldOnEBigObject: Boolean!\n tFieldOnEBigObject: Float!\n uFieldOnEBigObject: String!\n vFieldOnEBigObject: Int!\n wFieldOnEBigObject: Boolean!\n xFieldOnEBigObject: Float!\n yFieldOnEBigObject: String!\n zFieldOnEBigObject: Int!\n}\n\ntype FBigObject {\n aFieldOnFBigObject: String!\n bFieldOnFBigObject: Int!\n cFieldOnFBigObject: Boolean!\n dFieldOnFBigObject: Float!\n eFieldOnFBigObject: String!\n fFieldOnFBigObject: Int!\n gFieldOnFBigObject: Boolean!\n hFieldOnFBigObject: Float!\n iFieldOnFBigObject: String!\n jFieldOnFBigObject: Int!\n kFieldOnFBigObject: Boolean!\n lFieldOnFBigObject: Float!\n mFieldOnFBigObject: String!\n nFieldOnFBigObject: Int!\n oFieldOnFBigObject: Boolean!\n pFieldOnFBigObject: Float!\n qFieldOnFBigObject: String!\n rFieldOnFBigObject: Int!\n sFieldOnFBigObject: Boolean!\n tFieldOnFBigObject: Float!\n uFieldOnFBigObject: String!\n vFieldOnFBigObject: Int!\n wFieldOnFBigObject: Boolean!\n xFieldOnFBigObject: Float!\n yFieldOnFBigObject: String!\n zFieldOnFBigObject: Int!\n}\n\ntype GBigObject {\n aFieldOnGBigObject: String!\n bFieldOnGBigObject: Int!\n cFieldOnGBigObject: Boolean!\n dFieldOnGBigObject: Float!\n eFieldOnGBigObject: String!\n fFieldOnGBigObject: Int!\n gFieldOnGBigObject: Boolean!\n hFieldOnGBigObject: Float!\n iFieldOnGBigObject: String!\n jFieldOnGBigObject: Int!\n kFieldOnGBigObject: Boolean!\n lFieldOnGBigObject: Float!\n mFieldOnGBigObject: String!\n nFieldOnGBigObject: Int!\n oFieldOnGBigObject: Boolean!\n pFieldOnGBigObject: Float!\n qFieldOnGBigObject: String!\n rFieldOnGBigObject: Int!\n sFieldOnGBigObject: Boolean!\n tFieldOnGBigObject: Float!\n uFieldOnGBigObject: String!\n vFieldOnGBigObject: Int!\n wFieldOnGBigObject: Boolean!\n xFieldOnGBigObject: Float!\n yFieldOnGBigObject: String!\n zFieldOnGBigObject: Int!\n}\n\ntype HBigObject {\n aFieldOnHBigObject: String!\n bFieldOnHBigObject: Int!\n cFieldOnHBigObject: Boolean!\n dFieldOnHBigObject: Float!\n eFieldOnHBigObject: String!\n fFieldOnHBigObject: Int!\n gFieldOnHBigObject: Boolean!\n hFieldOnHBigObject: Float!\n iFieldOnHBigObject: String!\n jFieldOnHBigObject: Int!\n kFieldOnHBigObject: Boolean!\n lFieldOnHBigObject: Float!\n mFieldOnHBigObject: String!\n nFieldOnHBigObject: Int!\n oFieldOnHBigObject: Boolean!\n pFieldOnHBigObject: Float!\n qFieldOnHBigObject: String!\n rFieldOnHBigObject: Int!\n sFieldOnHBigObject: Boolean!\n tFieldOnHBigObject: Float!\n uFieldOnHBigObject: String!\n vFieldOnHBigObject: Int!\n wFieldOnHBigObject: Boolean!\n xFieldOnHBigObject: Float!\n yFieldOnHBigObject: String!\n zFieldOnHBigObject: Int!\n}\n\ntype IBigObject {\n aFieldOnIBigObject: String!\n bFieldOnIBigObject: Int!\n cFieldOnIBigObject: Boolean!\n dFieldOnIBigObject: Float!\n eFieldOnIBigObject: String!\n fFieldOnIBigObject: Int!\n gFieldOnIBigObject: Boolean!\n hFieldOnIBigObject: Float!\n iFieldOnIBigObject: String!\n jFieldOnIBigObject: Int!\n kFieldOnIBigObject: Boolean!\n lFieldOnIBigObject: Float!\n mFieldOnIBigObject: String!\n nFieldOnIBigObject: Int!\n oFieldOnIBigObject: Boolean!\n pFieldOnIBigObject: Float!\n qFieldOnIBigObject: String!\n rFieldOnIBigObject: Int!\n sFieldOnIBigObject: Boolean!\n tFieldOnIBigObject: Float!\n uFieldOnIBigObject: String!\n vFieldOnIBigObject: Int!\n wFieldOnIBigObject: Boolean!\n xFieldOnIBigObject: Float!\n yFieldOnIBigObject: String!\n zFieldOnIBigObject: Int!\n}\n\ntype JBigObject {\n aFieldOnJBigObject: String!\n bFieldOnJBigObject: Int!\n cFieldOnJBigObject: Boolean!\n dFieldOnJBigObject: Float!\n eFieldOnJBigObject: String!\n fFieldOnJBigObject: Int!\n gFieldOnJBigObject: Boolean!\n hFieldOnJBigObject: Float!\n iFieldOnJBigObject: String!\n jFieldOnJBigObject: Int!\n kFieldOnJBigObject: Boolean!\n lFieldOnJBigObject: Float!\n mFieldOnJBigObject: String!\n nFieldOnJBigObject: Int!\n oFieldOnJBigObject: Boolean!\n pFieldOnJBigObject: Float!\n qFieldOnJBigObject: String!\n rFieldOnJBigObject: Int!\n sFieldOnJBigObject: Boolean!\n tFieldOnJBigObject: Float!\n uFieldOnJBigObject: String!\n vFieldOnJBigObject: Int!\n wFieldOnJBigObject: Boolean!\n xFieldOnJBigObject: Float!\n yFieldOnJBigObject: String!\n zFieldOnJBigObject: Int!\n}\n\ntype KBigObject {\n aFieldOnKBigObject: String!\n bFieldOnKBigObject: Int!\n cFieldOnKBigObject: Boolean!\n dFieldOnKBigObject: Float!\n eFieldOnKBigObject: String!\n fFieldOnKBigObject: Int!\n gFieldOnKBigObject: Boolean!\n hFieldOnKBigObject: Float!\n iFieldOnKBigObject: String!\n jFieldOnKBigObject: Int!\n kFieldOnKBigObject: Boolean!\n lFieldOnKBigObject: Float!\n mFieldOnKBigObject: String!\n nFieldOnKBigObject: Int!\n oFieldOnKBigObject: Boolean!\n pFieldOnKBigObject: Float!\n qFieldOnKBigObject: String!\n rFieldOnKBigObject: Int!\n sFieldOnKBigObject: Boolean!\n tFieldOnKBigObject: Float!\n uFieldOnKBigObject: String!\n vFieldOnKBigObject: Int!\n wFieldOnKBigObject: Boolean!\n xFieldOnKBigObject: Float!\n yFieldOnKBigObject: String!\n zFieldOnKBigObject: Int!\n}\n\ntype LBigObject {\n aFieldOnLBigObject: String!\n bFieldOnLBigObject: Int!\n cFieldOnLBigObject: Boolean!\n dFieldOnLBigObject: Float!\n eFieldOnLBigObject: String!\n fFieldOnLBigObject: Int!\n gFieldOnLBigObject: Boolean!\n hFieldOnLBigObject: Float!\n iFieldOnLBigObject: String!\n jFieldOnLBigObject: Int!\n kFieldOnLBigObject: Boolean!\n lFieldOnLBigObject: Float!\n mFieldOnLBigObject: String!\n nFieldOnLBigObject: Int!\n oFieldOnLBigObject: Boolean!\n pFieldOnLBigObject: Float!\n qFieldOnLBigObject: String!\n rFieldOnLBigObject: Int!\n sFieldOnLBigObject: Boolean!\n tFieldOnLBigObject: Float!\n uFieldOnLBigObject: String!\n vFieldOnLBigObject: Int!\n wFieldOnLBigObject: Boolean!\n xFieldOnLBigObject: Float!\n yFieldOnLBigObject: String!\n zFieldOnLBigObject: Int!\n}\n\ntype MBigObject {\n aFieldOnMBigObject: String!\n bFieldOnMBigObject: Int!\n cFieldOnMBigObject: Boolean!\n dFieldOnMBigObject: Float!\n eFieldOnMBigObject: String!\n fFieldOnMBigObject: Int!\n gFieldOnMBigObject: Boolean!\n hFieldOnMBigObject: Float!\n iFieldOnMBigObject: String!\n jFieldOnMBigObject: Int!\n kFieldOnMBigObject: Boolean!\n lFieldOnMBigObject: Float!\n mFieldOnMBigObject: String!\n nFieldOnMBigObject: Int!\n oFieldOnMBigObject: Boolean!\n pFieldOnMBigObject: Float!\n qFieldOnMBigObject: String!\n rFieldOnMBigObject: Int!\n sFieldOnMBigObject: Boolean!\n tFieldOnMBigObject: Float!\n uFieldOnMBigObject: String!\n vFieldOnMBigObject: Int!\n wFieldOnMBigObject: Boolean!\n xFieldOnMBigObject: Float!\n yFieldOnMBigObject: String!\n zFieldOnMBigObject: Int!\n}\n\ntype NBigObject {\n aFieldOnNBigObject: String!\n bFieldOnNBigObject: Int!\n cFieldOnNBigObject: Boolean!\n dFieldOnNBigObject: Float!\n eFieldOnNBigObject: String!\n fFieldOnNBigObject: Int!\n gFieldOnNBigObject: Boolean!\n hFieldOnNBigObject: Float!\n iFieldOnNBigObject: String!\n jFieldOnNBigObject: Int!\n kFieldOnNBigObject: Boolean!\n lFieldOnNBigObject: Float!\n mFieldOnNBigObject: String!\n nFieldOnNBigObject: Int!\n oFieldOnNBigObject: Boolean!\n pFieldOnNBigObject: Float!\n qFieldOnNBigObject: String!\n rFieldOnNBigObject: Int!\n sFieldOnNBigObject: Boolean!\n tFieldOnNBigObject: Float!\n uFieldOnNBigObject: String!\n vFieldOnNBigObject: Int!\n wFieldOnNBigObject: Boolean!\n xFieldOnNBigObject: Float!\n yFieldOnNBigObject: String!\n zFieldOnNBigObject: Int!\n}\n\ntype OBigObject {\n aFieldOnOBigObject: String!\n bFieldOnOBigObject: Int!\n cFieldOnOBigObject: Boolean!\n dFieldOnOBigObject: Float!\n eFieldOnOBigObject: String!\n fFieldOnOBigObject: Int!\n gFieldOnOBigObject: Boolean!\n hFieldOnOBigObject: Float!\n iFieldOnOBigObject: String!\n jFieldOnOBigObject: Int!\n kFieldOnOBigObject: Boolean!\n lFieldOnOBigObject: Float!\n mFieldOnOBigObject: String!\n nFieldOnOBigObject: Int!\n oFieldOnOBigObject: Boolean!\n pFieldOnOBigObject: Float!\n qFieldOnOBigObject: String!\n rFieldOnOBigObject: Int!\n sFieldOnOBigObject: Boolean!\n tFieldOnOBigObject: Float!\n uFieldOnOBigObject: String!\n vFieldOnOBigObject: Int!\n wFieldOnOBigObject: Boolean!\n xFieldOnOBigObject: Float!\n yFieldOnOBigObject: String!\n zFieldOnOBigObject: Int!\n}\n\ntype PBigObject {\n aFieldOnPBigObject: String!\n bFieldOnPBigObject: Int!\n cFieldOnPBigObject: Boolean!\n dFieldOnPBigObject: Float!\n eFieldOnPBigObject: String!\n fFieldOnPBigObject: Int!\n gFieldOnPBigObject: Boolean!\n hFieldOnPBigObject: Float!\n iFieldOnPBigObject: String!\n jFieldOnPBigObject: Int!\n kFieldOnPBigObject: Boolean!\n lFieldOnPBigObject: Float!\n mFieldOnPBigObject: String!\n nFieldOnPBigObject: Int!\n oFieldOnPBigObject: Boolean!\n pFieldOnPBigObject: Float!\n qFieldOnPBigObject: String!\n rFieldOnPBigObject: Int!\n sFieldOnPBigObject: Boolean!\n tFieldOnPBigObject: Float!\n uFieldOnPBigObject: String!\n vFieldOnPBigObject: Int!\n wFieldOnPBigObject: Boolean!\n xFieldOnPBigObject: Float!\n yFieldOnPBigObject: String!\n zFieldOnPBigObject: Int!\n}\n\ntype QBigObject {\n aFieldOnQBigObject: String!\n bFieldOnQBigObject: Int!\n cFieldOnQBigObject: Boolean!\n dFieldOnQBigObject: Float!\n eFieldOnQBigObject: String!\n fFieldOnQBigObject: Int!\n gFieldOnQBigObject: Boolean!\n hFieldOnQBigObject: Float!\n iFieldOnQBigObject: String!\n jFieldOnQBigObject: Int!\n kFieldOnQBigObject: Boolean!\n lFieldOnQBigObject: Float!\n mFieldOnQBigObject: String!\n nFieldOnQBigObject: Int!\n oFieldOnQBigObject: Boolean!\n pFieldOnQBigObject: Float!\n qFieldOnQBigObject: String!\n rFieldOnQBigObject: Int!\n sFieldOnQBigObject: Boolean!\n tFieldOnQBigObject: Float!\n uFieldOnQBigObject: String!\n vFieldOnQBigObject: Int!\n wFieldOnQBigObject: Boolean!\n xFieldOnQBigObject: Float!\n yFieldOnQBigObject: String!\n zFieldOnQBigObject: Int!\n}\n\ntype RBigObject {\n aFieldOnRBigObject: String!\n bFieldOnRBigObject: Int!\n cFieldOnRBigObject: Boolean!\n dFieldOnRBigObject: Float!\n eFieldOnRBigObject: String!\n fFieldOnRBigObject: Int!\n gFieldOnRBigObject: Boolean!\n hFieldOnRBigObject: Float!\n iFieldOnRBigObject: String!\n jFieldOnRBigObject: Int!\n kFieldOnRBigObject: Boolean!\n lFieldOnRBigObject: Float!\n mFieldOnRBigObject: String!\n nFieldOnRBigObject: Int!\n oFieldOnRBigObject: Boolean!\n pFieldOnRBigObject: Float!\n qFieldOnRBigObject: String!\n rFieldOnRBigObject: Int!\n sFieldOnRBigObject: Boolean!\n tFieldOnRBigObject: Float!\n uFieldOnRBigObject: String!\n vFieldOnRBigObject: Int!\n wFieldOnRBigObject: Boolean!\n xFieldOnRBigObject: Float!\n yFieldOnRBigObject: String!\n zFieldOnRBigObject: Int!\n}\n\ntype SBigObject {\n aFieldOnSBigObject: String!\n bFieldOnSBigObject: Int!\n cFieldOnSBigObject: Boolean!\n dFieldOnSBigObject: Float!\n eFieldOnSBigObject: String!\n fFieldOnSBigObject: Int!\n gFieldOnSBigObject: Boolean!\n hFieldOnSBigObject: Float!\n iFieldOnSBigObject: String!\n jFieldOnSBigObject: Int!\n kFieldOnSBigObject: Boolean!\n lFieldOnSBigObject: Float!\n mFieldOnSBigObject: String!\n nFieldOnSBigObject: Int!\n oFieldOnSBigObject: Boolean!\n pFieldOnSBigObject: Float!\n qFieldOnSBigObject: String!\n rFieldOnSBigObject: Int!\n sFieldOnSBigObject: Boolean!\n tFieldOnSBigObject: Float!\n uFieldOnSBigObject: String!\n vFieldOnSBigObject: Int!\n wFieldOnSBigObject: Boolean!\n xFieldOnSBigObject: Float!\n yFieldOnSBigObject: String!\n zFieldOnSBigObject: Int!\n}\n\ntype TBigObject {\n aFieldOnTBigObject: String!\n bFieldOnTBigObject: Int!\n cFieldOnTBigObject: Boolean!\n dFieldOnTBigObject: Float!\n eFieldOnTBigObject: String!\n fFieldOnTBigObject: Int!\n gFieldOnTBigObject: Boolean!\n hFieldOnTBigObject: Float!\n iFieldOnTBigObject: String!\n jFieldOnTBigObject: Int!\n kFieldOnTBigObject: Boolean!\n lFieldOnTBigObject: Float!\n mFieldOnTBigObject: String!\n nFieldOnTBigObject: Int!\n oFieldOnTBigObject: Boolean!\n pFieldOnTBigObject: Float!\n qFieldOnTBigObject: String!\n rFieldOnTBigObject: Int!\n sFieldOnTBigObject: Boolean!\n tFieldOnTBigObject: Float!\n uFieldOnTBigObject: String!\n vFieldOnTBigObject: Int!\n wFieldOnTBigObject: Boolean!\n xFieldOnTBigObject: Float!\n yFieldOnTBigObject: String!\n zFieldOnTBigObject: Int!\n}\n\ntype UBigObject {\n aFieldOnUBigObject: String!\n bFieldOnUBigObject: Int!\n cFieldOnUBigObject: Boolean!\n dFieldOnUBigObject: Float!\n eFieldOnUBigObject: String!\n fFieldOnUBigObject: Int!\n gFieldOnUBigObject: Boolean!\n hFieldOnUBigObject: Float!\n iFieldOnUBigObject: String!\n jFieldOnUBigObject: Int!\n kFieldOnUBigObject: Boolean!\n lFieldOnUBigObject: Float!\n mFieldOnUBigObject: String!\n nFieldOnUBigObject: Int!\n oFieldOnUBigObject: Boolean!\n pFieldOnUBigObject: Float!\n qFieldOnUBigObject: String!\n rFieldOnUBigObject: Int!\n sFieldOnUBigObject: Boolean!\n tFieldOnUBigObject: Float!\n uFieldOnUBigObject: String!\n vFieldOnUBigObject: Int!\n wFieldOnUBigObject: Boolean!\n xFieldOnUBigObject: Float!\n yFieldOnUBigObject: String!\n zFieldOnUBigObject: Int!\n}\n\ntype VBigObject {\n aFieldOnVBigObject: String!\n bFieldOnVBigObject: Int!\n cFieldOnVBigObject: Boolean!\n dFieldOnVBigObject: Float!\n eFieldOnVBigObject: String!\n fFieldOnVBigObject: Int!\n gFieldOnVBigObject: Boolean!\n hFieldOnVBigObject: Float!\n iFieldOnVBigObject: String!\n jFieldOnVBigObject: Int!\n kFieldOnVBigObject: Boolean!\n lFieldOnVBigObject: Float!\n mFieldOnVBigObject: String!\n nFieldOnVBigObject: Int!\n oFieldOnVBigObject: Boolean!\n pFieldOnVBigObject: Float!\n qFieldOnVBigObject: String!\n rFieldOnVBigObject: Int!\n sFieldOnVBigObject: Boolean!\n tFieldOnVBigObject: Float!\n uFieldOnVBigObject: String!\n vFieldOnVBigObject: Int!\n wFieldOnVBigObject: Boolean!\n xFieldOnVBigObject: Float!\n yFieldOnVBigObject: String!\n zFieldOnVBigObject: Int!\n}\n\ntype WBigObject {\n aFieldOnWBigObject: String!\n bFieldOnWBigObject: Int!\n cFieldOnWBigObject: Boolean!\n dFieldOnWBigObject: Float!\n eFieldOnWBigObject: String!\n fFieldOnWBigObject: Int!\n gFieldOnWBigObject: Boolean!\n hFieldOnWBigObject: Float!\n iFieldOnWBigObject: String!\n jFieldOnWBigObject: Int!\n kFieldOnWBigObject: Boolean!\n lFieldOnWBigObject: Float!\n mFieldOnWBigObject: String!\n nFieldOnWBigObject: Int!\n oFieldOnWBigObject: Boolean!\n pFieldOnWBigObject: Float!\n qFieldOnWBigObject: String!\n rFieldOnWBigObject: Int!\n sFieldOnWBigObject: Boolean!\n tFieldOnWBigObject: Float!\n uFieldOnWBigObject: String!\n vFieldOnWBigObject: Int!\n wFieldOnWBigObject: Boolean!\n xFieldOnWBigObject: Float!\n yFieldOnWBigObject: String!\n zFieldOnWBigObject: Int!\n}\n\ntype XBigObject {\n aFieldOnXBigObject: String!\n bFieldOnXBigObject: Int!\n cFieldOnXBigObject: Boolean!\n dFieldOnXBigObject: Float!\n eFieldOnXBigObject: String!\n fFieldOnXBigObject: Int!\n gFieldOnXBigObject: Boolean!\n hFieldOnXBigObject: Float!\n iFieldOnXBigObject: String!\n jFieldOnXBigObject: Int!\n kFieldOnXBigObject: Boolean!\n lFieldOnXBigObject: Float!\n mFieldOnXBigObject: String!\n nFieldOnXBigObject: Int!\n oFieldOnXBigObject: Boolean!\n pFieldOnXBigObject: Float!\n qFieldOnXBigObject: String!\n rFieldOnXBigObject: Int!\n sFieldOnXBigObject: Boolean!\n tFieldOnXBigObject: Float!\n uFieldOnXBigObject: String!\n vFieldOnXBigObject: Int!\n wFieldOnXBigObject: Boolean!\n xFieldOnXBigObject: Float!\n yFieldOnXBigObject: String!\n zFieldOnXBigObject: Int!\n}\n\ntype YBigObject {\n aFieldOnYBigObject: String!\n bFieldOnYBigObject: Int!\n cFieldOnYBigObject: Boolean!\n dFieldOnYBigObject: Float!\n eFieldOnYBigObject: String!\n fFieldOnYBigObject: Int!\n gFieldOnYBigObject: Boolean!\n hFieldOnYBigObject: Float!\n iFieldOnYBigObject: String!\n jFieldOnYBigObject: Int!\n kFieldOnYBigObject: Boolean!\n lFieldOnYBigObject: Float!\n mFieldOnYBigObject: String!\n nFieldOnYBigObject: Int!\n oFieldOnYBigObject: Boolean!\n pFieldOnYBigObject: Float!\n qFieldOnYBigObject: String!\n rFieldOnYBigObject: Int!\n sFieldOnYBigObject: Boolean!\n tFieldOnYBigObject: Float!\n uFieldOnYBigObject: String!\n vFieldOnYBigObject: Int!\n wFieldOnYBigObject: Boolean!\n xFieldOnYBigObject: Float!\n yFieldOnYBigObject: String!\n zFieldOnYBigObject: Int!\n}\n\ntype ZBigObject {\n aFieldOnZBigObject: String!\n bFieldOnZBigObject: Int!\n cFieldOnZBigObject: Boolean!\n dFieldOnZBigObject: Float!\n eFieldOnZBigObject: String!\n fFieldOnZBigObject: Int!\n gFieldOnZBigObject: Boolean!\n hFieldOnZBigObject: Float!\n iFieldOnZBigObject: String!\n jFieldOnZBigObject: Int!\n kFieldOnZBigObject: Boolean!\n lFieldOnZBigObject: Float!\n mFieldOnZBigObject: String!\n nFieldOnZBigObject: Int!\n oFieldOnZBigObject: Boolean!\n pFieldOnZBigObject: Float!\n qFieldOnZBigObject: String!\n rFieldOnZBigObject: Int!\n sFieldOnZBigObject: Boolean!\n tFieldOnZBigObject: Float!\n uFieldOnZBigObject: String!\n vFieldOnZBigObject: Int!\n wFieldOnZBigObject: Boolean!\n xFieldOnZBigObject: Float!\n yFieldOnZBigObject: String!\n zFieldOnZBigObject: Int!\n}\n\ntype Engineer implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n engineerType: EngineerType!\n}\n\ntype Marketer implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n}\n\ntype Operator implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n operatorType: [OperationType!]!\n}\n\ntype Employee implements Identifiable {\n details: Details\n id: Int!\n tag: String!\n expertise: String!\n role: RoleType!\n notes: String\n updatedAt: String!\n startDate: String!\n currentMood: Mood!\n derivedMood: Mood!\n isAvailable: Boolean\n rootFieldThrowsError: String\n rootFieldErrorWrapper: ErrorWrapper\n primaryWorkItem: EmployeeWorkItem\n lastWorkReview: WorkReviewResult\n workSetup: WorkSetup\n hobbies: [Hobby!]\n products: [ProductName!]!\n productCount: Int!\n fieldThrowsError: String\n}\n\ntype Cosmo implements IProduct {\n upc: ID!\n engineers: [Employee!]!\n lead: Employee!\n isLeadAvailable: Boolean\n name: ProductName!\n repositoryURL: String!\n}\n\ntype SDK implements IProduct {\n upc: ID!\n engineers: [Employee!]!\n owner: Employee!\n unicode: String!\n clientLanguages: [ProgrammingLanguage!]!\n}\n\ntype TechnicalWorkItem implements EmployeeWorkItem {\n name: String!\n priority: Int!\n codeCount: Int!\n handler: WorkItemHandler!\n specs: TechnicalSpecs!\n}\n\ntype ManagementWorkItem implements EmployeeWorkItem {\n name: String!\n priority: Int!\n teamSize: String!\n handler: WorkItemHandler!\n specs: ManagementSpecs!\n}\n\ninterface Pet implements Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Alligator implements Pet & Animal {\n class: Class!\n dangerous: String!\n gender: Gender!\n name: String!\n}\n\ntype Cat implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n type: CatType!\n}\n\ntype Dog implements Pet & Animal {\n breed: DogBreed!\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Mouse implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Pony implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Exercise implements Hobby {\n employees: [Employee!]!\n category: ExerciseType!\n}\n\ntype Flying implements Experience & Hobby {\n employees: [Employee!]!\n planeModels: [String!]!\n yearsOfExperience: Float!\n}\n\ntype Gaming implements Experience & Hobby {\n employees: [Employee!]!\n genres: [GameGenre!]!\n name: String!\n yearsOfExperience: Float!\n}\n\ntype Other implements Hobby {\n employees: [Employee!]!\n name: String!\n}\n\ntype Programming implements Hobby {\n employees: [Employee!]!\n languages: [ProgrammingLanguage!]!\n}\n\ntype Travelling implements Hobby {\n employees: [Employee!]!\n countriesLived: [Country!]!\n}\n\ntype DirectiveFact implements TopSecretFact {\n title: String!\n description: FactContent!\n factType: TopSecretFactType\n}\n\ntype EntityFact implements TopSecretFact {\n title: String!\n description: FactContent!\n factType: TopSecretFactType\n}\n\ntype MiscellaneousFact implements TopSecretFact {\n title: String!\n description: FactContent!\n factType: TopSecretFactType\n}"
+ "graphqlClientSchema": "type Query {\n employee(id: Int!): Employee\n employeeAsList(id: Int!): [Employee]\n employees: [Employee]\n products: [Products!]!\n teammates(team: Department!): [Employee!]!\n firstEmployee: Employee!\n findEmployeesBy(criteria: FindEmployeeCriteria!): [Employee!]!\n\n \"\"\" This is a GraphQL query that retrieves a list of employees.\"\"\"\n findEmployees(criteria: SearchInput): [Employee!]!\n productTypes: [Products!]!\n topSecretFederationFacts: [TopSecretFact!]!\n factTypes: [TopSecretFactType!]\n\n \"\"\"Returns the value of the received HTTP header.\"\"\"\n headerValue(name: String!): String!\n\n \"\"\"Returns the value of the given key in the WS initial payload.\"\"\"\n initPayloadValue(key: String!): String!\n initialPayload: Map\n\n \"\"\"Returns response after the given delay\"\"\"\n delay(response: String!, ms: Int!): String!\n bigResponse(artificialDelay: Int! = 0, bigObjects: Int! = 100, nestedObjects: Int! = 100, deeplyNestedObjects: Int! = 100): [BigObject!]!\n longResponse(artificialDelay: Int! = 0, bytes: Int!): String\n bigAbstractResponse: BigAbstractResponse\n rootFieldWithListArg(arg: [String!]!): [String!]!\n rootFieldWithNestedListArg(arg: [[String!]!]!): [[String!]!]!\n rootFieldWithListOfInputArg(arg: [InputType!]!): [InputResponse!]!\n rootFieldWithListOfEnumArg(arg: [EnumType!]!): [EnumType!]!\n rootFieldWithInput(arg: InputArg!): String!\n floatField(arg: Float): Float\n sharedThings(numOfA: Int!, numOfB: Int!): [Thing!]!\n secret: Secret\n}\n\nscalar Upload\n\ntype Mutation {\n updateEmployeeTag(id: Int!, tag: String!): Employee\n singleUpload(file: Upload!): Boolean!\n singleUploadWithInput(arg: FileUpload!): Boolean!\n multipleUpload(files: [Upload!]!): Boolean!\n addFact(fact: TopSecretFactInput!): TopSecretFact!\n\n \"\"\" This mutation updates the availability status of an employee in the system.\n \"\"\"\n updateAvailability(employeeID: Int!, isAvailable: Boolean!): Employee!\n\n \"\"\" This mutation update the mood of an employee. \"\"\"\n updateMood(employeeID: Int!, mood: Mood!): Employee!\n}\n\ninput FileUpload {\n nested: DeeplyNestedFileUpload\n nestedList: [Upload!]\n}\n\ninput DeeplyNestedFileUpload {\n file: Upload!\n}\n\ntype Subscription {\n \"\"\"`currentTime` will return a stream of `Time` objects.\"\"\"\n currentTime: Time!\n countEmp(max: Int!, intervalMilliseconds: Int!): Int!\n countEmp2(max: Int!, intervalMilliseconds: Int!): Int!\n countFor(count: Int!): Int!\n countHob(max: Int!, intervalMilliseconds: Int!): Int!\n\n \"\"\"Returns a stream with the value of the received HTTP header.\"\"\"\n headerValue(name: String!, repeat: Int): TimestampedString!\n\n \"\"\"\n Returns a stream with the value of value of the given key in the WS initial payload.\n \"\"\"\n initPayloadValue(key: String!, repeat: Int): TimestampedString!\n\n \"\"\"Returns a stream with the value of the WS initial payload.\"\"\"\n initialPayload(repeat: Int): Map\n returnsError: String!\n\n \"\"\"\n Returns a stream with the values of the WS initial payload and subscribe extensions\n \"\"\"\n metadata(repeat: Int! = 1): SubscribeMetadata!\n}\n\nenum Department {\n ENGINEERING\n MARKETING\n OPERATIONS\n}\n\ninterface RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n}\n\nenum EngineerType {\n BACKEND\n FRONTEND\n FULLSTACK\n}\n\ninterface Identifiable {\n id: Int!\n}\n\nenum OperationType {\n FINANCE\n HUMAN_RESOURCES\n}\n\ntype Details {\n forename: String!\n location: Country!\n surname: String!\n pastLocations: [City!]!\n middlename: String @deprecated\n hasChildren: Boolean!\n maritalStatus: MaritalStatus\n nationality: Nationality!\n pets: [Pet]\n}\n\ntype City {\n type: String!\n name: String!\n country: Country\n}\n\ntype Country {\n key: CountryKey!\n language: String\n}\n\ntype CountryKey {\n name: String!\n}\n\nenum Mood {\n HAPPY\n SAD\n}\n\ntype ErrorWrapper {\n okField: String\n errorField: String\n}\n\ntype Time {\n unixTime: Int!\n timeStamp: String!\n}\n\nunion Products = Consultancy | Cosmo | SDK | Documentation\n\ninterface IProduct {\n upc: ID!\n engineers: [Employee!]!\n}\n\ntype Consultancy {\n upc: ID!\n lead: Employee!\n isLeadAvailable: Boolean\n name: ProductName!\n}\n\ninterface EmployeeWorkItem {\n name: String!\n priority: Int!\n}\n\ntype WorkItemHandler {\n name: String!\n assignedItem: EmployeeWorkItem!\n}\n\ntype TechnicalSpecs {\n name: String!\n complexity: Float!\n metrics: WorkMetrics!\n}\n\ntype ManagementSpecs {\n name: String!\n scope: Float!\n metrics: WorkMetrics!\n}\n\ntype WorkMetrics {\n score: Float!\n efficiency: Float!\n}\n\nunion WorkReviewResult = WorkApproval | WorkRejection\n\ntype WorkApproval {\n comment: String!\n approvedAt: String!\n}\n\ntype WorkRejection {\n reason: String!\n rejectionCode: String!\n}\n\ntype WorkSetup {\n priority: String!\n primaryItem: EmployeeWorkItem!\n}\n\ninput FindEmployeeCriteria @oneOf {\n id: Int\n department: Department\n title: String\n}\n\nenum Class {\n FISH\n MAMMAL\n REPTILE\n}\n\nenum Gender {\n FEMALE\n MALE\n UNKNOWN\n}\n\ninterface Animal {\n class: Class!\n gender: Gender!\n}\n\nenum CatType {\n HOME\n STREET\n}\n\nenum DogBreed {\n GOLDEN_RETRIEVER\n POODLE\n ROTTWEILER\n YORKSHIRE_TERRIER\n}\n\nenum MaritalStatus {\n ENGAGED\n MARRIED\n}\n\nenum Nationality {\n AMERICAN\n DUTCH\n ENGLISH\n GERMAN\n INDIAN\n SPANISH\n UKRAINIAN\n}\n\n\"\"\" Allows to filter employees by their details. \"\"\"\ninput SearchInput {\n hasPets: Boolean\n nationality: Nationality\n nested: NestedSearchInput\n}\n\ninput NestedSearchInput {\n maritalStatus: MaritalStatus\n hasChildren: Boolean\n}\n\nenum ExerciseType {\n CALISTHENICS\n HIKING\n SPORT\n STRENGTH_TRAINING\n}\n\ninterface Experience {\n yearsOfExperience: Float!\n}\n\nenum GameGenre {\n ADVENTURE\n BOARD\n FPS\n CARD\n RPG\n ROGUELITE\n SIMULATION\n STRATEGY\n}\n\nenum ProgrammingLanguage {\n CSHARP\n GO\n RUST\n TYPESCRIPT\n}\n\ninterface Hobby {\n employees: [Employee!]!\n}\n\ninput TopSecretFactInput {\n title: String!\n description: FactContent!\n factType: TopSecretFactType!\n}\n\nenum TopSecretFactType {\n DIRECTIVE\n ENTITY\n MISCELLANEOUS\n}\n\ninterface TopSecretFact {\n description: FactContent!\n factType: TopSecretFactType\n}\n\nscalar FactContent\n\nenum ProductName {\n CONSULTANCY\n COSMO\n ENGINE\n FINANCE\n HUMAN_RESOURCES\n MARKETING\n SDK\n}\n\ntype Documentation {\n url(product: ProductName!): String!\n urls(products: [ProductName!]!): [String!]!\n}\n\ntype Secret {\n value: String\n}\n\ntype Thing {\n b: String!\n}\n\ninput InputArg {\n enums: [EnumType!]\n enum: EnumType\n string: String\n strings: [String!]\n}\n\nenum EnumType {\n A\n B\n C\n}\n\ninput InputType {\n arg: String!\n}\n\ntype InputResponse {\n arg: String!\n}\n\nscalar Map\n\ntype TimestampedString {\n \"\"\"The value of the string.\"\"\"\n value: String!\n\n \"\"\"The timestamp when the response was generated.\"\"\"\n unixTime: Int!\n\n \"\"\"Sequence number\"\"\"\n seq: Int!\n\n \"\"\"Total number of responses to be sent\"\"\"\n total: Int!\n initialPayload: Map\n extensions: Map\n}\n\ntype SubscribeMetadata {\n initialPayload: Map\n subscribeExtensions: Map\n}\n\ntype BigObject {\n nestedObjects: [NestedObject!]!\n}\n\ntype NestedObject {\n deeplyNestedObjects: [DeeplyNestedObject!]!\n}\n\ntype DeeplyNestedObject {\n aFieldOnDeeplyNestedObject: String!\n bFieldOnDeeplyNestedObject: Int!\n cFieldOnDeeplyNestedObject: Boolean!\n dFieldOnDeeplyNestedObject: Float!\n eFieldOnDeeplyNestedObject: String!\n fFieldOnDeeplyNestedObject: Int!\n gFieldOnDeeplyNestedObject: Boolean!\n hFieldOnDeeplyNestedObject: Float!\n iFieldOnDeeplyNestedObject: String!\n jFieldOnDeeplyNestedObject: Int!\n kFieldOnDeeplyNestedObject: Boolean!\n lFieldOnDeeplyNestedObject: Float!\n mFieldOnDeeplyNestedObject: String!\n nFieldOnDeeplyNestedObject: Int!\n oFieldOnDeeplyNestedObject: Boolean!\n pFieldOnDeeplyNestedObject: Float!\n qFieldOnDeeplyNestedObject: String!\n rFieldOnDeeplyNestedObject: Int!\n sFieldOnDeeplyNestedObject: Boolean!\n tFieldOnDeeplyNestedObject: Float!\n uFieldOnDeeplyNestedObject: String!\n vFieldOnDeeplyNestedObject: Int!\n wFieldOnDeeplyNestedObject: Boolean!\n xFieldOnDeeplyNestedObject: Float!\n yFieldOnDeeplyNestedObject: String!\n zFieldOnDeeplyNestedObject: Int!\n}\n\nunion BigAbstractResponse = ABigObject | BBigObject | CBigObject | DBigObject | EBigObject | FBigObject | GBigObject | HBigObject | IBigObject | JBigObject | KBigObject | LBigObject | MBigObject | NBigObject | OBigObject | PBigObject | QBigObject | RBigObject | SBigObject | TBigObject | UBigObject | VBigObject | WBigObject | XBigObject | YBigObject | ZBigObject\n\ntype ABigObject {\n aFieldOnABigObject: String!\n bFieldOnABigObject: Int!\n cFieldOnABigObject: Boolean!\n dFieldOnABigObject: Float!\n eFieldOnABigObject: String!\n fFieldOnABigObject: Int!\n gFieldOnABigObject: Boolean!\n hFieldOnABigObject: Float!\n iFieldOnABigObject: String!\n jFieldOnABigObject: Int!\n kFieldOnABigObject: Boolean!\n lFieldOnABigObject: Float!\n mFieldOnABigObject: String!\n nFieldOnABigObject: Int!\n oFieldOnABigObject: Boolean!\n pFieldOnABigObject: Float!\n qFieldOnABigObject: String!\n rFieldOnABigObject: Int!\n sFieldOnABigObject: Boolean!\n tFieldOnABigObject: Float!\n uFieldOnABigObject: String!\n vFieldOnABigObject: Int!\n wFieldOnABigObject: Boolean!\n xFieldOnABigObject: Float!\n yFieldOnABigObject: String!\n zFieldOnABigObject: Int!\n}\n\ntype BBigObject {\n aFieldOnBBigObject: String!\n bFieldOnBBigObject: Int!\n cFieldOnBBigObject: Boolean!\n dFieldOnBBigObject: Float!\n eFieldOnBBigObject: String!\n fFieldOnBBigObject: Int!\n gFieldOnBBigObject: Boolean!\n hFieldOnBBigObject: Float!\n iFieldOnBBigObject: String!\n jFieldOnBBigObject: Int!\n kFieldOnBBigObject: Boolean!\n lFieldOnBBigObject: Float!\n mFieldOnBBigObject: String!\n nFieldOnBBigObject: Int!\n oFieldOnBBigObject: Boolean!\n pFieldOnBBigObject: Float!\n qFieldOnBBigObject: String!\n rFieldOnBBigObject: Int!\n sFieldOnBBigObject: Boolean!\n tFieldOnBBigObject: Float!\n uFieldOnBBigObject: String!\n vFieldOnBBigObject: Int!\n wFieldOnBBigObject: Boolean!\n xFieldOnBBigObject: Float!\n yFieldOnBBigObject: String!\n zFieldOnBBigObject: Int!\n}\n\ntype CBigObject {\n aFieldOnCBigObject: String!\n bFieldOnCBigObject: Int!\n cFieldOnCBigObject: Boolean!\n dFieldOnCBigObject: Float!\n eFieldOnCBigObject: String!\n fFieldOnCBigObject: Int!\n gFieldOnCBigObject: Boolean!\n hFieldOnCBigObject: Float!\n iFieldOnCBigObject: String!\n jFieldOnCBigObject: Int!\n kFieldOnCBigObject: Boolean!\n lFieldOnCBigObject: Float!\n mFieldOnCBigObject: String!\n nFieldOnCBigObject: Int!\n oFieldOnCBigObject: Boolean!\n pFieldOnCBigObject: Float!\n qFieldOnCBigObject: String!\n rFieldOnCBigObject: Int!\n sFieldOnCBigObject: Boolean!\n tFieldOnCBigObject: Float!\n uFieldOnCBigObject: String!\n vFieldOnCBigObject: Int!\n wFieldOnCBigObject: Boolean!\n xFieldOnCBigObject: Float!\n yFieldOnCBigObject: String!\n zFieldOnCBigObject: Int!\n}\n\ntype DBigObject {\n aFieldOnDBigObject: String!\n bFieldOnDBigObject: Int!\n cFieldOnDBigObject: Boolean!\n dFieldOnDBigObject: Float!\n eFieldOnDBigObject: String!\n fFieldOnDBigObject: Int!\n gFieldOnDBigObject: Boolean!\n hFieldOnDBigObject: Float!\n iFieldOnDBigObject: String!\n jFieldOnDBigObject: Int!\n kFieldOnDBigObject: Boolean!\n lFieldOnDBigObject: Float!\n mFieldOnDBigObject: String!\n nFieldOnDBigObject: Int!\n oFieldOnDBigObject: Boolean!\n pFieldOnDBigObject: Float!\n qFieldOnDBigObject: String!\n rFieldOnDBigObject: Int!\n sFieldOnDBigObject: Boolean!\n tFieldOnDBigObject: Float!\n uFieldOnDBigObject: String!\n vFieldOnDBigObject: Int!\n wFieldOnDBigObject: Boolean!\n xFieldOnDBigObject: Float!\n yFieldOnDBigObject: String!\n zFieldOnDBigObject: Int!\n}\n\ntype EBigObject {\n aFieldOnEBigObject: String!\n bFieldOnEBigObject: Int!\n cFieldOnEBigObject: Boolean!\n dFieldOnEBigObject: Float!\n eFieldOnEBigObject: String!\n fFieldOnEBigObject: Int!\n gFieldOnEBigObject: Boolean!\n hFieldOnEBigObject: Float!\n iFieldOnEBigObject: String!\n jFieldOnEBigObject: Int!\n kFieldOnEBigObject: Boolean!\n lFieldOnEBigObject: Float!\n mFieldOnEBigObject: String!\n nFieldOnEBigObject: Int!\n oFieldOnEBigObject: Boolean!\n pFieldOnEBigObject: Float!\n qFieldOnEBigObject: String!\n rFieldOnEBigObject: Int!\n sFieldOnEBigObject: Boolean!\n tFieldOnEBigObject: Float!\n uFieldOnEBigObject: String!\n vFieldOnEBigObject: Int!\n wFieldOnEBigObject: Boolean!\n xFieldOnEBigObject: Float!\n yFieldOnEBigObject: String!\n zFieldOnEBigObject: Int!\n}\n\ntype FBigObject {\n aFieldOnFBigObject: String!\n bFieldOnFBigObject: Int!\n cFieldOnFBigObject: Boolean!\n dFieldOnFBigObject: Float!\n eFieldOnFBigObject: String!\n fFieldOnFBigObject: Int!\n gFieldOnFBigObject: Boolean!\n hFieldOnFBigObject: Float!\n iFieldOnFBigObject: String!\n jFieldOnFBigObject: Int!\n kFieldOnFBigObject: Boolean!\n lFieldOnFBigObject: Float!\n mFieldOnFBigObject: String!\n nFieldOnFBigObject: Int!\n oFieldOnFBigObject: Boolean!\n pFieldOnFBigObject: Float!\n qFieldOnFBigObject: String!\n rFieldOnFBigObject: Int!\n sFieldOnFBigObject: Boolean!\n tFieldOnFBigObject: Float!\n uFieldOnFBigObject: String!\n vFieldOnFBigObject: Int!\n wFieldOnFBigObject: Boolean!\n xFieldOnFBigObject: Float!\n yFieldOnFBigObject: String!\n zFieldOnFBigObject: Int!\n}\n\ntype GBigObject {\n aFieldOnGBigObject: String!\n bFieldOnGBigObject: Int!\n cFieldOnGBigObject: Boolean!\n dFieldOnGBigObject: Float!\n eFieldOnGBigObject: String!\n fFieldOnGBigObject: Int!\n gFieldOnGBigObject: Boolean!\n hFieldOnGBigObject: Float!\n iFieldOnGBigObject: String!\n jFieldOnGBigObject: Int!\n kFieldOnGBigObject: Boolean!\n lFieldOnGBigObject: Float!\n mFieldOnGBigObject: String!\n nFieldOnGBigObject: Int!\n oFieldOnGBigObject: Boolean!\n pFieldOnGBigObject: Float!\n qFieldOnGBigObject: String!\n rFieldOnGBigObject: Int!\n sFieldOnGBigObject: Boolean!\n tFieldOnGBigObject: Float!\n uFieldOnGBigObject: String!\n vFieldOnGBigObject: Int!\n wFieldOnGBigObject: Boolean!\n xFieldOnGBigObject: Float!\n yFieldOnGBigObject: String!\n zFieldOnGBigObject: Int!\n}\n\ntype HBigObject {\n aFieldOnHBigObject: String!\n bFieldOnHBigObject: Int!\n cFieldOnHBigObject: Boolean!\n dFieldOnHBigObject: Float!\n eFieldOnHBigObject: String!\n fFieldOnHBigObject: Int!\n gFieldOnHBigObject: Boolean!\n hFieldOnHBigObject: Float!\n iFieldOnHBigObject: String!\n jFieldOnHBigObject: Int!\n kFieldOnHBigObject: Boolean!\n lFieldOnHBigObject: Float!\n mFieldOnHBigObject: String!\n nFieldOnHBigObject: Int!\n oFieldOnHBigObject: Boolean!\n pFieldOnHBigObject: Float!\n qFieldOnHBigObject: String!\n rFieldOnHBigObject: Int!\n sFieldOnHBigObject: Boolean!\n tFieldOnHBigObject: Float!\n uFieldOnHBigObject: String!\n vFieldOnHBigObject: Int!\n wFieldOnHBigObject: Boolean!\n xFieldOnHBigObject: Float!\n yFieldOnHBigObject: String!\n zFieldOnHBigObject: Int!\n}\n\ntype IBigObject {\n aFieldOnIBigObject: String!\n bFieldOnIBigObject: Int!\n cFieldOnIBigObject: Boolean!\n dFieldOnIBigObject: Float!\n eFieldOnIBigObject: String!\n fFieldOnIBigObject: Int!\n gFieldOnIBigObject: Boolean!\n hFieldOnIBigObject: Float!\n iFieldOnIBigObject: String!\n jFieldOnIBigObject: Int!\n kFieldOnIBigObject: Boolean!\n lFieldOnIBigObject: Float!\n mFieldOnIBigObject: String!\n nFieldOnIBigObject: Int!\n oFieldOnIBigObject: Boolean!\n pFieldOnIBigObject: Float!\n qFieldOnIBigObject: String!\n rFieldOnIBigObject: Int!\n sFieldOnIBigObject: Boolean!\n tFieldOnIBigObject: Float!\n uFieldOnIBigObject: String!\n vFieldOnIBigObject: Int!\n wFieldOnIBigObject: Boolean!\n xFieldOnIBigObject: Float!\n yFieldOnIBigObject: String!\n zFieldOnIBigObject: Int!\n}\n\ntype JBigObject {\n aFieldOnJBigObject: String!\n bFieldOnJBigObject: Int!\n cFieldOnJBigObject: Boolean!\n dFieldOnJBigObject: Float!\n eFieldOnJBigObject: String!\n fFieldOnJBigObject: Int!\n gFieldOnJBigObject: Boolean!\n hFieldOnJBigObject: Float!\n iFieldOnJBigObject: String!\n jFieldOnJBigObject: Int!\n kFieldOnJBigObject: Boolean!\n lFieldOnJBigObject: Float!\n mFieldOnJBigObject: String!\n nFieldOnJBigObject: Int!\n oFieldOnJBigObject: Boolean!\n pFieldOnJBigObject: Float!\n qFieldOnJBigObject: String!\n rFieldOnJBigObject: Int!\n sFieldOnJBigObject: Boolean!\n tFieldOnJBigObject: Float!\n uFieldOnJBigObject: String!\n vFieldOnJBigObject: Int!\n wFieldOnJBigObject: Boolean!\n xFieldOnJBigObject: Float!\n yFieldOnJBigObject: String!\n zFieldOnJBigObject: Int!\n}\n\ntype KBigObject {\n aFieldOnKBigObject: String!\n bFieldOnKBigObject: Int!\n cFieldOnKBigObject: Boolean!\n dFieldOnKBigObject: Float!\n eFieldOnKBigObject: String!\n fFieldOnKBigObject: Int!\n gFieldOnKBigObject: Boolean!\n hFieldOnKBigObject: Float!\n iFieldOnKBigObject: String!\n jFieldOnKBigObject: Int!\n kFieldOnKBigObject: Boolean!\n lFieldOnKBigObject: Float!\n mFieldOnKBigObject: String!\n nFieldOnKBigObject: Int!\n oFieldOnKBigObject: Boolean!\n pFieldOnKBigObject: Float!\n qFieldOnKBigObject: String!\n rFieldOnKBigObject: Int!\n sFieldOnKBigObject: Boolean!\n tFieldOnKBigObject: Float!\n uFieldOnKBigObject: String!\n vFieldOnKBigObject: Int!\n wFieldOnKBigObject: Boolean!\n xFieldOnKBigObject: Float!\n yFieldOnKBigObject: String!\n zFieldOnKBigObject: Int!\n}\n\ntype LBigObject {\n aFieldOnLBigObject: String!\n bFieldOnLBigObject: Int!\n cFieldOnLBigObject: Boolean!\n dFieldOnLBigObject: Float!\n eFieldOnLBigObject: String!\n fFieldOnLBigObject: Int!\n gFieldOnLBigObject: Boolean!\n hFieldOnLBigObject: Float!\n iFieldOnLBigObject: String!\n jFieldOnLBigObject: Int!\n kFieldOnLBigObject: Boolean!\n lFieldOnLBigObject: Float!\n mFieldOnLBigObject: String!\n nFieldOnLBigObject: Int!\n oFieldOnLBigObject: Boolean!\n pFieldOnLBigObject: Float!\n qFieldOnLBigObject: String!\n rFieldOnLBigObject: Int!\n sFieldOnLBigObject: Boolean!\n tFieldOnLBigObject: Float!\n uFieldOnLBigObject: String!\n vFieldOnLBigObject: Int!\n wFieldOnLBigObject: Boolean!\n xFieldOnLBigObject: Float!\n yFieldOnLBigObject: String!\n zFieldOnLBigObject: Int!\n}\n\ntype MBigObject {\n aFieldOnMBigObject: String!\n bFieldOnMBigObject: Int!\n cFieldOnMBigObject: Boolean!\n dFieldOnMBigObject: Float!\n eFieldOnMBigObject: String!\n fFieldOnMBigObject: Int!\n gFieldOnMBigObject: Boolean!\n hFieldOnMBigObject: Float!\n iFieldOnMBigObject: String!\n jFieldOnMBigObject: Int!\n kFieldOnMBigObject: Boolean!\n lFieldOnMBigObject: Float!\n mFieldOnMBigObject: String!\n nFieldOnMBigObject: Int!\n oFieldOnMBigObject: Boolean!\n pFieldOnMBigObject: Float!\n qFieldOnMBigObject: String!\n rFieldOnMBigObject: Int!\n sFieldOnMBigObject: Boolean!\n tFieldOnMBigObject: Float!\n uFieldOnMBigObject: String!\n vFieldOnMBigObject: Int!\n wFieldOnMBigObject: Boolean!\n xFieldOnMBigObject: Float!\n yFieldOnMBigObject: String!\n zFieldOnMBigObject: Int!\n}\n\ntype NBigObject {\n aFieldOnNBigObject: String!\n bFieldOnNBigObject: Int!\n cFieldOnNBigObject: Boolean!\n dFieldOnNBigObject: Float!\n eFieldOnNBigObject: String!\n fFieldOnNBigObject: Int!\n gFieldOnNBigObject: Boolean!\n hFieldOnNBigObject: Float!\n iFieldOnNBigObject: String!\n jFieldOnNBigObject: Int!\n kFieldOnNBigObject: Boolean!\n lFieldOnNBigObject: Float!\n mFieldOnNBigObject: String!\n nFieldOnNBigObject: Int!\n oFieldOnNBigObject: Boolean!\n pFieldOnNBigObject: Float!\n qFieldOnNBigObject: String!\n rFieldOnNBigObject: Int!\n sFieldOnNBigObject: Boolean!\n tFieldOnNBigObject: Float!\n uFieldOnNBigObject: String!\n vFieldOnNBigObject: Int!\n wFieldOnNBigObject: Boolean!\n xFieldOnNBigObject: Float!\n yFieldOnNBigObject: String!\n zFieldOnNBigObject: Int!\n}\n\ntype OBigObject {\n aFieldOnOBigObject: String!\n bFieldOnOBigObject: Int!\n cFieldOnOBigObject: Boolean!\n dFieldOnOBigObject: Float!\n eFieldOnOBigObject: String!\n fFieldOnOBigObject: Int!\n gFieldOnOBigObject: Boolean!\n hFieldOnOBigObject: Float!\n iFieldOnOBigObject: String!\n jFieldOnOBigObject: Int!\n kFieldOnOBigObject: Boolean!\n lFieldOnOBigObject: Float!\n mFieldOnOBigObject: String!\n nFieldOnOBigObject: Int!\n oFieldOnOBigObject: Boolean!\n pFieldOnOBigObject: Float!\n qFieldOnOBigObject: String!\n rFieldOnOBigObject: Int!\n sFieldOnOBigObject: Boolean!\n tFieldOnOBigObject: Float!\n uFieldOnOBigObject: String!\n vFieldOnOBigObject: Int!\n wFieldOnOBigObject: Boolean!\n xFieldOnOBigObject: Float!\n yFieldOnOBigObject: String!\n zFieldOnOBigObject: Int!\n}\n\ntype PBigObject {\n aFieldOnPBigObject: String!\n bFieldOnPBigObject: Int!\n cFieldOnPBigObject: Boolean!\n dFieldOnPBigObject: Float!\n eFieldOnPBigObject: String!\n fFieldOnPBigObject: Int!\n gFieldOnPBigObject: Boolean!\n hFieldOnPBigObject: Float!\n iFieldOnPBigObject: String!\n jFieldOnPBigObject: Int!\n kFieldOnPBigObject: Boolean!\n lFieldOnPBigObject: Float!\n mFieldOnPBigObject: String!\n nFieldOnPBigObject: Int!\n oFieldOnPBigObject: Boolean!\n pFieldOnPBigObject: Float!\n qFieldOnPBigObject: String!\n rFieldOnPBigObject: Int!\n sFieldOnPBigObject: Boolean!\n tFieldOnPBigObject: Float!\n uFieldOnPBigObject: String!\n vFieldOnPBigObject: Int!\n wFieldOnPBigObject: Boolean!\n xFieldOnPBigObject: Float!\n yFieldOnPBigObject: String!\n zFieldOnPBigObject: Int!\n}\n\ntype QBigObject {\n aFieldOnQBigObject: String!\n bFieldOnQBigObject: Int!\n cFieldOnQBigObject: Boolean!\n dFieldOnQBigObject: Float!\n eFieldOnQBigObject: String!\n fFieldOnQBigObject: Int!\n gFieldOnQBigObject: Boolean!\n hFieldOnQBigObject: Float!\n iFieldOnQBigObject: String!\n jFieldOnQBigObject: Int!\n kFieldOnQBigObject: Boolean!\n lFieldOnQBigObject: Float!\n mFieldOnQBigObject: String!\n nFieldOnQBigObject: Int!\n oFieldOnQBigObject: Boolean!\n pFieldOnQBigObject: Float!\n qFieldOnQBigObject: String!\n rFieldOnQBigObject: Int!\n sFieldOnQBigObject: Boolean!\n tFieldOnQBigObject: Float!\n uFieldOnQBigObject: String!\n vFieldOnQBigObject: Int!\n wFieldOnQBigObject: Boolean!\n xFieldOnQBigObject: Float!\n yFieldOnQBigObject: String!\n zFieldOnQBigObject: Int!\n}\n\ntype RBigObject {\n aFieldOnRBigObject: String!\n bFieldOnRBigObject: Int!\n cFieldOnRBigObject: Boolean!\n dFieldOnRBigObject: Float!\n eFieldOnRBigObject: String!\n fFieldOnRBigObject: Int!\n gFieldOnRBigObject: Boolean!\n hFieldOnRBigObject: Float!\n iFieldOnRBigObject: String!\n jFieldOnRBigObject: Int!\n kFieldOnRBigObject: Boolean!\n lFieldOnRBigObject: Float!\n mFieldOnRBigObject: String!\n nFieldOnRBigObject: Int!\n oFieldOnRBigObject: Boolean!\n pFieldOnRBigObject: Float!\n qFieldOnRBigObject: String!\n rFieldOnRBigObject: Int!\n sFieldOnRBigObject: Boolean!\n tFieldOnRBigObject: Float!\n uFieldOnRBigObject: String!\n vFieldOnRBigObject: Int!\n wFieldOnRBigObject: Boolean!\n xFieldOnRBigObject: Float!\n yFieldOnRBigObject: String!\n zFieldOnRBigObject: Int!\n}\n\ntype SBigObject {\n aFieldOnSBigObject: String!\n bFieldOnSBigObject: Int!\n cFieldOnSBigObject: Boolean!\n dFieldOnSBigObject: Float!\n eFieldOnSBigObject: String!\n fFieldOnSBigObject: Int!\n gFieldOnSBigObject: Boolean!\n hFieldOnSBigObject: Float!\n iFieldOnSBigObject: String!\n jFieldOnSBigObject: Int!\n kFieldOnSBigObject: Boolean!\n lFieldOnSBigObject: Float!\n mFieldOnSBigObject: String!\n nFieldOnSBigObject: Int!\n oFieldOnSBigObject: Boolean!\n pFieldOnSBigObject: Float!\n qFieldOnSBigObject: String!\n rFieldOnSBigObject: Int!\n sFieldOnSBigObject: Boolean!\n tFieldOnSBigObject: Float!\n uFieldOnSBigObject: String!\n vFieldOnSBigObject: Int!\n wFieldOnSBigObject: Boolean!\n xFieldOnSBigObject: Float!\n yFieldOnSBigObject: String!\n zFieldOnSBigObject: Int!\n}\n\ntype TBigObject {\n aFieldOnTBigObject: String!\n bFieldOnTBigObject: Int!\n cFieldOnTBigObject: Boolean!\n dFieldOnTBigObject: Float!\n eFieldOnTBigObject: String!\n fFieldOnTBigObject: Int!\n gFieldOnTBigObject: Boolean!\n hFieldOnTBigObject: Float!\n iFieldOnTBigObject: String!\n jFieldOnTBigObject: Int!\n kFieldOnTBigObject: Boolean!\n lFieldOnTBigObject: Float!\n mFieldOnTBigObject: String!\n nFieldOnTBigObject: Int!\n oFieldOnTBigObject: Boolean!\n pFieldOnTBigObject: Float!\n qFieldOnTBigObject: String!\n rFieldOnTBigObject: Int!\n sFieldOnTBigObject: Boolean!\n tFieldOnTBigObject: Float!\n uFieldOnTBigObject: String!\n vFieldOnTBigObject: Int!\n wFieldOnTBigObject: Boolean!\n xFieldOnTBigObject: Float!\n yFieldOnTBigObject: String!\n zFieldOnTBigObject: Int!\n}\n\ntype UBigObject {\n aFieldOnUBigObject: String!\n bFieldOnUBigObject: Int!\n cFieldOnUBigObject: Boolean!\n dFieldOnUBigObject: Float!\n eFieldOnUBigObject: String!\n fFieldOnUBigObject: Int!\n gFieldOnUBigObject: Boolean!\n hFieldOnUBigObject: Float!\n iFieldOnUBigObject: String!\n jFieldOnUBigObject: Int!\n kFieldOnUBigObject: Boolean!\n lFieldOnUBigObject: Float!\n mFieldOnUBigObject: String!\n nFieldOnUBigObject: Int!\n oFieldOnUBigObject: Boolean!\n pFieldOnUBigObject: Float!\n qFieldOnUBigObject: String!\n rFieldOnUBigObject: Int!\n sFieldOnUBigObject: Boolean!\n tFieldOnUBigObject: Float!\n uFieldOnUBigObject: String!\n vFieldOnUBigObject: Int!\n wFieldOnUBigObject: Boolean!\n xFieldOnUBigObject: Float!\n yFieldOnUBigObject: String!\n zFieldOnUBigObject: Int!\n}\n\ntype VBigObject {\n aFieldOnVBigObject: String!\n bFieldOnVBigObject: Int!\n cFieldOnVBigObject: Boolean!\n dFieldOnVBigObject: Float!\n eFieldOnVBigObject: String!\n fFieldOnVBigObject: Int!\n gFieldOnVBigObject: Boolean!\n hFieldOnVBigObject: Float!\n iFieldOnVBigObject: String!\n jFieldOnVBigObject: Int!\n kFieldOnVBigObject: Boolean!\n lFieldOnVBigObject: Float!\n mFieldOnVBigObject: String!\n nFieldOnVBigObject: Int!\n oFieldOnVBigObject: Boolean!\n pFieldOnVBigObject: Float!\n qFieldOnVBigObject: String!\n rFieldOnVBigObject: Int!\n sFieldOnVBigObject: Boolean!\n tFieldOnVBigObject: Float!\n uFieldOnVBigObject: String!\n vFieldOnVBigObject: Int!\n wFieldOnVBigObject: Boolean!\n xFieldOnVBigObject: Float!\n yFieldOnVBigObject: String!\n zFieldOnVBigObject: Int!\n}\n\ntype WBigObject {\n aFieldOnWBigObject: String!\n bFieldOnWBigObject: Int!\n cFieldOnWBigObject: Boolean!\n dFieldOnWBigObject: Float!\n eFieldOnWBigObject: String!\n fFieldOnWBigObject: Int!\n gFieldOnWBigObject: Boolean!\n hFieldOnWBigObject: Float!\n iFieldOnWBigObject: String!\n jFieldOnWBigObject: Int!\n kFieldOnWBigObject: Boolean!\n lFieldOnWBigObject: Float!\n mFieldOnWBigObject: String!\n nFieldOnWBigObject: Int!\n oFieldOnWBigObject: Boolean!\n pFieldOnWBigObject: Float!\n qFieldOnWBigObject: String!\n rFieldOnWBigObject: Int!\n sFieldOnWBigObject: Boolean!\n tFieldOnWBigObject: Float!\n uFieldOnWBigObject: String!\n vFieldOnWBigObject: Int!\n wFieldOnWBigObject: Boolean!\n xFieldOnWBigObject: Float!\n yFieldOnWBigObject: String!\n zFieldOnWBigObject: Int!\n}\n\ntype XBigObject {\n aFieldOnXBigObject: String!\n bFieldOnXBigObject: Int!\n cFieldOnXBigObject: Boolean!\n dFieldOnXBigObject: Float!\n eFieldOnXBigObject: String!\n fFieldOnXBigObject: Int!\n gFieldOnXBigObject: Boolean!\n hFieldOnXBigObject: Float!\n iFieldOnXBigObject: String!\n jFieldOnXBigObject: Int!\n kFieldOnXBigObject: Boolean!\n lFieldOnXBigObject: Float!\n mFieldOnXBigObject: String!\n nFieldOnXBigObject: Int!\n oFieldOnXBigObject: Boolean!\n pFieldOnXBigObject: Float!\n qFieldOnXBigObject: String!\n rFieldOnXBigObject: Int!\n sFieldOnXBigObject: Boolean!\n tFieldOnXBigObject: Float!\n uFieldOnXBigObject: String!\n vFieldOnXBigObject: Int!\n wFieldOnXBigObject: Boolean!\n xFieldOnXBigObject: Float!\n yFieldOnXBigObject: String!\n zFieldOnXBigObject: Int!\n}\n\ntype YBigObject {\n aFieldOnYBigObject: String!\n bFieldOnYBigObject: Int!\n cFieldOnYBigObject: Boolean!\n dFieldOnYBigObject: Float!\n eFieldOnYBigObject: String!\n fFieldOnYBigObject: Int!\n gFieldOnYBigObject: Boolean!\n hFieldOnYBigObject: Float!\n iFieldOnYBigObject: String!\n jFieldOnYBigObject: Int!\n kFieldOnYBigObject: Boolean!\n lFieldOnYBigObject: Float!\n mFieldOnYBigObject: String!\n nFieldOnYBigObject: Int!\n oFieldOnYBigObject: Boolean!\n pFieldOnYBigObject: Float!\n qFieldOnYBigObject: String!\n rFieldOnYBigObject: Int!\n sFieldOnYBigObject: Boolean!\n tFieldOnYBigObject: Float!\n uFieldOnYBigObject: String!\n vFieldOnYBigObject: Int!\n wFieldOnYBigObject: Boolean!\n xFieldOnYBigObject: Float!\n yFieldOnYBigObject: String!\n zFieldOnYBigObject: Int!\n}\n\ntype ZBigObject {\n aFieldOnZBigObject: String!\n bFieldOnZBigObject: Int!\n cFieldOnZBigObject: Boolean!\n dFieldOnZBigObject: Float!\n eFieldOnZBigObject: String!\n fFieldOnZBigObject: Int!\n gFieldOnZBigObject: Boolean!\n hFieldOnZBigObject: Float!\n iFieldOnZBigObject: String!\n jFieldOnZBigObject: Int!\n kFieldOnZBigObject: Boolean!\n lFieldOnZBigObject: Float!\n mFieldOnZBigObject: String!\n nFieldOnZBigObject: Int!\n oFieldOnZBigObject: Boolean!\n pFieldOnZBigObject: Float!\n qFieldOnZBigObject: String!\n rFieldOnZBigObject: Int!\n sFieldOnZBigObject: Boolean!\n tFieldOnZBigObject: Float!\n uFieldOnZBigObject: String!\n vFieldOnZBigObject: Int!\n wFieldOnZBigObject: Boolean!\n xFieldOnZBigObject: Float!\n yFieldOnZBigObject: String!\n zFieldOnZBigObject: Int!\n}\n\ntype Engineer implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n engineerType: EngineerType!\n}\n\ntype Marketer implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n}\n\ntype Operator implements RoleType {\n departments: [Department!]!\n title: [String!]!\n employees: [Employee!]!\n operatorType: [OperationType!]!\n}\n\ntype Employee implements Identifiable {\n details: Details\n id: Int!\n tag: String!\n expertise: String!\n role: RoleType!\n notes: String\n updatedAt: String!\n startDate: String!\n currentMood: Mood!\n derivedMood: Mood!\n isAvailable: Boolean\n rootFieldThrowsError: String\n rootFieldErrorWrapper: ErrorWrapper\n primaryWorkItem: EmployeeWorkItem\n lastWorkReview: WorkReviewResult\n workSetup: WorkSetup\n hobbies: [Hobby!]\n products: [ProductName!]!\n productCount: Int!\n fieldThrowsError: String\n}\n\ntype Cosmo implements IProduct {\n upc: ID!\n engineers: [Employee!]!\n lead: Employee!\n isLeadAvailable: Boolean\n name: ProductName!\n repositoryURL: String!\n}\n\ntype SDK implements IProduct {\n upc: ID!\n engineers: [Employee!]!\n owner: Employee!\n unicode: String!\n clientLanguages: [ProgrammingLanguage!]!\n}\n\ntype TechnicalWorkItem implements EmployeeWorkItem {\n name: String!\n priority: Int!\n codeCount: Int!\n handler: WorkItemHandler!\n specs: TechnicalSpecs!\n}\n\ntype ManagementWorkItem implements EmployeeWorkItem {\n name: String!\n priority: Int!\n teamSize: String!\n handler: WorkItemHandler!\n specs: ManagementSpecs!\n}\n\ninterface Pet implements Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Alligator implements Pet & Animal {\n class: Class!\n dangerous: String!\n gender: Gender!\n name: String!\n}\n\ntype Cat implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n type: CatType!\n}\n\ntype Dog implements Pet & Animal {\n breed: DogBreed!\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Mouse implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Pony implements Pet & Animal {\n class: Class!\n gender: Gender!\n name: String!\n}\n\ntype Exercise implements Hobby {\n employees: [Employee!]!\n category: ExerciseType!\n}\n\ntype Flying implements Experience & Hobby {\n employees: [Employee!]!\n planeModels: [String!]!\n yearsOfExperience: Float!\n}\n\ntype Gaming implements Experience & Hobby {\n employees: [Employee!]!\n genres: [GameGenre!]!\n name: String!\n yearsOfExperience: Float!\n}\n\ntype Other implements Hobby {\n employees: [Employee!]!\n name: String!\n}\n\ntype Programming implements Hobby {\n employees: [Employee!]!\n languages: [ProgrammingLanguage!]!\n}\n\ntype Travelling implements Hobby {\n employees: [Employee!]!\n countriesLived: [Country!]!\n}\n\ntype DirectiveFact implements TopSecretFact {\n title: String!\n description: FactContent!\n factType: TopSecretFactType\n}\n\ntype EntityFact implements TopSecretFact {\n title: String!\n description: FactContent!\n factType: TopSecretFactType\n}\n\ntype MiscellaneousFact implements TopSecretFact {\n title: String!\n description: FactContent!\n factType: TopSecretFactType\n}"
},
"version": "00000000-0000-0000-0000-000000000000",
"subgraphs": [
diff --git a/router-tests/testenv/testenv.go b/router-tests/testenv/testenv.go
index 0702ec6243..8f3c0a1a21 100644
--- a/router-tests/testenv/testenv.go
+++ b/router-tests/testenv/testenv.go
@@ -434,8 +434,10 @@ type MCPConfig struct {
Port int
}
-var redisHost = "redis://localhost:6379"
-var redisClusterHost = "redis://localhost:7001"
+var (
+ redisHost = "redis://localhost:6379"
+ redisClusterHost = "redis://localhost:7001"
+)
// CreateTestSupervisorEnv is currently tailored specifically for /lifecycle/supervisor_test.go, refer to that test
// for usage example. CreateTestSupervisorEnv is not a drop-in replacement for CreateTestEnv!
@@ -1383,9 +1385,10 @@ func configureRouter(listenerAddr string, testConfig *Config, routerConfig *node
PrintQueryPlans: false,
EnableCacheResponseHeaders: true,
},
- WebSocketClientPollTimeout: 300 * time.Millisecond,
- WebSocketClientConnBufferSize: 1,
- WebSocketClientReadTimeout: 1 * time.Second,
+ WebSocketServerPollTimeout: 300 * time.Millisecond,
+ WebSocketServerConnBufferSize: 1,
+ WebSocketServerReadTimeout: 1 * time.Second,
+ WebSocketServerWriteTimeout: 2 * time.Second,
WebSocketClientWriteTimeout: 2 * time.Second,
// Avoid get in conflict with any test that doesn't expect to handle pings
WebSocketClientPingInterval: 30 * time.Second,
@@ -1850,10 +1853,10 @@ func grpcURL(endpoint string) string {
return "dns:///" + endpoint
}
-func ReadAndCheckJSON(t testing.TB, conn *websocket.Conn, v interface{}) (err error) {
+func ReadAndCheckJSON(t testing.TB, conn *websocket.Conn, v any) (err error) {
_, payload, err := conn.ReadMessage()
if err != nil {
- return err
+ return fmt.Errorf("read message: %w", err)
}
if err := json.Unmarshal(payload, &v); err != nil {
t.Logf("Failed to decode WebSocket message. Raw payload: %s", string(payload))
@@ -3015,6 +3018,8 @@ func ReadSSEField(t testing.TB, reader *bufio.Reader) string {
}
func WSReadJSON(t testing.TB, conn *websocket.Conn, v interface{}) (err error) {
+ t.Helper()
+
b := backoff.New(5*time.Second, 100*time.Millisecond)
attempts := 0
diff --git a/router-tests/testenv/testexec.go b/router-tests/testenv/testexec.go
index bea2b81456..c9a3518eef 100644
--- a/router-tests/testenv/testexec.go
+++ b/router-tests/testenv/testexec.go
@@ -3,6 +3,7 @@ package testenv
import (
"bufio"
"context"
+ "errors"
"fmt"
"io"
"net/http"
@@ -211,8 +212,18 @@ func runCmdWithLogs(t *testing.T, ctx context.Context, cmd *exec.Cmd, waitToComp
cmd.Stdout = w
cmd.Stderr = w
- // Capture output in real-time
+ done := make(chan struct{})
+ // Closing the pipe makes scanner.Scan return, which lets the goroutine exit
+ // before the test finishes. Without this guard the goroutine can race the
+ // test's own Cleanup/defers by calling t.Log after the test has returned.
+ t.Cleanup(func() {
+ _ = w.Close()
+ _ = r.Close()
+ <-done
+ })
+
go func() {
+ defer close(done)
scanner := bufio.NewScanner(r)
for scanner.Scan() {
line := scanner.Text()
@@ -235,7 +246,7 @@ func runCmdWithLogs(t *testing.T, ctx context.Context, cmd *exec.Cmd, waitToComp
}
}
}
- if err := scanner.Err(); err != nil {
+ if err := scanner.Err(); err != nil && !errors.Is(err, io.ErrClosedPipe) {
t.Logf("error reading output: %v", err)
}
}()
diff --git a/router/core/errors.go b/router/core/errors.go
index fdf811286d..ebc7a4f025 100644
--- a/router/core/errors.go
+++ b/router/core/errors.go
@@ -14,7 +14,8 @@ import (
"github.com/wundergraph/cosmo/router/internal/unique"
"github.com/wundergraph/cosmo/router/pkg/pubsub/datasource"
rtrace "github.com/wundergraph/cosmo/router/pkg/trace"
- "github.com/wundergraph/graphql-go-tools/v2/pkg/engine/datasource/graphql_datasource"
+ "github.com/wundergraph/graphql-go-tools/v2/pkg/engine/datasource/graphql_datasource/subscriptionclient/transport"
+
"github.com/wundergraph/graphql-go-tools/v2/pkg/engine/resolve"
"github.com/wundergraph/graphql-go-tools/v2/pkg/graphqlerrors"
"github.com/wundergraph/graphql-go-tools/v2/pkg/operationreport"
@@ -61,6 +62,24 @@ const (
ExtCodeErrBatchSubscriptionsUnsupported = "BATCHING_SUBSCRIPTION_UNSUPPORTED"
)
+// isTerminalSubscriptionError reports whether the given error, when surfaced
+// from the resolver during a subscription, should terminate the stream rather
+// than being delivered inline as a per-update error. These are errors that
+// invalidate the whole subscription (auth reject, upgrade failure, rate limit)
+// — continuing to deliver updates after one of these wouldn't be meaningful.
+func isTerminalSubscriptionError(err error) bool {
+ switch getErrorType(err) {
+ case errorTypeUnauthorized,
+ errorTypeUpgradeFailed,
+ errorTypeInvalidWsSubprotocol,
+ errorTypeRateLimit,
+ errorTypeContextCanceled,
+ errorTypeContextTimeout:
+ return true
+ }
+ return false
+}
+
func getErrorType(err error) errorType {
if errors.Is(err, ErrRateLimitExceeded) {
return errorTypeRateLimit
@@ -71,7 +90,7 @@ func getErrorType(err error) errorType {
if errors.Is(err, context.Canceled) {
return errorTypeContextCanceled
}
- var upgradeErr *graphql_datasource.UpgradeRequestError
+ var upgradeErr transport.ErrFailedUpgrade
if errors.As(err, &upgradeErr) {
return errorTypeUpgradeFailed
}
@@ -89,7 +108,7 @@ func getErrorType(err error) errorType {
if errors.As(err, &streamsHandlerErr) {
return errorTypeStreamsHandlerError
}
- var invalidWsSubprotocolErr graphql_datasource.InvalidWsSubprotocolError
+ var invalidWsSubprotocolErr transport.ErrInvalidSubprotocol
if errors.As(err, &invalidWsSubprotocolErr) {
return errorTypeInvalidWsSubprotocol
}
@@ -144,7 +163,6 @@ func trackFinalResponseError(ctx context.Context, err error) {
}
func getAggregatedSubgraphErrorCodes(err error) []string {
-
if unwrapped, ok := err.(multiError); ok {
errs := unwrapped.Unwrap()
@@ -173,7 +191,6 @@ func getSubgraphNames(ds []resolve.DataSourceInfo) []string {
}
func getAggregatedSubgraphServiceNames(err error) []string {
-
if unwrapped, ok := err.(multiError); ok {
errs := unwrapped.Unwrap()
@@ -196,7 +213,6 @@ func getAggregatedSubgraphServiceNames(err error) []string {
// propagateSubgraphErrors propagates the subgraph errors to the request context
func propagateSubgraphErrors(ctx *resolve.Context) {
err := ctx.SubgraphErrors()
-
if err != nil {
trackFinalResponseError(ctx.Context(), err)
}
diff --git a/router/core/factoryresolver.go b/router/core/factoryresolver.go
index c2a547c35c..2a4446d1a6 100644
--- a/router/core/factoryresolver.go
+++ b/router/core/factoryresolver.go
@@ -23,6 +23,7 @@ import (
"github.com/wundergraph/graphql-go-tools/v2/pkg/engine/argument_templates"
"github.com/wundergraph/graphql-go-tools/v2/pkg/engine/datasource/graphql_datasource"
+
grpcdatasource "github.com/wundergraph/graphql-go-tools/v2/pkg/engine/datasource/grpc_datasource"
"github.com/wundergraph/graphql-go-tools/v2/pkg/engine/datasource/staticdatasource"
"github.com/wundergraph/graphql-go-tools/v2/pkg/engine/plan"
@@ -76,7 +77,7 @@ type DefaultFactoryResolver struct {
baseTransport http.RoundTripper
transportFactory ApiTransportFactory
defaultSubgraphRequestTimeout time.Duration
- subscriptionClientOptions []graphql_datasource.Options
+ subscriptionClientOptions []graphql_datasource.SubscriptionClientOption
}
func NewDefaultFactoryResolver(
@@ -126,29 +127,28 @@ func NewDefaultFactoryResolver(
factoryLogger = abstractlogger.NewZapLogger(log, abstractlogger.DebugLevel)
}
- var netPollConfig graphql_datasource.NetPollConfiguration
-
- netPollConfig.ApplyDefaults()
-
- netPollConfig.Enable = enableNetPoll
-
- options := []graphql_datasource.Options{
+ options := []graphql_datasource.SubscriptionClientOption{
graphql_datasource.WithLogger(factoryLogger),
- graphql_datasource.WithNetPollConfiguration(netPollConfig),
}
if subscriptionClientOptions != nil {
if subscriptionClientOptions.PingInterval > 0 {
options = append(options, graphql_datasource.WithPingInterval(subscriptionClientOptions.PingInterval))
}
- if subscriptionClientOptions.ReadTimeout > 0 {
- options = append(options, graphql_datasource.WithReadTimeout(subscriptionClientOptions.ReadTimeout))
- }
if subscriptionClientOptions.PingTimeout > 0 {
options = append(options, graphql_datasource.WithPingTimeout(subscriptionClientOptions.PingTimeout))
}
- if subscriptionClientOptions.FrameTimeout > 0 {
- options = append(options, graphql_datasource.WithFrameTimeout(subscriptionClientOptions.FrameTimeout))
+ if subscriptionClientOptions.WriteTimeout > 0 {
+ options = append(options, graphql_datasource.WithWriteTimeout(subscriptionClientOptions.WriteTimeout))
+ }
+ if subscriptionClientOptions.AckTimeout > 0 {
+ options = append(options, graphql_datasource.WithAckTimeout(subscriptionClientOptions.AckTimeout))
+ }
+ if subscriptionClientOptions.ReadLimit > 0 {
+ options = append(options, graphql_datasource.WithReadLimit(subscriptionClientOptions.ReadLimit))
+ }
+ if subscriptionClientOptions.DefaultErrorExtensionCode != "" {
+ options = append(options, graphql_datasource.WithDefaultErrorExtensionCode(subscriptionClientOptions.DefaultErrorExtensionCode))
}
}
@@ -183,10 +183,7 @@ func (d *DefaultFactoryResolver) ResolveGraphqlFactory(subgraphName string) (pla
if d.transportFactory == nil || d.baseTransport == nil {
// dummy implementation for plan generator that doesn't make requests
- subscriptionClient := graphql_datasource.NewGraphQLSubscriptionClient(
- http.DefaultClient,
- http.DefaultClient,
- d.engineCtx,
+ subscriptionClient := graphql_datasource.NewGraphQLSubscriptionClient(d.engineCtx,
d.subscriptionClientOptions...,
)
return graphql_datasource.NewFactory(d.engineCtx, http.DefaultClient, subscriptionClient)
@@ -202,10 +199,8 @@ func (d *DefaultFactoryResolver) ResolveGraphqlFactory(subgraphName string) (pla
}
subscriptionClient := graphql_datasource.NewGraphQLSubscriptionClient(
- defaultHTTPClient,
- streamingClient,
d.engineCtx,
- d.subscriptionClientOptions...,
+ append([]graphql_datasource.SubscriptionClientOption{graphql_datasource.WithUpgradeClient(defaultHTTPClient), graphql_datasource.WithStreamingClient(streamingClient)}, d.subscriptionClientOptions...)...,
)
if subgraphClient, ok := d.subgraphHTTPClients[subgraphName]; ok {
diff --git a/router/core/flushwriter.go b/router/core/flushwriter.go
index 98e6ab3901..6d39f32dc8 100644
--- a/router/core/flushwriter.go
+++ b/router/core/flushwriter.go
@@ -66,7 +66,7 @@ func (f *HttpFlushWriter) Complete() {
// Flush before closing the writer to ensure all data is sent
f.flusher.Flush()
- f.Close(resolve.SubscriptionCloseKindNormal)
+ f.cancel()
}
func (f *HttpFlushWriter) Write(p []byte) (n int, err error) {
@@ -104,11 +104,12 @@ func (f *HttpFlushWriter) Heartbeat() error {
return nil
}
-func (f *HttpFlushWriter) Close(_ resolve.SubscriptionCloseKind) {
+func (f *HttpFlushWriter) Error(data []byte) {
if f.ctx.Err() != nil {
return
}
-
+ _, _ = f.buf.Write(data)
+ _ = f.Flush()
f.cancel()
}
@@ -159,7 +160,7 @@ func (f *HttpFlushWriter) Flush() (err error) {
f.flusher.Flush()
if f.subscribeOnce {
- defer f.Close(resolve.SubscriptionCloseKindNormal)
+ defer f.cancel()
}
return nil
diff --git a/router/core/graph_server.go b/router/core/graph_server.go
index 23812b8fe4..907d5abfbb 100644
--- a/router/core/graph_server.go
+++ b/router/core/graph_server.go
@@ -1305,10 +1305,12 @@ func (s *graphServer) buildGraphMux(
logger: s.logger,
trackUsageInfo: s.graphqlMetricsConfig.Enabled || s.metricConfig.Prometheus.PromSchemaFieldUsage.Enabled,
subscriptionClientOptions: &SubscriptionClientOptions{
- PingInterval: s.engineExecutionConfiguration.WebSocketClientPingInterval,
- PingTimeout: s.engineExecutionConfiguration.WebSocketClientPingTimeout,
- ReadTimeout: s.engineExecutionConfiguration.WebSocketClientReadTimeout,
- FrameTimeout: s.engineExecutionConfiguration.WebSocketClientFrameTimeout,
+ PingInterval: s.engineExecutionConfiguration.WebSocketClientPingInterval,
+ PingTimeout: s.engineExecutionConfiguration.WebSocketClientPingTimeout,
+ WriteTimeout: s.engineExecutionConfiguration.WebSocketClientWriteTimeout,
+ AckTimeout: s.engineExecutionConfiguration.WebSocketClientAckTimeout,
+ ReadLimit: int64(s.engineExecutionConfiguration.WebSocketClientReadLimit),
+ DefaultErrorExtensionCode: s.subgraphErrorPropagation.DefaultExtensionCode,
},
transportOptions: &TransportOptions{
SubgraphTransportOptions: s.subgraphTransportOptions,
@@ -1680,11 +1682,11 @@ func (s *graphServer) buildGraphMux(
AccessController: s.accessController,
Logger: s.logger,
Stats: s.engineStats,
- ReadTimeout: s.engineExecutionConfiguration.WebSocketClientReadTimeout,
- WriteTimeout: s.engineExecutionConfiguration.WebSocketClientWriteTimeout,
+ ReadTimeout: s.engineExecutionConfiguration.WebSocketServerReadTimeout,
+ WriteTimeout: s.engineExecutionConfiguration.WebSocketServerWriteTimeout,
EnableNetPoll: s.engineExecutionConfiguration.EnableNetPoll,
- NetPollTimeout: s.engineExecutionConfiguration.WebSocketClientPollTimeout,
- NetPollConnBufferSize: s.engineExecutionConfiguration.WebSocketClientConnBufferSize,
+ NetPollTimeout: s.engineExecutionConfiguration.WebSocketServerPollTimeout,
+ NetPollConnBufferSize: s.engineExecutionConfiguration.WebSocketServerConnBufferSize,
WebSocketConfiguration: s.webSocketConfiguration,
ClientHeader: s.clientHeader,
DisableVariablesRemapping: s.engineExecutionConfiguration.DisableVariablesRemapping,
@@ -1773,7 +1775,6 @@ func (s *graphServer) setupConnector(
Logger: s.logger,
Endpoint: sg.RoutingUrl,
})
-
if err != nil {
return fmt.Errorf("failed to create standalone plugin for subgraph %s: %w", dsConfig.Id, err)
}
@@ -1929,9 +1930,9 @@ func (s *graphServer) wait(ctx context.Context) error {
// After all requests are done, it will shut down the metric store and runtime metrics.
// Shutdown does cancel the context after all non-hijacked requests such as WebSockets has been handled.
func (s *graphServer) Shutdown(ctx context.Context) error {
- // Cancel the context after the graceful shutdown is done
- // to clean up resources like websocket connections, pools, etc.
- defer s.cancelFunc()
+ // Cancel context immediately so long-lived websocket handlers start graceful close with GoingAway.
+ // Non-hijacked HTTP requests are still governed by in-flight tracking and the shutdown context below.
+ s.cancelFunc()
s.logger.Debug("Shutdown of graph server initiated. Waiting for in-flight requests to finish.",
zap.String("config_version", s.baseRouterConfigVersion),
diff --git a/router/core/graphql_handler.go b/router/core/graphql_handler.go
index d8abf7c401..feb745390a 100644
--- a/router/core/graphql_handler.go
+++ b/router/core/graphql_handler.go
@@ -19,7 +19,7 @@ import (
rotel "github.com/wundergraph/cosmo/router/pkg/otel"
"github.com/wundergraph/cosmo/router/pkg/statistics"
- "github.com/wundergraph/graphql-go-tools/v2/pkg/engine/datasource/graphql_datasource"
+ "github.com/wundergraph/graphql-go-tools/v2/pkg/engine/datasource/graphql_datasource/subscriptionclient/transport"
"github.com/wundergraph/graphql-go-tools/v2/pkg/engine/plan"
"github.com/wundergraph/graphql-go-tools/v2/pkg/engine/resolve"
"github.com/wundergraph/graphql-go-tools/v2/pkg/graphqlerrors"
@@ -370,7 +370,24 @@ func (h *GraphQLHandler) configureRateLimiting(ctx *resolve.Context) *resolve.Co
// WriteError writes the error to the response writer. This function must be concurrency-safe.
// @TODO This function should be refactored to be a helper function for websocket and http error writing
// In the websocket case, we call this function concurrently as part of the polling loop. This is error-prone.
+// WriteError is used by the resolver's AsyncErrorWriter and by request-scoped
+// handlers. For subscription writers it emits a non-terminal error frame
+// (inlined into a next/data frame) so the subscription stays alive - the
+// per-update contract in the resolver. Terminal subscription failures should
+// call WriteTerminalError instead.
func (h *GraphQLHandler) WriteError(ctx *resolve.Context, err error, res *resolve.GraphQLResponse, w io.Writer) {
+ h.writeError(ctx, err, res, w, false)
+}
+
+// WriteTerminalError delivers a terminal error to a subscription writer. The
+// writer emits a protocol-level error frame (and, for subscriptions-transport-ws,
+// a following complete) so the client stops the subscription. For
+// non-subscription writers this behaves identically to WriteError.
+func (h *GraphQLHandler) WriteTerminalError(ctx *resolve.Context, err error, res *resolve.GraphQLResponse, w io.Writer) {
+ h.writeError(ctx, err, res, w, true)
+}
+
+func (h *GraphQLHandler) writeError(ctx *resolve.Context, err error, res *resolve.GraphQLResponse, w io.Writer, terminal bool) {
reqContext := getRequestContext(ctx.Context())
if reqContext == nil {
@@ -453,7 +470,7 @@ func (h *GraphQLHandler) WriteError(ctx *resolve.Context, err error, res *resolv
httpWriter.WriteHeader(http.StatusInternalServerError)
}
case errorTypeUpgradeFailed:
- var upgradeErr *graphql_datasource.UpgradeRequestError
+ var upgradeErr transport.ErrFailedUpgrade
if h.subgraphErrorPropagation.PropagateStatusCodes && errors.As(err, &upgradeErr) && upgradeErr.StatusCode != 0 {
response.Errors[0].Extensions = &Extensions{
StatusCode: upgradeErr.StatusCode,
@@ -510,6 +527,26 @@ func (h *GraphQLHandler) WriteError(ctx *resolve.Context, err error, res *resolv
}
}
+ if sub, ok := w.(resolve.SubscriptionResponseWriter); ok {
+ data, encErr := json.Marshal(response)
+ if encErr != nil {
+ requestLogger.Error("Unable to marshal error response", zap.Error(encErr))
+ return
+ }
+ if terminal || isTerminalSubscriptionError(err) {
+ sub.Error(data)
+ return
+ }
+ if _, wErr := sub.Write(data); wErr != nil {
+ requestLogger.Debug("Unable to write error response", zap.Error(wErr))
+ return
+ }
+ if flushErr := sub.Flush(); flushErr != nil {
+ requestLogger.Debug("Unable to flush error response", zap.Error(flushErr))
+ }
+ return
+ }
+
err = json.NewEncoder(w).Encode(response)
if err != nil {
if rErrors.IsBrokenPipe(err) {
@@ -518,10 +555,6 @@ func (h *GraphQLHandler) WriteError(ctx *resolve.Context, err error, res *resolv
requestLogger.Error("Unable to write error response", zap.Error(err))
}
}
-
- if flusher, ok := w.(resolve.SubscriptionResponseWriter); ok {
- _ = flusher.Flush()
- }
}
func (h *GraphQLHandler) setDebugCacheHeaders(w http.ResponseWriter, opCtx *operationContext) {
diff --git a/router/core/header_rule_engine.go b/router/core/header_rule_engine.go
index 784411b75d..bcc6f75438 100644
--- a/router/core/header_rule_engine.go
+++ b/router/core/header_rule_engine.go
@@ -241,21 +241,21 @@ func AddCacheControlPolicyToRules(rules *config.HeaderRules, cacheControl config
return rules
}
-func (hf *HeaderPropagation) getAllRules() ([]*config.RequestHeaderRule, []*config.ResponseHeaderRule, []*config.RouterResponseHeaderRule) {
- rhrs := hf.rules.All.Request
- for _, subgraph := range hf.rules.Subgraphs {
+func (h *HeaderPropagation) getAllRules() ([]*config.RequestHeaderRule, []*config.ResponseHeaderRule, []*config.RouterResponseHeaderRule) {
+ rhrs := h.rules.All.Request
+ for _, subgraph := range h.rules.Subgraphs {
rhrs = append(rhrs, subgraph.Request...)
}
- rhrrs := hf.rules.All.Response
- for _, subgraph := range hf.rules.Subgraphs {
+ rhrrs := h.rules.All.Response
+ for _, subgraph := range h.rules.Subgraphs {
rhrrs = append(rhrrs, subgraph.Response...)
}
- return rhrs, rhrrs, hf.rules.Router.Response
+ return rhrs, rhrrs, h.rules.Router.Response
}
-func (hf *HeaderPropagation) processRule(rule config.HeaderRule, index int) error {
+func (h *HeaderPropagation) processRule(rule config.HeaderRule, index int) error {
switch rule.GetOperation() {
case config.HeaderRuleOperationSet:
case config.HeaderRuleOperationPropagate:
@@ -264,7 +264,7 @@ func (hf *HeaderPropagation) processRule(rule config.HeaderRule, index int) erro
if err != nil {
return fmt.Errorf("invalid regex '%s' for header rule %d: %w", rule.GetMatching(), index, err)
}
- hf.regex[rule.GetMatching()] = regex
+ h.regex[rule.GetMatching()] = regex
}
default:
return fmt.Errorf("unhandled operation '%s' for header rule %+v", rule.GetOperation(), rule)
@@ -272,15 +272,15 @@ func (hf *HeaderPropagation) processRule(rule config.HeaderRule, index int) erro
return nil
}
-func (hf *HeaderPropagation) collectRuleMatchers(rhrs []*config.RequestHeaderRule, rhrrs []*config.ResponseHeaderRule) error {
+func (h *HeaderPropagation) collectRuleMatchers(rhrs []*config.RequestHeaderRule, rhrrs []*config.ResponseHeaderRule) error {
for i, rule := range rhrs {
- if err := hf.processRule(rule, i); err != nil {
+ if err := h.processRule(rule, i); err != nil {
return err
}
}
for i, rule := range rhrrs {
- if err := hf.processRule(rule, i); err != nil {
+ if err := h.processRule(rule, i); err != nil {
return err
}
}
@@ -288,33 +288,33 @@ func (hf *HeaderPropagation) collectRuleMatchers(rhrs []*config.RequestHeaderRul
return nil
}
-func (hf *HeaderPropagation) compileExpressionRules(requestRules []*config.RequestHeaderRule, routerResponseRules []*config.RouterResponseHeaderRule) error {
+func (h *HeaderPropagation) compileExpressionRules(requestRules []*config.RequestHeaderRule, routerResponseRules []*config.RouterResponseHeaderRule) error {
manager := expr.CreateNewExprManager()
for _, rule := range requestRules {
if rule.Expression == "" {
continue
}
- if _, ok := hf.compiledRules[rule.Expression]; ok {
+ if _, ok := h.compiledRules[rule.Expression]; ok {
continue
}
program, err := manager.CompileExpression(rule.Expression, reflect.String)
if err != nil {
return fmt.Errorf("error compiling expression %s for header rule %s: %w", rule.Expression, rule.Name, err)
}
- hf.compiledRules[rule.Expression] = program
+ h.compiledRules[rule.Expression] = program
}
for _, rule := range routerResponseRules {
if rule.Expression == "" {
continue
}
- if _, ok := hf.compiledRouterResponseRules[rule.Expression]; ok {
+ if _, ok := h.compiledRouterResponseRules[rule.Expression]; ok {
continue
}
program, err := manager.CompileExpression(rule.Expression, reflect.String)
if err != nil {
return fmt.Errorf("error compiling expression %s for header rule %s: %w", rule.Expression, rule.Name, err)
}
- hf.compiledRouterResponseRules[rule.Expression] = program
+ h.compiledRouterResponseRules[rule.Expression] = program
}
return nil
}
diff --git a/router/core/plan_generator.go b/router/core/plan_generator.go
index 79465bd12e..39c9b0d1f4 100644
--- a/router/core/plan_generator.go
+++ b/router/core/plan_generator.go
@@ -24,7 +24,6 @@ import (
"github.com/wundergraph/graphql-go-tools/v2/pkg/astparser"
"github.com/wundergraph/graphql-go-tools/v2/pkg/asttransform"
"github.com/wundergraph/graphql-go-tools/v2/pkg/astvalidation"
- "github.com/wundergraph/graphql-go-tools/v2/pkg/engine/datasource/graphql_datasource"
"github.com/wundergraph/graphql-go-tools/v2/pkg/engine/datasource/introspection_datasource"
"github.com/wundergraph/graphql-go-tools/v2/pkg/engine/plan"
"github.com/wundergraph/graphql-go-tools/v2/pkg/engine/postprocess"
@@ -347,9 +346,6 @@ func (pg *PlanGenerator) loadConfiguration(routerConfig *nodev1.RouterConfig, lo
}
}
- var netPollConfig graphql_datasource.NetPollConfiguration
- netPollConfig.ApplyDefaults()
-
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
diff --git a/router/core/transport.go b/router/core/transport.go
index c162fc54a1..4f95093020 100644
--- a/router/core/transport.go
+++ b/router/core/transport.go
@@ -215,10 +215,12 @@ type TransportOptions struct {
}
type SubscriptionClientOptions struct {
- PingInterval time.Duration
- PingTimeout time.Duration
- ReadTimeout time.Duration
- FrameTimeout time.Duration
+ PingInterval time.Duration
+ PingTimeout time.Duration
+ WriteTimeout time.Duration
+ AckTimeout time.Duration
+ ReadLimit int64
+ DefaultErrorExtensionCode string
}
func NewTransport(opts *TransportOptions) *TransportFactory {
diff --git a/router/core/websocket.go b/router/core/websocket.go
index c19aa08be9..95f83864b6 100644
--- a/router/core/websocket.go
+++ b/router/core/websocket.go
@@ -20,9 +20,7 @@ import (
"github.com/gobwas/ws/wsutil"
"github.com/gorilla/websocket"
"github.com/tidwall/gjson"
- "go.uber.org/atomic"
- "go.uber.org/zap"
-
+ "github.com/tidwall/sjson"
"github.com/wundergraph/astjson"
"github.com/wundergraph/cosmo/router/internal/expr"
"github.com/wundergraph/cosmo/router/internal/persistedoperation"
@@ -32,15 +30,20 @@ import (
"github.com/wundergraph/cosmo/router/pkg/logging"
"github.com/wundergraph/cosmo/router/pkg/statistics"
rtrace "github.com/wundergraph/cosmo/router/pkg/trace"
-
"github.com/wundergraph/graphql-go-tools/v2/pkg/engine/plan"
"github.com/wundergraph/graphql-go-tools/v2/pkg/engine/resolve"
"github.com/wundergraph/graphql-go-tools/v2/pkg/netpoll"
+ "go.uber.org/atomic"
+ "go.uber.org/zap"
)
-var (
- errClientTerminatedConnection = errors.New("client terminated connection")
-)
+// errClientTerminatedConnection is returned by HandleMessage when the client
+// sends a terminate message. It surfaces as *wsproto.CloseError so the read
+// loops handle it via the same errors.As path as any other close-kind error.
+var errClientTerminatedConnection = &wsproto.CloseError{
+ Err: errors.New("client terminated connection"),
+ Kind: wsproto.CloseKindNormal,
+}
type WebsocketMiddlewareOptions struct {
OperationProcessor *OperationProcessor
@@ -68,7 +71,6 @@ type WebsocketMiddlewareOptions struct {
}
func NewWebsocketMiddleware(ctx context.Context, opts WebsocketMiddlewareOptions) func(http.Handler) http.Handler {
-
handler := &WebsocketHandler{
ctx: ctx,
operationProcessor: opts.OperationProcessor,
@@ -167,7 +169,6 @@ func newWSConnectionWrapper(conn net.Conn, readTimeout, writeTimeout time.Durati
}
func (c *wsConnectionWrapper) ReadJSON(v any) error {
-
if c.readTimeout > 0 {
err := c.conn.SetReadDeadline(time.Now().Add(c.readTimeout))
if err != nil {
@@ -184,7 +185,6 @@ func (c *wsConnectionWrapper) ReadJSON(v any) error {
}
func (c *wsConnectionWrapper) WriteText(text string) error {
-
c.mu.Lock()
defer c.mu.Unlock()
@@ -270,9 +270,7 @@ type WebsocketHandler struct {
}
func (h *WebsocketHandler) handleUpgradeRequest(w http.ResponseWriter, r *http.Request) {
- var (
- subProtocol string
- )
+ var subProtocol string
requestID := middleware.GetReqID(r.Context())
requestContext := getRequestContext(r.Context())
@@ -366,7 +364,7 @@ func (h *WebsocketHandler) handleUpgradeRequest(w http.ResponseWriter, r *http.R
Protocol: protocol,
Logger: requestLogger,
Stats: h.stats,
- ConnectionID: resolve.ConnectionIDs.Inc(),
+ ConnectionID: resolve.NewConnectionID(),
ClientInfo: clientInfo,
InitRequestID: requestID,
ForwardUpgradeHeaders: h.forwardUpgradeHeadersConfig,
@@ -383,7 +381,7 @@ func (h *WebsocketHandler) handleUpgradeRequest(w http.ResponseWriter, r *http.R
requestLogger.Debug("Initializing websocket connection", zap.Error(err))
- handler.Close(false)
+ handler.Close(false, wsproto.CloseKindOf(err))
return
}
@@ -405,7 +403,7 @@ func (h *WebsocketHandler) handleUpgradeRequest(w http.ResponseWriter, r *http.R
}
http.Error(handler.w, http.StatusText(statusCode), statusCode)
_ = handler.writeErrorMessage(requestID, errorMessage)
- handler.Close(false)
+ handler.Close(false, wsproto.CloseKindNormal)
return
}
}
@@ -417,7 +415,7 @@ func (h *WebsocketHandler) handleUpgradeRequest(w http.ResponseWriter, r *http.R
if err != nil {
requestLogger.Error("Error parsing initial payload: %v", zap.Error(err))
_ = handler.writeErrorMessage(requestID, err)
- handler.Close(false)
+ handler.Close(false, wsproto.CloseKindNormal)
return
}
jwtToken, ok := initialPayloadMap[fromInitialPayloadConfig.Key].(string)
@@ -425,7 +423,7 @@ func (h *WebsocketHandler) handleUpgradeRequest(w http.ResponseWriter, r *http.R
err := fmt.Errorf("invalid JWT token in initial payload: JWT token is not a string")
requestLogger.Error(err.Error())
_ = handler.writeErrorMessage(requestID, err)
- handler.Close(false)
+ handler.Close(false, wsproto.CloseKindNormal)
return
}
handler.request.Header.Set(fromInitialPayloadConfig.ExportToken.HeaderKey, jwtToken)
@@ -439,7 +437,7 @@ func (h *WebsocketHandler) handleUpgradeRequest(w http.ResponseWriter, r *http.R
err = h.addConnection(c, handler)
if err != nil {
requestLogger.Error("Adding connection to net poller", zap.Error(err))
- handler.Close(true)
+ handler.Close(true, wsproto.CloseKindNormal)
}
return
}
@@ -453,11 +451,11 @@ func (h *WebsocketHandler) handleConnectionSync(handler *WebSocketConnectionHand
h.stats.ConnectionsInc()
defer h.stats.ConnectionsDec()
serverDone := h.ctx.Done()
- defer handler.Close(true)
for {
select {
case <-serverDone:
+ handler.Close(true, wsproto.CloseKindGoingAway)
return
default:
msg, err := handler.protocol.ReadMessage()
@@ -465,13 +463,16 @@ func (h *WebsocketHandler) handleConnectionSync(handler *WebSocketConnectionHand
if isReadTimeout(err) {
continue
}
- h.logger.Debug("Client closed connection")
+ h.logger.Debug("Client closed connection", zap.Error(err))
+ handler.Close(true, wsproto.CloseKindOf(err))
return
}
err = h.HandleMessage(handler, msg)
if err != nil {
h.logger.Debug("Handling websocket message", zap.Error(err))
- if errors.Is(err, errClientTerminatedConnection) {
+ var closeErr *wsproto.CloseError
+ if errors.As(err, &closeErr) {
+ handler.Close(true, closeErr.Kind)
return
}
}
@@ -491,7 +492,7 @@ func (h *WebsocketHandler) addConnection(conn net.Conn, handler *WebSocketConnec
return h.netPoll.Add(conn)
}
-func (h *WebsocketHandler) removeConnection(conn net.Conn, handler *WebSocketConnectionHandler, fd int) {
+func (h *WebsocketHandler) removeConnection(conn net.Conn, handler *WebSocketConnectionHandler, fd int, closeKind wsproto.CloseKind) {
h.stats.ConnectionsDec()
h.connectionsMu.Lock()
delete(h.connections, fd)
@@ -500,7 +501,7 @@ func (h *WebsocketHandler) removeConnection(conn net.Conn, handler *WebSocketCon
if err != nil {
h.logger.Warn("Removing connection from net poller", zap.Error(err))
}
- handler.Close(true)
+ handler.Close(true, closeKind)
}
func socketFd(conn net.Conn) int {
@@ -535,13 +536,12 @@ func isReadTimeout(err error) bool {
func (h *WebsocketHandler) runPoller() {
done := h.ctx.Done()
defer func() {
- h.connectionsMu.Lock()
- _ = h.netPoll.Close(true)
- h.connectionsMu.Unlock()
+ _ = h.netPoll.Close(false)
}()
for {
select {
case <-done:
+ h.closeAllConnections()
return
default:
connections, err := h.netPoll.Wait(128)
@@ -567,21 +567,25 @@ func (h *WebsocketHandler) runPoller() {
if fd == 0 {
h.logger.Debug("Invalid socket fd", zap.Int("fd", fd))
- h.removeConnection(conn, handler, fd)
+ h.removeConnection(conn, handler, fd, wsproto.CloseKindNormal)
continue
}
msg, err := handler.protocol.ReadMessage()
if err != nil {
h.logger.Debug("Client closed connection", zap.Error(err))
- h.removeConnection(conn, handler, fd)
+ h.removeConnection(conn, handler, fd, wsproto.CloseKindOf(err))
continue
}
err = h.HandleMessage(handler, msg)
if err != nil {
h.logger.Debug("Handling websocket message", zap.Error(err))
- if errors.Is(err, errClientTerminatedConnection) {
- h.removeConnection(conn, handler, fd)
+
+ // Only closeErr closes, which is why we're not using wsproto.CloseKindOf,
+ // which defaults to CloseKindNormal
+ var closeErr *wsproto.CloseError
+ if errors.As(err, &closeErr) {
+ h.removeConnection(conn, handler, fd, closeErr.Kind)
continue
}
}
@@ -590,6 +594,21 @@ func (h *WebsocketHandler) runPoller() {
}
}
+func (h *WebsocketHandler) closeAllConnections() {
+ h.connectionsMu.Lock()
+ handlers := make([]*WebSocketConnectionHandler, 0, len(h.connections))
+ for fd, handler := range h.connections {
+ handlers = append(handlers, handler)
+ delete(h.connections, fd)
+ }
+ h.connectionsMu.Unlock()
+
+ for _, handler := range handlers {
+ h.stats.ConnectionsDec()
+ handler.Close(true, wsproto.CloseKindGoingAway)
+ }
+}
+
type websocketResponseWriter struct {
id string
protocol wsproto.Proto
@@ -599,12 +618,15 @@ type websocketResponseWriter struct {
logger *zap.Logger
stats statistics.EngineStatistics
propagateErrors bool
+ subscriptions *sync.Map
}
-var _ http.ResponseWriter = (*websocketResponseWriter)(nil)
-var _ resolve.SubscriptionResponseWriter = (*websocketResponseWriter)(nil)
+var (
+ _ http.ResponseWriter = (*websocketResponseWriter)(nil)
+ _ resolve.SubscriptionResponseWriter = (*websocketResponseWriter)(nil)
+)
-func newWebsocketResponseWriter(id string, protocol wsproto.Proto, propagateErrors bool, logger *zap.Logger, stats statistics.EngineStatistics) *websocketResponseWriter {
+func newWebsocketResponseWriter(id string, protocol wsproto.Proto, propagateErrors bool, logger *zap.Logger, stats statistics.EngineStatistics, subscriptions *sync.Map) *websocketResponseWriter {
return &websocketResponseWriter{
id: id,
protocol: protocol,
@@ -612,6 +634,7 @@ func newWebsocketResponseWriter(id string, protocol wsproto.Proto, propagateErro
logger: logger.With(zap.String("subscription_id", id)),
stats: stats,
propagateErrors: propagateErrors,
+ subscriptions: subscriptions,
}
}
@@ -624,6 +647,9 @@ func (rw *websocketResponseWriter) WriteHeader(statusCode int) {
}
func (rw *websocketResponseWriter) Complete() {
+ if rw.subscriptions != nil {
+ rw.subscriptions.Delete(rw.id)
+ }
err := rw.protocol.Complete(rw.id)
if err != nil {
rw.logger.Debug("Sending complete message", zap.Error(err))
@@ -635,10 +661,38 @@ func (rw *websocketResponseWriter) Heartbeat() error {
return nil
}
-func (rw *websocketResponseWriter) Close(kind resolve.SubscriptionCloseKind) {
- err := rw.protocol.Close(kind.WSCode, kind.Reason)
- if err != nil {
+// Error delivers a terminal error payload. The subscription will not
+// produce any further messages after this call, so protocols that need
+// an explicit termination frame (subscriptions-transport-ws: complete
+// after data+errors) emit it here. Non-terminal per-update errors must
+// use Flush with errors buffered via Write, which keeps the subscription
+// alive.
+func (rw *websocketResponseWriter) Error(data []byte) {
+ if rw.subscriptions != nil {
+ rw.subscriptions.Delete(rw.id)
+ }
+ var errors json.RawMessage
+ if rw.propagateErrors {
+ errorsResult := gjson.GetBytes(data, "errors")
+ if errorsResult.Type == gjson.JSON {
+ errors = json.RawMessage(errorsResult.Raw)
+ } else {
+ errors = data
+ }
+ } else {
+ errors = json.RawMessage(`[{"message":"Unable to subscribe"}]`)
+ }
+ if err := rw.protocol.WriteGraphQLErrors(rw.id, errors, nil); err != nil {
rw.logger.Debug("Sending error message", zap.Error(err))
+ return
+ }
+ // subscriptions-transport-ws clients rely on an explicit "complete" to end
+ // the stream after a data+errors frame. graphql-transport-ws treats the
+ // "error" frame as terminal per spec, so no follow-up is needed there.
+ if rw.protocol.Subprotocol() == wsproto.SubscriptionsTransportWSSubprotocol {
+ if err := rw.protocol.Complete(rw.id); err != nil {
+ rw.logger.Debug("Sending complete after error", zap.Error(err))
+ }
}
}
@@ -649,7 +703,6 @@ func (rw *websocketResponseWriter) Write(data []byte) (int, error) {
func (rw *websocketResponseWriter) Flush() error {
if rw.buf.Len() > 0 {
- rw.logger.Debug("flushing", zap.Int("bytes", rw.buf.Len()))
payload := rw.buf.Bytes()
var extensions []byte
var err error
@@ -663,17 +716,17 @@ func (rw *websocketResponseWriter) Flush() error {
}
}
- // Check if the result is an error
- errorsResult := gjson.GetBytes(payload, "errors")
- if errorsResult.Type == gjson.JSON {
- if rw.propagateErrors {
- err = rw.protocol.WriteGraphQLErrors(rw.id, json.RawMessage(errorsResult.Raw), extensions)
- } else {
- err = rw.protocol.WriteGraphQLErrors(rw.id, json.RawMessage(`[{"message":"Unable to subscribe"}]`), extensions)
+ // Errors inside the buffered payload are emitted inline as part of the
+ // execution result (a non-terminal "next"/"data" frame) so the
+ // subscription stays alive. Terminal errors go through Error, which uses
+ // the protocol-level error frame.
+ if !rw.propagateErrors {
+ if errorsResult := gjson.GetBytes(payload, "errors"); errorsResult.Type == gjson.JSON {
+ payload, _ = sjson.SetRawBytes(payload, "errors", []byte(`[{"message":"Unable to subscribe"}]`))
}
- } else {
- err = rw.protocol.WriteGraphQLData(rw.id, payload, extensions)
}
+
+ err = rw.protocol.WriteGraphQLData(rw.id, payload, extensions)
rw.buf.Reset()
if err != nil {
return err
@@ -707,7 +760,7 @@ type WebSocketConnectionHandlerOptions struct {
Logger *zap.Logger
Stats statistics.EngineStatistics
PlanOptions PlanOptions
- ConnectionID int64
+ ConnectionID resolve.ConnectionID
ClientInfo *ClientInfo
InitRequestID string
ForwardUpgradeHeaders forwardConfig
@@ -739,7 +792,7 @@ type WebSocketConnectionHandler struct {
upgradeRequestQueryParams json.RawMessage
initRequestID string
- connectionID int64
+ connectionID resolve.ConnectionID
subscriptionIDs atomic.Int64
subscriptions sync.Map
stats statistics.EngineStatistics
@@ -764,9 +817,7 @@ type forwardConfig struct {
regexAllowList []*regexp.Regexp
}
-var (
- detectNonRegex = regexp.MustCompile(`^[A-Za-z0-9_-]+$`)
-)
+var detectNonRegex = regexp.MustCompile(`^[A-Za-z0-9_-]+$`)
func NewWebsocketConnectionHandler(ctx context.Context, opts WebSocketConnectionHandlerOptions) *WebSocketConnectionHandler {
return &WebSocketConnectionHandler{
@@ -831,7 +882,6 @@ func (h *WebSocketConnectionHandler) writeErrorMessage(operationID string, err e
}
func (h *WebSocketConnectionHandler) parseAndPlan(registration *SubscriptionRegistration) (*ParsedOperation, *operationContext, error) {
-
operationKit, err := h.operationProcessor.NewKit()
if err != nil {
return nil, nil, err
@@ -982,8 +1032,7 @@ func (h *WebSocketConnectionHandler) parseAndPlan(registration *SubscriptionRegi
}
func (h *WebSocketConnectionHandler) executeSubscription(registration *SubscriptionRegistration) {
-
- rw := newWebsocketResponseWriter(registration.msg.ID, h.protocol, h.graphqlHandler.subgraphErrorPropagation.Enabled, h.logger, h.stats)
+ rw := newWebsocketResponseWriter(registration.msg.ID, h.protocol, h.graphqlHandler.subgraphErrorPropagation.Enabled, h.logger, h.stats, &h.subscriptions)
_, operationCtx, err := h.parseAndPlan(registration)
if err != nil {
@@ -1054,7 +1103,7 @@ func (h *WebSocketConnectionHandler) executeSubscription(registration *Subscript
resolveCtx.Extensions = operationCtx.extensions
resolveCtx.ExecutionOptions = operationCtx.executionOptions
- if h.forwardInitialPayload && operationCtx.initialPayload != nil {
+ if operationCtx.initialPayload != nil {
resolveCtx.InitialPayload = operationCtx.initialPayload
}
@@ -1093,7 +1142,9 @@ func (h *WebSocketConnectionHandler) executeSubscription(registration *Subscript
err = h.graphqlHandler.executor.Resolver.AsyncResolveGraphQLSubscription(resolveCtx, p.Response, rw.SubscriptionResponseWriter(), registration.id)
if err != nil {
h.logger.Warn("Resolving GraphQL subscription", zap.Error(err))
- h.graphqlHandler.WriteError(resolveCtx, err, p.Response.Response, rw)
+ // Subscription setup failed so no updates will follow. Send a terminal
+ // error frame and stop.
+ h.graphqlHandler.WriteTerminalError(resolveCtx, err, p.Response.Response, rw)
return
}
}
@@ -1147,7 +1198,8 @@ func (h *WebSocketConnectionHandler) handleComplete(msg *wsproto.Message) error
ConnectionID: h.connectionID,
SubscriptionID: subscriptionID,
}
- return h.graphqlHandler.executor.Resolver.AsyncCompleteSubscription(id)
+ _ = h.protocol.Complete(msg.ID)
+ return h.graphqlHandler.executor.Resolver.UnsubscribeSubscription(id)
}
func (h *WebsocketHandler) HandleMessage(handler *WebSocketConnectionHandler, msg *wsproto.Message) (err error) {
@@ -1163,7 +1215,7 @@ func (h *WebsocketHandler) HandleMessage(handler *WebSocketConnectionHandler, ms
registration, err := handler.registerSubscription(msg)
if err != nil {
h.logger.Warn("Handling subscription registration", zap.Error(err))
- return handler.requestError(fmt.Errorf("error registering subscription id: %s", msg.ID))
+ return &wsproto.CloseError{Kind: wsproto.CloseKind{Code: 4409, Reason: "Subscriber for " + msg.ID + " already exists"}}
}
handler.executeSubscription(registration)
case wsproto.MessageTypeComplete:
@@ -1293,26 +1345,20 @@ func (h *WebSocketConnectionHandler) shouldComputeOperationSha256(operationKit *
return false
}
-func (h *WebSocketConnectionHandler) Complete(rw *websocketResponseWriter) {
- h.subscriptions.Delete(rw.id)
- err := rw.protocol.Complete(rw.id)
- if err != nil {
- return
- }
- _ = rw.Flush()
-}
-
-func (h *WebSocketConnectionHandler) Close(unsubscribe bool) {
+func (h *WebSocketConnectionHandler) Close(unsubscribe bool, closeKind wsproto.CloseKind) {
if unsubscribe {
// Remove any pending IDs associated with this connection
- err := h.graphqlHandler.executor.Resolver.AsyncUnsubscribeClient(h.connectionID)
+ err := h.graphqlHandler.executor.Resolver.UnsubscribeClient(h.connectionID)
if err != nil {
h.logger.Debug("Unsubscribing client", zap.Error(err))
}
}
- err := h.conn.Close()
- if err != nil {
+ if err := h.conn.WriteCloseFrame(closeKind.Code, closeKind.Reason); err != nil {
+ h.logger.Debug("Writing close frame", zap.Error(err))
+ }
+
+ if err := h.conn.Close(); err != nil {
h.logger.Debug("Closing websocket connection", zap.Error(err))
}
}
diff --git a/router/debug.config.yaml b/router/debug.config.yaml
index 10b042397b..c82f7733be 100644
--- a/router/debug.config.yaml
+++ b/router/debug.config.yaml
@@ -14,17 +14,36 @@ execution_config:
path: './__schemas/config.json'
# watch: true
+router_registration: false
+
log_level: debug
+headers:
+ all:
+ request:
+ - op: propagate
+ named: X-User-Id
+
watch_config:
- enabled: true
+ enabled: false
interval: '10s'
startup_delay:
enabled: false
maximum: '10s'
+access_logs:
+ enabled: false
+ level: info
+ add_stacktrace: true
+
telemetry:
+ metrics:
+ prometheus:
+ enabled: true
+ connection_stats: true
+ engine_stats:
+ subscriptions: true
tracing:
enabled: true
sampling_rate: 1
@@ -47,9 +66,10 @@ plugins:
engine:
max_concurrent_resolvers: 1024
+ enable_single_flight: true
debug:
report_websocket_connections: true
- report_memory_usage: true
+ report_memory_usage: false
events:
providers:
diff --git a/router/go.mod b/router/go.mod
index 714982861c..c2604da4a6 100644
--- a/router/go.mod
+++ b/router/go.mod
@@ -31,7 +31,7 @@ require (
github.com/tidwall/gjson v1.18.0
github.com/tidwall/sjson v1.2.5
github.com/twmb/franz-go v1.16.1
- github.com/wundergraph/graphql-go-tools/v2 v2.0.0
+ github.com/wundergraph/graphql-go-tools/v2 v2.1.0
// Do not upgrade, it renames attributes we rely on
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0
go.opentelemetry.io/contrib/propagators/b3 v1.23.0
@@ -97,6 +97,7 @@ require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cilium/ebpf v0.9.1 // indirect
+ github.com/coder/websocket v1.8.14 // indirect
github.com/containerd/cgroups/v3 v3.0.2 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
@@ -148,7 +149,7 @@ require (
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/r3labs/sse/v2 v2.8.1 // indirect
- github.com/rs/xid v1.5.0 // indirect
+ github.com/rs/xid v1.6.0 // indirect
github.com/segmentio/asm v1.1.3 // indirect
github.com/segmentio/encoding v0.5.4 // indirect
github.com/sergi/go-diff v1.3.1 // indirect
@@ -197,4 +198,4 @@ replace (
// Remember you can use Go workspaces to avoid using replace directives in multiple go.mod files
// Use what is best for your personal workflow. See CONTRIBUTING.md for more information
-// replace github.com/wundergraph/graphql-go-tools/v2 => ../../graphql-go-tools/v2
+//replace github.com/wundergraph/graphql-go-tools/v2 => ../../graphql-go-tools/v2
diff --git a/router/go.sum b/router/go.sum
index 26021d5fcc..561cbf94cd 100644
--- a/router/go.sum
+++ b/router/go.sum
@@ -43,8 +43,8 @@ github.com/cilium/ebpf v0.9.1 h1:64sn2K3UKw8NbP/blsixRpF3nXuyhz/VjRlRzvlBRu4=
github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY=
github.com/cloudflare/backoff v0.0.0-20161212185259-647f3cdfc87a h1:8d1CEOF1xldesKds5tRG3tExBsMOgWYownMHNCsev54=
github.com/cloudflare/backoff v0.0.0-20161212185259-647f3cdfc87a/go.mod h1:rzgs2ZOiguV6/NpiDgADjRLPNyZlApIWxKpkT+X8SdY=
-github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo=
-github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs=
+github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g=
+github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg=
github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0=
github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE=
github.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRccTampEyKpjpOnS3CyiV1Ebr8=
@@ -255,8 +255,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
-github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
-github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
+github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
+github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
github.com/sebdah/goldie/v2 v2.7.1 h1:PkBHymaYdtvEkZV7TmyqKxdmn5/Vcj+8TpATWZjnG5E=
@@ -327,8 +327,8 @@ github.com/wundergraph/astjson v1.1.0 h1:xORDosrZ87zQFJwNGe/HIHXqzpdHOFmqWgykCLV
github.com/wundergraph/astjson v1.1.0/go.mod h1:h12D/dxxnedtLzsKyBLK7/Oe4TAoGpRVC9nDpDrZSWw=
github.com/wundergraph/go-arena v1.1.0 h1:9+wSRkJAkA2vbYHp6s8tEGhPViRGQNGXqPHT0QzhdIc=
github.com/wundergraph/go-arena v1.1.0/go.mod h1:ROOysEHWJjLQ8FSfNxZCziagb7Qw2nXY3/vgKRh7eWw=
-github.com/wundergraph/graphql-go-tools/v2 v2.0.0 h1:F9hXgakaKxQen04cunNP2bdEl19GH/YGn7tISjeUf2M=
-github.com/wundergraph/graphql-go-tools/v2 v2.0.0/go.mod h1:HjTAO/cuICpu31IfHY9qmSPygx6Gza7Wt9hTSReTI+A=
+github.com/wundergraph/graphql-go-tools/v2 v2.1.0 h1:V1MU/uo+oc5b+aIh3SpCr0rJgLHuhonWg2fhN1sfMdY=
+github.com/wundergraph/graphql-go-tools/v2 v2.1.0/go.mod h1:UG/grnPEHumtD82H8FC+3dokiCGK8GF0b5IJc00lSbM=
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=
diff --git a/router/internal/wsproto/absinthe.go b/router/internal/wsproto/absinthe.go
index 656f4df151..ef9790da81 100644
--- a/router/internal/wsproto/absinthe.go
+++ b/router/internal/wsproto/absinthe.go
@@ -6,7 +6,6 @@ import (
"fmt"
"math/big"
- "github.com/gobwas/ws"
"github.com/tidwall/sjson"
)
@@ -204,14 +203,6 @@ func (p *absintheWSProtocol) WriteGraphQLErrors(id string, errors json.RawMessag
})
}
-func (p *absintheWSProtocol) Close(code ws.StatusCode, reason string) error {
- if err := p.conn.WriteCloseFrame(code, reason); err != nil {
- return err
- }
-
- return nil
-}
-
func (p *absintheWSProtocol) Complete(id string) error {
return p.conn.WriteJSON(absintheMessage{
ID: &id,
diff --git a/router/internal/wsproto/graphql_ws.go b/router/internal/wsproto/graphql_ws.go
index b559e8faf0..f4215ebbd1 100644
--- a/router/internal/wsproto/graphql_ws.go
+++ b/router/internal/wsproto/graphql_ws.go
@@ -3,8 +3,6 @@ package wsproto
import (
"encoding/json"
"fmt"
-
- "github.com/gobwas/ws"
)
// See protocol at https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md
@@ -55,7 +53,10 @@ func (p *graphQLWSProtocol) Initialize() (json.RawMessage, error) {
return nil, fmt.Errorf("error reading connection_init: %w", err)
}
if msg.Type != graphQLWSMessageTypeConnectionInit {
- return nil, fmt.Errorf("first message should be %s, got %s", graphQLWSMessageTypeConnectionInit, msg.Type)
+ return nil, &CloseError{
+ Err: fmt.Errorf("first message should be %s, got %s", graphQLWSMessageTypeConnectionInit, msg.Type),
+ Kind: CloseKindUnauthorized,
+ }
}
if err := p.conn.WriteJSON(graphQLWSMessage{Type: graphQLWSMessageTypeConnectionAck}); err != nil {
return nil, fmt.Errorf("sending %s: %w", graphQLWSMessageTypeConnectionAck, err)
@@ -78,8 +79,23 @@ func (p *graphQLWSProtocol) ReadMessage() (*Message, error) {
messageType = MessageTypeSubscribe
case graphQLWSMessageTypeComplete:
messageType = MessageTypeComplete
+ case graphQLWSMessageTypeConnectionInit:
+ return nil, &CloseError{
+ Err: fmt.Errorf("duplicate connection_init"),
+ Kind: CloseKindTooManyInits,
+ }
default:
- return nil, fmt.Errorf("unsupported message type %s", msg.Type)
+ // graphql-transport-ws spec requires closing with 4400 for unknown types.
+ return nil, &CloseError{
+ Err: fmt.Errorf("unsupported message type %s", msg.Type),
+ Kind: CloseKindInvalidMessageType,
+ }
+ }
+
+ if messageType == MessageTypeSubscribe || messageType == MessageTypeComplete {
+ if msg.ID == "" {
+ return nil, fmt.Errorf("missing id in %s message", msg.Type)
+ }
}
return &Message{
@@ -116,14 +132,6 @@ func (p *graphQLWSProtocol) WriteGraphQLErrors(id string, errors json.RawMessage
})
}
-func (p *graphQLWSProtocol) Close(code ws.StatusCode, reason string) error {
- if err := p.conn.WriteCloseFrame(code, reason); err != nil {
- return err
- }
-
- return nil
-}
-
func (p *graphQLWSProtocol) Complete(id string) error {
return p.conn.WriteJSON(
graphQLWSMessage{ID: id, Type: graphQLWSMessageTypeComplete},
diff --git a/router/internal/wsproto/proto.go b/router/internal/wsproto/proto.go
index d89fa0c943..c2c09ba9c5 100644
--- a/router/internal/wsproto/proto.go
+++ b/router/internal/wsproto/proto.go
@@ -2,6 +2,7 @@ package wsproto
import (
"encoding/json"
+ "errors"
"fmt"
"slices"
"strings"
@@ -11,8 +12,13 @@ import (
type Proto interface {
Subprotocol() string
- // Initialize starts the protocol and returns the initial payload received from the client
+ // Initialize starts the protocol and returns the initial payload received from the client.
+ // On a protocol-level rejection (bad first message, etc.) it returns a *CloseError carrying
+ // the close code and reason. The transport-layer caller writes the close frame.
Initialize() (json.RawMessage, error)
+ // ReadMessage reads the next message from the client. On a protocol-level rejection
+ // (duplicate connection_init, unknown message type, etc.) it returns a *CloseError; the
+ // transport-layer caller writes the close frame.
ReadMessage() (*Message, error)
Pong(*Message) error
@@ -21,9 +27,6 @@ type Proto interface {
// Complete is sent to indicate the requested operation is done and no more results will come in
Complete(id string) error
-
- // Close sends a close frame with the given code and reason
- Close(code ws.StatusCode, reason string) error
}
type ProtoConn interface {
@@ -32,6 +35,53 @@ type ProtoConn interface {
WriteCloseFrame(code ws.StatusCode, reason string) error
}
+// CloseKind is the WebSocket close code and reason sent to the downstream client
+// when the connection handler tears down. Connection-level concern — never sent
+// from the resolver.
+type CloseKind struct {
+ Code ws.StatusCode
+ Reason string
+}
+
+var (
+ CloseKindNormal = CloseKind{Code: ws.StatusNormalClosure, Reason: "Normal closure"}
+ CloseKindGoingAway = CloseKind{Code: ws.StatusGoingAway, Reason: "Going away"}
+ CloseKindUnauthorized = CloseKind{Code: 4401, Reason: "Unauthorized"}
+ CloseKindTooManyInits = CloseKind{Code: 4429, Reason: "Too many initialisation requests"}
+ CloseKindInvalidMessageType = CloseKind{Code: 4400, Reason: "Invalid message type"}
+)
+
+// CloseError signals that the protocol layer (or a downstream handler) wants the
+// connection torn down with a specific close kind. The protocol layer does not
+// write the close frame itself — it returns this error so the transport-layer
+// message loop owns the single Close call. Unwraps to the underlying cause for
+// log/debug purposes.
+type CloseError struct {
+ Err error
+ Kind CloseKind
+}
+
+func (e *CloseError) Error() string {
+ if e.Err != nil {
+ return e.Err.Error()
+ }
+ return e.Kind.Reason
+}
+
+func (e *CloseError) Unwrap() error { return e.Err }
+
+// CloseKindOf returns the close kind to use when tearing down a connection
+// after err. Errors that wrap a *CloseError carry their own kind; everything
+// else (network read failure, JSON decode error, etc.) falls back to
+// CloseKindNormal.
+func CloseKindOf(err error) CloseKind {
+ var ce *CloseError
+ if errors.As(err, &ce) {
+ return ce.Kind
+ }
+ return CloseKindNormal
+}
+
// MessageType indicates the type of the message received from the client
type MessageType int
diff --git a/router/internal/wsproto/subscriptions_transport_ws.go b/router/internal/wsproto/subscriptions_transport_ws.go
index 3245630aa5..b1603a7183 100644
--- a/router/internal/wsproto/subscriptions_transport_ws.go
+++ b/router/internal/wsproto/subscriptions_transport_ws.go
@@ -4,7 +4,6 @@ import (
"encoding/json"
"fmt"
- "github.com/gobwas/ws"
"github.com/tidwall/sjson"
)
@@ -58,7 +57,10 @@ func (p *subscriptionsTransportWSProtocol) Initialize() (json.RawMessage, error)
return nil, fmt.Errorf("error reading connection_init: %w", err)
}
if msg.Type != subscriptionsTransportWSMessageTypeConnectionInit {
- return nil, fmt.Errorf("first message should be %s, got %s", subscriptionsTransportWSMessageTypeConnectionInit, msg.Type)
+ return nil, &CloseError{
+ Err: fmt.Errorf("first message should be %s, got %s", subscriptionsTransportWSMessageTypeConnectionInit, msg.Type),
+ Kind: CloseKindUnauthorized,
+ }
}
if err := p.conn.WriteJSON(subscriptionsTransportWSMessage{Type: subscriptionsTransportWSMessageTypeConnectionAck}); err != nil {
return nil, fmt.Errorf("sending %s: %w", subscriptionsTransportWSMessageTypeConnectionAck, err)
@@ -79,8 +81,16 @@ func (p *subscriptionsTransportWSProtocol) ReadMessage() (*Message, error) {
messageType = MessageTypeSubscribe
case subscriptionsTransportWSMessageTypeStop:
messageType = MessageTypeComplete
+ case subscriptionsTransportWSMessageTypeConnectionInit:
+ return nil, &CloseError{
+ Err: fmt.Errorf("duplicate connection_init"),
+ Kind: CloseKindTooManyInits,
+ }
default:
- return nil, fmt.Errorf("unsupported message type %s", msg.Type)
+ return nil, &CloseError{
+ Err: fmt.Errorf("unsupported message type %s", msg.Type),
+ Kind: CloseKindInvalidMessageType,
+ }
}
return &Message{
@@ -108,7 +118,10 @@ func (p *subscriptionsTransportWSProtocol) WriteGraphQLData(id string, data json
}
func (p *subscriptionsTransportWSProtocol) WriteGraphQLErrors(id string, errors json.RawMessage, extensions json.RawMessage) error {
- // This protocol has errors inside an object, so we need to wrap it
+ // subscriptions-transport-ws reserves "error" for pre-execution failures,
+ // so runtime errors are delivered as a "data" frame with the errors inside
+ // the ExecutionResult. Callers decide whether to follow up with "complete"
+ // (for terminal errors) via Complete.
data, err := sjson.SetBytes([]byte(`{}`), "errors", errors)
if err != nil {
return fmt.Errorf("encoding JSON: %w", err)
@@ -121,14 +134,6 @@ func (p *subscriptionsTransportWSProtocol) WriteGraphQLErrors(id string, errors
})
}
-func (p *subscriptionsTransportWSProtocol) Close(code ws.StatusCode, reason string) error {
- if err := p.conn.WriteCloseFrame(code, reason); err != nil {
- return err
- }
-
- return nil
-}
-
func (p *subscriptionsTransportWSProtocol) Complete(id string) error {
return p.conn.WriteJSON(subscriptionsTransportWSMessage{
ID: id,
diff --git a/router/pkg/config/config.go b/router/pkg/config/config.go
index 225f68c6b4..22f58cf72a 100644
--- a/router/pkg/config/config.go
+++ b/router/pkg/config/config.go
@@ -426,18 +426,11 @@ type EngineExecutionConfiguration struct {
ForceEnableInboundRequestDeduplication bool `envDefault:"false" env:"ENGINE_FORCE_ENABLE_INBOUND_REQUEST_DEDUPLICATION" yaml:"force_enable_inbound_request_deduplication"`
EnableRequestTracing bool `envDefault:"true" env:"ENGINE_ENABLE_REQUEST_TRACING" yaml:"enable_request_tracing"`
- // EnableExecutionPlanCacheResponseHeader is deprecated, use EngineDebugConfiguration.EnableCacheResponseHeaders instead.
+ // Deprecated: EnableExecutionPlanCacheResponseHeader is deprecated, use EngineDebugConfiguration.EnableCacheResponseHeaders instead.
EnableExecutionPlanCacheResponseHeader bool `envDefault:"false" env:"ENGINE_ENABLE_EXECUTION_PLAN_CACHE_RESPONSE_HEADER" yaml:"enable_execution_plan_cache_response_header"`
MaxConcurrentResolvers int `envDefault:"1024" env:"ENGINE_MAX_CONCURRENT_RESOLVERS" yaml:"max_concurrent_resolvers,omitempty"`
EnableNetPoll bool `envDefault:"true" env:"ENGINE_ENABLE_NET_POLL" yaml:"enable_net_poll"`
- WebSocketClientPollTimeout time.Duration `envDefault:"1s" env:"ENGINE_WEBSOCKET_CLIENT_POLL_TIMEOUT" yaml:"websocket_client_poll_timeout,omitempty"`
- WebSocketClientConnBufferSize int `envDefault:"128" env:"ENGINE_WEBSOCKET_CLIENT_CONN_BUFFER_SIZE" yaml:"websocket_client_conn_buffer_size,omitempty"`
- WebSocketClientReadTimeout time.Duration `envDefault:"5s" env:"ENGINE_WEBSOCKET_CLIENT_READ_TIMEOUT" yaml:"websocket_client_read_timeout,omitempty"`
- WebSocketClientWriteTimeout time.Duration `envDefault:"10s" env:"ENGINE_WEBSOCKET_CLIENT_WRITE_TIMEOUT" yaml:"websocket_client_write_timeout,omitempty"`
- WebSocketClientPingInterval time.Duration `envDefault:"15s" env:"ENGINE_WEBSOCKET_CLIENT_PING_INTERVAL" yaml:"websocket_client_ping_interval,omitempty"`
- WebSocketClientPingTimeout time.Duration `envDefault:"30s" env:"ENGINE_WEBSOCKET_CLIENT_PING_TIMEOUT" yaml:"websocket_client_ping_timeout,omitempty"`
- WebSocketClientFrameTimeout time.Duration `envDefault:"100ms" env:"ENGINE_WEBSOCKET_CLIENT_FRAME_TIMEOUT" yaml:"websocket_client_frame_timeout,omitempty"`
ExecutionPlanCacheSize int64 `envDefault:"1024" env:"ENGINE_EXECUTION_PLAN_CACHE_SIZE" yaml:"execution_plan_cache_size,omitempty"`
SlowPlanCacheSize int64 `envDefault:"300" env:"ENGINE_SLOW_PLAN_CACHE_SIZE" yaml:"slow_plan_cache_size,omitempty"`
SlowPlanCacheThreshold time.Duration `envDefault:"100ms" env:"ENGINE_SLOW_PLAN_CACHE_THRESHOLD" yaml:"slow_plan_cache_threshold,omitempty"`
@@ -456,6 +449,19 @@ type EngineExecutionConfiguration struct {
EnableRequireFetchReasons bool `envDefault:"false" env:"ENGINE_ENABLE_REQUIRE_FETCH_REASONS" yaml:"enable_require_fetch_reasons"`
SubscriptionFetchTimeout time.Duration `envDefault:"30s" env:"ENGINE_SUBSCRIPTION_FETCH_TIMEOUT" yaml:"subscription_fetch_timeout,omitempty"`
+ // Server-side WebSocket handler options (router accepting client connections)
+ WebSocketServerReadTimeout time.Duration `envDefault:"5s" env:"ENGINE_WEBSOCKET_SERVER_READ_TIMEOUT" yaml:"websocket_server_read_timeout,omitempty"`
+ WebSocketServerWriteTimeout time.Duration `envDefault:"10s" env:"ENGINE_WEBSOCKET_SERVER_WRITE_TIMEOUT" yaml:"websocket_server_write_timeout,omitempty"`
+ WebSocketServerPollTimeout time.Duration `envDefault:"1s" env:"ENGINE_WEBSOCKET_SERVER_POLL_TIMEOUT" yaml:"websocket_server_poll_timeout,omitempty"`
+ WebSocketServerConnBufferSize int `envDefault:"128" env:"ENGINE_WEBSOCKET_SERVER_CONN_BUFFER_SIZE" yaml:"websocket_server_conn_buffer_size,omitempty"`
+
+ // Subscription client options (router connecting to subgraphs)
+ WebSocketClientWriteTimeout time.Duration `envDefault:"10s" env:"ENGINE_WEBSOCKET_CLIENT_WRITE_TIMEOUT" yaml:"websocket_client_write_timeout,omitempty"`
+ WebSocketClientReadLimit BytesString `envDefault:"1MB" env:"ENGINE_WEBSOCKET_CLIENT_READ_LIMIT" yaml:"websocket_client_read_limit,omitempty"`
+ WebSocketClientPingInterval time.Duration `envDefault:"15s" env:"ENGINE_WEBSOCKET_CLIENT_PING_INTERVAL" yaml:"websocket_client_ping_interval,omitempty"`
+ WebSocketClientPingTimeout time.Duration `envDefault:"30s" env:"ENGINE_WEBSOCKET_CLIENT_PING_TIMEOUT" yaml:"websocket_client_ping_timeout,omitempty"`
+ WebSocketClientAckTimeout time.Duration `envDefault:"30s" env:"ENGINE_WEBSOCKET_CLIENT_ACK_TIMEOUT" yaml:"websocket_client_ack_timeout,omitempty"`
+
ValidateRequiredExternalFields bool `envDefault:"false" env:"ENGINE_VALIDATE_REQUIRED_EXTERNAL_FIELDS" yaml:"validate_required_external_fields"`
RelaxSubgraphOperationFieldSelectionMergingNullability bool `envDefault:"false" env:"ENGINE_RELAX_SUBGRAPH_OPERATION_FIELD_SELECTION_MERGING_NULLABILITY" yaml:"relax_subgraph_operation_field_selection_merging_nullability"`
diff --git a/router/pkg/config/config.schema.json b/router/pkg/config/config.schema.json
index 54fa556e93..e90ae50407 100644
--- a/router/pkg/config/config.schema.json
+++ b/router/pkg/config/config.schema.json
@@ -3555,28 +3555,34 @@
"description": "Enables the more efficient poll implementation for all WebSocket implementations (client, server) of the router. This is only available on Linux and MacOS. On Windows or when the host system is limited, the default synchronous implementation is used.",
"default": true
},
- "websocket_client_poll_timeout": {
+ "websocket_client_write_timeout": {
"type": "string",
"format": "go-duration",
- "default": "1s",
- "description": "The timeout for the poll loop of the WebSocket client implementation. The timeout is specified as a string with a number and a unit, e.g. 10ms, 1s, 1m, 1h. The supported units are 'ms', 's', 'm', 'h'."
+ "default": "10s",
+ "description": "The write timeout for WebSocket operations when the router connects to subgraphs (subscribe, unsubscribe, ping, pong). The timeout is specified as a string with a number and a unit, e.g. 10ms, 1s, 1m, 1h. The supported units are 'ms', 's', 'm', 'h'."
},
- "websocket_client_conn_buffer_size": {
- "type": "integer",
- "default": 128,
- "description": "The buffer size for the poll buffer of the WebSocket client implementation. The buffer size determines how many connections can be handled in one loop."
+ "websocket_server_read_timeout": {
+ "type": "string",
+ "format": "go-duration",
+ "description": "The read timeout for the server-side WebSocket handler. The timeout is specified as a string with a number and a unit, e.g. 10ms, 1s, 1m, 1h. The supported units are 'ms', 's', 'm', 'h'.",
+ "default": "5s"
},
- "websocket_client_read_timeout": {
+ "websocket_server_write_timeout": {
"type": "string",
"format": "go-duration",
- "default": "5s",
- "description": "Defines the timeout for the websocket read of the WebSocket client implementation. This is used to set the read deadline for the connection. The timeout is specified as a string with a number and a unit, e.g. 10ms, 1s, 1m, 1h. The supported units are 'ms', 's', 'm', 'h'."
+ "description": "The write timeout for the server-side WebSocket handler. The timeout is specified as a string with a number and a unit, e.g. 10ms, 1s, 1m, 1h. The supported units are 'ms', 's', 'm', 'h'.",
+ "default": "10s"
},
- "websocket_client_write_timeout": {
+ "websocket_server_poll_timeout": {
"type": "string",
"format": "go-duration",
- "default": "10s",
- "description": "Defines the timeout for the websocket write of the WebSocket client implementation. This is used to set the write deadline for the connection. The timeout is specified as a string with a number and a unit, e.g. 10ms, 1s, 1m, 1h. The supported units are 'ms', 's', 'm', 'h'."
+ "description": "The poll timeout for the server-side WebSocket net poller. The timeout is specified as a string with a number and a unit, e.g. 10ms, 1s, 1m, 1h. The supported units are 'ms', 's', 'm', 'h'.",
+ "default": "1s"
+ },
+ "websocket_server_conn_buffer_size": {
+ "type": "integer",
+ "default": 128,
+ "description": "The buffer size for the server-side WebSocket net poller. Determines how many connections can be handled in one poll loop."
},
"websocket_client_ping_interval": {
"type": "string",
@@ -3596,13 +3602,22 @@
"minimum": "5s"
}
},
- "websocket_client_frame_timeout": {
+ "websocket_client_ack_timeout": {
"type": "string",
"format": "go-duration",
- "description": "The Websocket client frame timeout to the subgraph. Defines how long the router will wait for a frame response from the subgraph. The timeout is specified as a string with a number and a unit, e.g. 10ms, 1s, 1m, 1h. The supported units are 'ms', 's', 'm', 'h'.",
- "default": "100ms",
+ "description": "The maximum time to wait for a connection_ack message after sending connection_init to a subgraph WebSocket. The timeout is specified as a string with a number and a unit, e.g. 10ms, 1s, 1m, 1h. The supported units are 'ms', 's', 'm', 'h'.",
+ "default": "30s",
"duration": {
- "minimum": "10ms"
+ "minimum": "1s"
+ }
+ },
+ "websocket_client_read_limit": {
+ "type": "string",
+ "format": "bytes-string",
+ "description": "The maximum size of an incoming WebSocket message from a subgraph. The size is specified as a string with a number and a unit, e.g. 1KB, 1MB, 10MB. The supported units are 'KB', 'MB', 'GB'.",
+ "default": "1MB",
+ "bytes": {
+ "minimum": "1KB"
}
},
"execution_plan_cache_size": {
diff --git a/router/pkg/config/fixtures/full.yaml b/router/pkg/config/fixtures/full.yaml
index eed7b3f973..42c6986d38 100644
--- a/router/pkg/config/fixtures/full.yaml
+++ b/router/pkg/config/fixtures/full.yaml
@@ -376,13 +376,15 @@ engine:
max_concurrent_resolvers: 32
enable_net_poll: true
enable_subgraph_fetch_operation_name: true
- websocket_client_poll_timeout: 1s
- websocket_client_conn_buffer_size: 128
- websocket_client_read_timeout: 5s
websocket_client_write_timeout: 10s
- websocket_client_frame_timeout: 100ms
+ websocket_server_read_timeout: 5s
+ websocket_server_write_timeout: 10s
+ websocket_server_poll_timeout: 1s
+ websocket_server_conn_buffer_size: 128
+ websocket_client_read_limit: 1MB
websocket_client_ping_interval: 10s
websocket_client_ping_timeout: 30s
+ websocket_client_ack_timeout: 30s
execution_plan_cache_size: 1024
resolver_max_recyclable_parser_size: 4096
debug:
diff --git a/router/pkg/config/testdata/config_defaults.json b/router/pkg/config/testdata/config_defaults.json
index d64a0b40fb..8dc81bf6ed 100644
--- a/router/pkg/config/testdata/config_defaults.json
+++ b/router/pkg/config/testdata/config_defaults.json
@@ -444,13 +444,6 @@
"EnableExecutionPlanCacheResponseHeader": false,
"MaxConcurrentResolvers": 1024,
"EnableNetPoll": true,
- "WebSocketClientPollTimeout": 1000000000,
- "WebSocketClientConnBufferSize": 128,
- "WebSocketClientReadTimeout": 5000000000,
- "WebSocketClientWriteTimeout": 10000000000,
- "WebSocketClientPingInterval": 15000000000,
- "WebSocketClientPingTimeout": 30000000000,
- "WebSocketClientFrameTimeout": 100000000,
"ExecutionPlanCacheSize": 1024,
"SlowPlanCacheSize": 300,
"SlowPlanCacheThreshold": 100000000,
@@ -468,6 +461,15 @@
"DisableVariablesRemapping": false,
"EnableRequireFetchReasons": false,
"SubscriptionFetchTimeout": 30000000000,
+ "WebSocketServerReadTimeout": 5000000000,
+ "WebSocketServerWriteTimeout": 10000000000,
+ "WebSocketServerPollTimeout": 1000000000,
+ "WebSocketServerConnBufferSize": 128,
+ "WebSocketClientWriteTimeout": 10000000000,
+ "WebSocketClientReadLimit": 1000000,
+ "WebSocketClientPingInterval": 15000000000,
+ "WebSocketClientPingTimeout": 30000000000,
+ "WebSocketClientAckTimeout": 30000000000,
"ValidateRequiredExternalFields": false,
"RelaxSubgraphOperationFieldSelectionMergingNullability": false
},
diff --git a/router/pkg/config/testdata/config_full.json b/router/pkg/config/testdata/config_full.json
index fbc42cf002..33cc0c92e6 100644
--- a/router/pkg/config/testdata/config_full.json
+++ b/router/pkg/config/testdata/config_full.json
@@ -864,13 +864,6 @@
"EnableExecutionPlanCacheResponseHeader": false,
"MaxConcurrentResolvers": 32,
"EnableNetPoll": true,
- "WebSocketClientPollTimeout": 1000000000,
- "WebSocketClientConnBufferSize": 128,
- "WebSocketClientReadTimeout": 5000000000,
- "WebSocketClientWriteTimeout": 10000000000,
- "WebSocketClientPingInterval": 10000000000,
- "WebSocketClientPingTimeout": 30000000000,
- "WebSocketClientFrameTimeout": 100000000,
"ExecutionPlanCacheSize": 1024,
"SlowPlanCacheSize": 300,
"SlowPlanCacheThreshold": 100000000,
@@ -888,6 +881,15 @@
"DisableVariablesRemapping": false,
"EnableRequireFetchReasons": false,
"SubscriptionFetchTimeout": 30000000000,
+ "WebSocketServerReadTimeout": 5000000000,
+ "WebSocketServerWriteTimeout": 10000000000,
+ "WebSocketServerPollTimeout": 1000000000,
+ "WebSocketServerConnBufferSize": 128,
+ "WebSocketClientWriteTimeout": 10000000000,
+ "WebSocketClientReadLimit": 1000000,
+ "WebSocketClientPingInterval": 10000000000,
+ "WebSocketClientPingTimeout": 30000000000,
+ "WebSocketClientAckTimeout": 30000000000,
"ValidateRequiredExternalFields": false,
"RelaxSubgraphOperationFieldSelectionMergingNullability": false
},
diff --git a/router/pkg/pubsub/datasource/mocks.go b/router/pkg/pubsub/datasource/mocks.go
index 69b5a7eab8..cbada9235a 100644
--- a/router/pkg/pubsub/datasource/mocks.go
+++ b/router/pkg/pubsub/datasource/mocks.go
@@ -1102,75 +1102,68 @@ func (_m *MockSubscriptionEventUpdater) EXPECT() *MockSubscriptionEventUpdater_E
return &MockSubscriptionEventUpdater_Expecter{mock: &_m.Mock}
}
-// Close provides a mock function for the type MockSubscriptionEventUpdater
-func (_mock *MockSubscriptionEventUpdater) Close(kind resolve.SubscriptionCloseKind) {
- _mock.Called(kind)
+// Complete provides a mock function for the type MockSubscriptionEventUpdater
+func (_mock *MockSubscriptionEventUpdater) Complete() {
+ _mock.Called()
return
}
-// MockSubscriptionEventUpdater_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close'
-type MockSubscriptionEventUpdater_Close_Call struct {
+// MockSubscriptionEventUpdater_Complete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Complete'
+type MockSubscriptionEventUpdater_Complete_Call struct {
*mock.Call
}
-// Close is a helper method to define mock.On call
-// - kind resolve.SubscriptionCloseKind
-func (_e *MockSubscriptionEventUpdater_Expecter) Close(kind interface{}) *MockSubscriptionEventUpdater_Close_Call {
- return &MockSubscriptionEventUpdater_Close_Call{Call: _e.mock.On("Close", kind)}
+// Complete is a helper method to define mock.On call
+func (_e *MockSubscriptionEventUpdater_Expecter) Complete() *MockSubscriptionEventUpdater_Complete_Call {
+ return &MockSubscriptionEventUpdater_Complete_Call{Call: _e.mock.On("Complete")}
}
-func (_c *MockSubscriptionEventUpdater_Close_Call) Run(run func(kind resolve.SubscriptionCloseKind)) *MockSubscriptionEventUpdater_Close_Call {
+func (_c *MockSubscriptionEventUpdater_Complete_Call) Run(run func()) *MockSubscriptionEventUpdater_Complete_Call {
_c.Call.Run(func(args mock.Arguments) {
- var arg0 resolve.SubscriptionCloseKind
- if args[0] != nil {
- arg0 = args[0].(resolve.SubscriptionCloseKind)
- }
- run(
- arg0,
- )
+ run()
})
return _c
}
-func (_c *MockSubscriptionEventUpdater_Close_Call) Return() *MockSubscriptionEventUpdater_Close_Call {
+func (_c *MockSubscriptionEventUpdater_Complete_Call) Return() *MockSubscriptionEventUpdater_Complete_Call {
_c.Call.Return()
return _c
}
-func (_c *MockSubscriptionEventUpdater_Close_Call) RunAndReturn(run func(kind resolve.SubscriptionCloseKind)) *MockSubscriptionEventUpdater_Close_Call {
+func (_c *MockSubscriptionEventUpdater_Complete_Call) RunAndReturn(run func()) *MockSubscriptionEventUpdater_Complete_Call {
_c.Run(run)
return _c
}
-// Complete provides a mock function for the type MockSubscriptionEventUpdater
-func (_mock *MockSubscriptionEventUpdater) Complete() {
+// Done provides a mock function for the type MockSubscriptionEventUpdater
+func (_mock *MockSubscriptionEventUpdater) Done() {
_mock.Called()
return
}
-// MockSubscriptionEventUpdater_Complete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Complete'
-type MockSubscriptionEventUpdater_Complete_Call struct {
+// MockSubscriptionEventUpdater_Done_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Done'
+type MockSubscriptionEventUpdater_Done_Call struct {
*mock.Call
}
-// Complete is a helper method to define mock.On call
-func (_e *MockSubscriptionEventUpdater_Expecter) Complete() *MockSubscriptionEventUpdater_Complete_Call {
- return &MockSubscriptionEventUpdater_Complete_Call{Call: _e.mock.On("Complete")}
+// Done is a helper method to define mock.On call
+func (_e *MockSubscriptionEventUpdater_Expecter) Done() *MockSubscriptionEventUpdater_Done_Call {
+ return &MockSubscriptionEventUpdater_Done_Call{Call: _e.mock.On("Done")}
}
-func (_c *MockSubscriptionEventUpdater_Complete_Call) Run(run func()) *MockSubscriptionEventUpdater_Complete_Call {
+func (_c *MockSubscriptionEventUpdater_Done_Call) Run(run func()) *MockSubscriptionEventUpdater_Done_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
-func (_c *MockSubscriptionEventUpdater_Complete_Call) Return() *MockSubscriptionEventUpdater_Complete_Call {
+func (_c *MockSubscriptionEventUpdater_Done_Call) Return() *MockSubscriptionEventUpdater_Done_Call {
_c.Call.Return()
return _c
}
-func (_c *MockSubscriptionEventUpdater_Complete_Call) RunAndReturn(run func()) *MockSubscriptionEventUpdater_Complete_Call {
+func (_c *MockSubscriptionEventUpdater_Done_Call) RunAndReturn(run func()) *MockSubscriptionEventUpdater_Done_Call {
_c.Run(run)
return _c
}
diff --git a/router/pkg/pubsub/datasource/mocks_resolve.go b/router/pkg/pubsub/datasource/mocks_resolve.go
index 19bad89c16..876bd75172 100644
--- a/router/pkg/pubsub/datasource/mocks_resolve.go
+++ b/router/pkg/pubsub/datasource/mocks_resolve.go
@@ -38,28 +38,28 @@ func (_m *MockSubscriptionUpdater) EXPECT() *MockSubscriptionUpdater_Expecter {
return &MockSubscriptionUpdater_Expecter{mock: &_m.Mock}
}
-// Close provides a mock function for the type MockSubscriptionUpdater
-func (_mock *MockSubscriptionUpdater) Close(kind resolve.SubscriptionCloseKind) {
- _mock.Called(kind)
+// CloseSubscription provides a mock function for the type MockSubscriptionUpdater
+func (_mock *MockSubscriptionUpdater) CloseSubscription(id resolve.SubscriptionIdentifier) {
+ _mock.Called(id)
return
}
-// MockSubscriptionUpdater_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close'
-type MockSubscriptionUpdater_Close_Call struct {
+// MockSubscriptionUpdater_CloseSubscription_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CloseSubscription'
+type MockSubscriptionUpdater_CloseSubscription_Call struct {
*mock.Call
}
-// Close is a helper method to define mock.On call
-// - kind resolve.SubscriptionCloseKind
-func (_e *MockSubscriptionUpdater_Expecter) Close(kind interface{}) *MockSubscriptionUpdater_Close_Call {
- return &MockSubscriptionUpdater_Close_Call{Call: _e.mock.On("Close", kind)}
+// CloseSubscription is a helper method to define mock.On call
+// - id resolve.SubscriptionIdentifier
+func (_e *MockSubscriptionUpdater_Expecter) CloseSubscription(id interface{}) *MockSubscriptionUpdater_CloseSubscription_Call {
+ return &MockSubscriptionUpdater_CloseSubscription_Call{Call: _e.mock.On("CloseSubscription", id)}
}
-func (_c *MockSubscriptionUpdater_Close_Call) Run(run func(kind resolve.SubscriptionCloseKind)) *MockSubscriptionUpdater_Close_Call {
+func (_c *MockSubscriptionUpdater_CloseSubscription_Call) Run(run func(id resolve.SubscriptionIdentifier)) *MockSubscriptionUpdater_CloseSubscription_Call {
_c.Call.Run(func(args mock.Arguments) {
- var arg0 resolve.SubscriptionCloseKind
+ var arg0 resolve.SubscriptionIdentifier
if args[0] != nil {
- arg0 = args[0].(resolve.SubscriptionCloseKind)
+ arg0 = args[0].(resolve.SubscriptionIdentifier)
}
run(
arg0,
@@ -68,91 +68,118 @@ func (_c *MockSubscriptionUpdater_Close_Call) Run(run func(kind resolve.Subscrip
return _c
}
-func (_c *MockSubscriptionUpdater_Close_Call) Return() *MockSubscriptionUpdater_Close_Call {
+func (_c *MockSubscriptionUpdater_CloseSubscription_Call) Return() *MockSubscriptionUpdater_CloseSubscription_Call {
_c.Call.Return()
return _c
}
-func (_c *MockSubscriptionUpdater_Close_Call) RunAndReturn(run func(kind resolve.SubscriptionCloseKind)) *MockSubscriptionUpdater_Close_Call {
+func (_c *MockSubscriptionUpdater_CloseSubscription_Call) RunAndReturn(run func(id resolve.SubscriptionIdentifier)) *MockSubscriptionUpdater_CloseSubscription_Call {
_c.Run(run)
return _c
}
-// CloseSubscription provides a mock function for the type MockSubscriptionUpdater
-func (_mock *MockSubscriptionUpdater) CloseSubscription(kind resolve.SubscriptionCloseKind, id resolve.SubscriptionIdentifier) {
- _mock.Called(kind, id)
+// Complete provides a mock function for the type MockSubscriptionUpdater
+func (_mock *MockSubscriptionUpdater) Complete() {
+ _mock.Called()
return
}
-// MockSubscriptionUpdater_CloseSubscription_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CloseSubscription'
-type MockSubscriptionUpdater_CloseSubscription_Call struct {
+// MockSubscriptionUpdater_Complete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Complete'
+type MockSubscriptionUpdater_Complete_Call struct {
*mock.Call
}
-// CloseSubscription is a helper method to define mock.On call
-// - kind resolve.SubscriptionCloseKind
-// - id resolve.SubscriptionIdentifier
-func (_e *MockSubscriptionUpdater_Expecter) CloseSubscription(kind interface{}, id interface{}) *MockSubscriptionUpdater_CloseSubscription_Call {
- return &MockSubscriptionUpdater_CloseSubscription_Call{Call: _e.mock.On("CloseSubscription", kind, id)}
+// Complete is a helper method to define mock.On call
+func (_e *MockSubscriptionUpdater_Expecter) Complete() *MockSubscriptionUpdater_Complete_Call {
+ return &MockSubscriptionUpdater_Complete_Call{Call: _e.mock.On("Complete")}
}
-func (_c *MockSubscriptionUpdater_CloseSubscription_Call) Run(run func(kind resolve.SubscriptionCloseKind, id resolve.SubscriptionIdentifier)) *MockSubscriptionUpdater_CloseSubscription_Call {
+func (_c *MockSubscriptionUpdater_Complete_Call) Run(run func()) *MockSubscriptionUpdater_Complete_Call {
_c.Call.Run(func(args mock.Arguments) {
- var arg0 resolve.SubscriptionCloseKind
- if args[0] != nil {
- arg0 = args[0].(resolve.SubscriptionCloseKind)
- }
- var arg1 resolve.SubscriptionIdentifier
- if args[1] != nil {
- arg1 = args[1].(resolve.SubscriptionIdentifier)
- }
- run(
- arg0,
- arg1,
- )
+ run()
})
return _c
}
-func (_c *MockSubscriptionUpdater_CloseSubscription_Call) Return() *MockSubscriptionUpdater_CloseSubscription_Call {
+func (_c *MockSubscriptionUpdater_Complete_Call) Return() *MockSubscriptionUpdater_Complete_Call {
_c.Call.Return()
return _c
}
-func (_c *MockSubscriptionUpdater_CloseSubscription_Call) RunAndReturn(run func(kind resolve.SubscriptionCloseKind, id resolve.SubscriptionIdentifier)) *MockSubscriptionUpdater_CloseSubscription_Call {
+func (_c *MockSubscriptionUpdater_Complete_Call) RunAndReturn(run func()) *MockSubscriptionUpdater_Complete_Call {
_c.Run(run)
return _c
}
-// Complete provides a mock function for the type MockSubscriptionUpdater
-func (_mock *MockSubscriptionUpdater) Complete() {
+// Done provides a mock function for the type MockSubscriptionUpdater
+func (_mock *MockSubscriptionUpdater) Done() {
_mock.Called()
return
}
-// MockSubscriptionUpdater_Complete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Complete'
-type MockSubscriptionUpdater_Complete_Call struct {
+// MockSubscriptionUpdater_Done_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Done'
+type MockSubscriptionUpdater_Done_Call struct {
*mock.Call
}
-// Complete is a helper method to define mock.On call
-func (_e *MockSubscriptionUpdater_Expecter) Complete() *MockSubscriptionUpdater_Complete_Call {
- return &MockSubscriptionUpdater_Complete_Call{Call: _e.mock.On("Complete")}
+// Done is a helper method to define mock.On call
+func (_e *MockSubscriptionUpdater_Expecter) Done() *MockSubscriptionUpdater_Done_Call {
+ return &MockSubscriptionUpdater_Done_Call{Call: _e.mock.On("Done")}
}
-func (_c *MockSubscriptionUpdater_Complete_Call) Run(run func()) *MockSubscriptionUpdater_Complete_Call {
+func (_c *MockSubscriptionUpdater_Done_Call) Run(run func()) *MockSubscriptionUpdater_Done_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
-func (_c *MockSubscriptionUpdater_Complete_Call) Return() *MockSubscriptionUpdater_Complete_Call {
+func (_c *MockSubscriptionUpdater_Done_Call) Return() *MockSubscriptionUpdater_Done_Call {
_c.Call.Return()
return _c
}
-func (_c *MockSubscriptionUpdater_Complete_Call) RunAndReturn(run func()) *MockSubscriptionUpdater_Complete_Call {
+func (_c *MockSubscriptionUpdater_Done_Call) RunAndReturn(run func()) *MockSubscriptionUpdater_Done_Call {
+ _c.Run(run)
+ return _c
+}
+
+// Error provides a mock function for the type MockSubscriptionUpdater
+func (_mock *MockSubscriptionUpdater) Error(data []byte) {
+ _mock.Called(data)
+ return
+}
+
+// MockSubscriptionUpdater_Error_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Error'
+type MockSubscriptionUpdater_Error_Call struct {
+ *mock.Call
+}
+
+// Error is a helper method to define mock.On call
+// - data []byte
+func (_e *MockSubscriptionUpdater_Expecter) Error(data interface{}) *MockSubscriptionUpdater_Error_Call {
+ return &MockSubscriptionUpdater_Error_Call{Call: _e.mock.On("Error", data)}
+}
+
+func (_c *MockSubscriptionUpdater_Error_Call) Run(run func(data []byte)) *MockSubscriptionUpdater_Error_Call {
+ _c.Call.Run(func(args mock.Arguments) {
+ var arg0 []byte
+ if args[0] != nil {
+ arg0 = args[0].([]byte)
+ }
+ run(
+ arg0,
+ )
+ })
+ return _c
+}
+
+func (_c *MockSubscriptionUpdater_Error_Call) Return() *MockSubscriptionUpdater_Error_Call {
+ _c.Call.Return()
+ return _c
+}
+
+func (_c *MockSubscriptionUpdater_Error_Call) RunAndReturn(run func(data []byte)) *MockSubscriptionUpdater_Error_Call {
_c.Run(run)
return _c
}
diff --git a/router/pkg/pubsub/datasource/subscription_event_updater.go b/router/pkg/pubsub/datasource/subscription_event_updater.go
index df2224448d..03c3493ce7 100644
--- a/router/pkg/pubsub/datasource/subscription_event_updater.go
+++ b/router/pkg/pubsub/datasource/subscription_event_updater.go
@@ -19,7 +19,7 @@ const defaultTimeout = 5 * time.Second
type SubscriptionEventUpdater interface {
Update(events []StreamEvent)
Complete()
- Close(kind resolve.SubscriptionCloseKind)
+ Done()
SetHooks(hooks Hooks)
}
@@ -84,8 +84,8 @@ func (s *subscriptionEventUpdater) Complete() {
s.eventUpdater.Complete()
}
-func (s *subscriptionEventUpdater) Close(kind resolve.SubscriptionCloseKind) {
- s.eventUpdater.Close(kind)
+func (s *subscriptionEventUpdater) Done() {
+ s.eventUpdater.Done()
}
func (s *subscriptionEventUpdater) SetHooks(hooks Hooks) {
@@ -124,7 +124,7 @@ func (s *subscriptionEventUpdater) updateSubscription(subscriptionCtx context.Co
// In case there was an error we close the affected subscription.
if err != nil {
- s.eventUpdater.CloseSubscription(resolve.SubscriptionCloseKindNormal, subID)
+ s.eventUpdater.CloseSubscription(subID)
}
}
@@ -136,7 +136,7 @@ func (s *subscriptionEventUpdater) recoverPanic(subID resolve.SubscriptionIdenti
zap.Any("error", err),
)
- s.eventUpdater.CloseSubscription(resolve.SubscriptionCloseKindDownstreamServiceError, subID)
+ s.eventUpdater.CloseSubscription(subID)
}
func NewSubscriptionEventUpdater(
diff --git a/router/pkg/pubsub/datasource/subscription_event_updater_test.go b/router/pkg/pubsub/datasource/subscription_event_updater_test.go
index 2c7f6bac3e..411ab2bd98 100644
--- a/router/pkg/pubsub/datasource/subscription_event_updater_test.go
+++ b/router/pkg/pubsub/datasource/subscription_event_updater_test.go
@@ -145,7 +145,7 @@ func TestSubscriptionEventUpdater_UpdateSubscriptions_WithHooks_Error(t *testing
mockUpdater.On("Subscriptions").Return(map[context.Context]resolve.SubscriptionIdentifier{
context.Background(): subId,
})
- mockUpdater.On("CloseSubscription", resolve.SubscriptionCloseKindNormal, subId).Return()
+ mockUpdater.On("CloseSubscription", subId).Return()
// Should not call Update or UpdateSubscription on eventUpdater since hook fails
updater := NewSubscriptionEventUpdater(
@@ -165,7 +165,7 @@ func TestSubscriptionEventUpdater_UpdateSubscriptions_WithHooks_Error(t *testing
// Assert that Update and UpdateSubscription were not called on the eventUpdater
mockUpdater.AssertNotCalled(t, "Update")
mockUpdater.AssertNotCalled(t, "UpdateSubscription")
- mockUpdater.AssertCalled(t, "CloseSubscription", resolve.SubscriptionCloseKindNormal, subId)
+ mockUpdater.AssertCalled(t, "CloseSubscription", subId)
}
func TestSubscriptionEventUpdater_Update_WithMultipleHooks_Success(t *testing.T) {
@@ -270,7 +270,7 @@ func TestSubscriptionEventUpdater_Update_WithMultipleHooks_Error(t *testing.T) {
// Events from hook1 should still be sent despite the error
mockUpdater.On("UpdateSubscription", subId, []byte("original data")).Return()
// Subscription should be closed due to the error from hook1
- mockUpdater.On("CloseSubscription", resolve.SubscriptionCloseKindNormal, subId).Return()
+ mockUpdater.On("CloseSubscription", subId).Return()
updater := NewSubscriptionEventUpdater(
config,
@@ -304,7 +304,7 @@ func TestSubscriptionEventUpdater_Update_WithMultipleHooks_Error(t *testing.T) {
// Verify events from hook1 were still sent
mockUpdater.AssertCalled(t, "UpdateSubscription", subId, []byte("original data"))
// Verify subscription was closed due to hook1's error
- mockUpdater.AssertCalled(t, "CloseSubscription", resolve.SubscriptionCloseKindNormal, subId)
+ mockUpdater.AssertCalled(t, "CloseSubscription", subId)
// Verify Update was not called (since hooks are present)
mockUpdater.AssertNotCalled(t, "Update")
}
@@ -330,16 +330,15 @@ func TestSubscriptionEventUpdater_Complete(t *testing.T) {
updater.Complete()
}
-func TestSubscriptionEventUpdater_Close(t *testing.T) {
+func TestSubscriptionEventUpdaterDoneForwardsToDone(t *testing.T) {
mockUpdater := NewMockSubscriptionUpdater(t)
config := &testSubscriptionEventConfig{
providerID: "test-provider",
providerType: ProviderTypeNats,
fieldName: "testField",
}
- closeKind := resolve.SubscriptionCloseKindNormal
- mockUpdater.On("Close", closeKind).Return()
+ mockUpdater.On("Done").Return()
updater := NewSubscriptionEventUpdater(
config,
@@ -349,7 +348,7 @@ func TestSubscriptionEventUpdater_Close(t *testing.T) {
testEventBuilder,
)
- updater.Close(closeKind)
+ updater.Done()
}
func TestSubscriptionEventUpdater_SetHooks(t *testing.T) {
@@ -530,7 +529,7 @@ func TestSubscriptionEventUpdater_Update_WithSingleHookError_ClosesSubscription(
// Events are still sent even when hook returns error
mockUpdater.On("UpdateSubscription", subId, []byte("test data")).Return()
// Subscription should be closed due to the error
- mockUpdater.On("CloseSubscription", resolve.SubscriptionCloseKindNormal, subId).Return()
+ mockUpdater.On("CloseSubscription", subId).Return()
updater := NewSubscriptionEventUpdater(config, Hooks{
OnReceiveEvents: OnReceiveEventsHooks{
@@ -543,7 +542,7 @@ func TestSubscriptionEventUpdater_Update_WithSingleHookError_ClosesSubscription(
// Verify events were still sent despite the error
mockUpdater.AssertCalled(t, "UpdateSubscription", subId, []byte("test data"))
// Verify subscription was closed due to the error
- mockUpdater.AssertCalled(t, "CloseSubscription", resolve.SubscriptionCloseKindNormal, subId)
+ mockUpdater.AssertCalled(t, "CloseSubscription", subId)
// Update should NOT be called when hooks are present
mockUpdater.AssertNotCalled(t, "Update")
}
@@ -695,40 +694,6 @@ func TestSubscriptionEventUpdater_UpdateEvents_EmptyEvents(t *testing.T) {
mockUpdater.AssertNotCalled(t, "Update")
}
-func TestSubscriptionEventUpdater_Close_WithDifferentCloseKinds(t *testing.T) {
- testCases := []struct {
- name string
- closeKind resolve.SubscriptionCloseKind
- }{
- {"Normal", resolve.SubscriptionCloseKindNormal},
- {"DownstreamServiceError", resolve.SubscriptionCloseKindDownstreamServiceError},
- {"GoingAway", resolve.SubscriptionCloseKindGoingAway},
- }
-
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- mockUpdater := NewMockSubscriptionUpdater(t)
- config := &testSubscriptionEventConfig{
- providerID: "test-provider",
- providerType: ProviderTypeNats,
- fieldName: "testField",
- }
-
- mockUpdater.On("Close", tc.closeKind).Return()
-
- updater := NewSubscriptionEventUpdater(
- config,
- Hooks{},
- mockUpdater,
- zap.NewNop(),
- testEventBuilder,
- )
-
- updater.Close(tc.closeKind)
- })
- }
-}
-
func TestSubscriptionEventUpdater_UpdateSubscription_WithHookError_ClosesSubscription(t *testing.T) {
testCases := []struct {
name string
@@ -777,11 +742,11 @@ func TestSubscriptionEventUpdater_UpdateSubscription_WithHookError_ClosesSubscri
mockUpdater.On("Subscriptions").Return(map[context.Context]resolve.SubscriptionIdentifier{
context.Background(): subId,
})
- mockUpdater.On("CloseSubscription", resolve.SubscriptionCloseKindNormal, subId).Return()
+ mockUpdater.On("CloseSubscription", subId).Return()
updater.Update(events)
- mockUpdater.AssertCalled(t, "CloseSubscription", resolve.SubscriptionCloseKindNormal, subId)
+ mockUpdater.AssertCalled(t, "CloseSubscription", subId)
})
}
}
@@ -831,7 +796,7 @@ func TestSubscriptionEventUpdater_OnReceiveEvents_PanicRecovery(t *testing.T) {
mockUpdater.On("Subscriptions").Return(map[context.Context]resolve.SubscriptionIdentifier{
context.Background(): subId,
})
- mockUpdater.On("CloseSubscription", resolve.SubscriptionCloseKindDownstreamServiceError, subId).Return()
+ mockUpdater.On("CloseSubscription", subId).Return()
updater := NewSubscriptionEventUpdater(
config,
@@ -854,7 +819,7 @@ func TestSubscriptionEventUpdater_OnReceiveEvents_PanicRecovery(t *testing.T) {
}, 10*time.Millisecond, time.Millisecond, "expected panic recovery log")
// Assert that subscription was closed due to panic
- mockUpdater.AssertCalled(t, "CloseSubscription", resolve.SubscriptionCloseKindDownstreamServiceError, subId)
+ mockUpdater.AssertCalled(t, "CloseSubscription", subId)
mockUpdater.AssertNotCalled(t, "UpdateSubscription")
// Assert that panic was logged with correct details
diff --git a/speedtrap/Makefile b/speedtrap/Makefile
new file mode 100644
index 0000000000..28d51e8b03
--- /dev/null
+++ b/speedtrap/Makefile
@@ -0,0 +1,6 @@
+cli = pnpm dlx tsx ../cli/src/index.ts router
+
+.PHONY: config-router
+
+config-router:
+ $(cli) compose -i scenarios/graphql/configs/cosmo/graph.yaml -o scenarios/graphql/configs/cosmo/config.json
diff --git a/speedtrap/README.md b/speedtrap/README.md
new file mode 100644
index 0000000000..eb0a9bebac
--- /dev/null
+++ b/speedtrap/README.md
@@ -0,0 +1,129 @@
+# speedtrap
+
+Black-box scenario harness for WebSocket services. Ships with scenarios for GraphQL subscriptions (`graphql-transport-ws` and `graphql-ws`) so the same suite can be pointed at any gateway (Cosmo router, Apollo, Hive, or a new implementation) and asserted against at the wire level.
+
+Benchmarking is planned on the same harness, so the suite doubles as a correctness check and a performance comparison across implementations.
+
+## Mental Model
+
+A scenario controls **both sides** of the target under test:
+
+- **Client side**: a WebSocket client that speedtrap dials against `TargetAddr`.
+- **Backend side**: one or more mock subgraph backends that the target connects to, registered in `HarnessConfig.Backends`.
+
+The target sits in the middle. Usually that's a GraphQL router proxying subscriptions to subgraphs, but it can also be a plain WebSocket server with no backends at all.
+
+```
+ speedtrap client --> [ target under test ] --> speedtrap backends
+ (c) (router, gateway, (b)
+ or direct WS server)
+```
+
+`Run` is written as a sequence of reads and writes on both sides, asserting that the target forwarded, transformed, or rejected messages correctly.
+
+## Concepts
+
+| Type | Role |
+|-|-|
+| `Scenario` | A named test: `{Name, Run func(*S)}`. |
+| `S` | Per-scenario context. Satisfies the failure-reporting interface of `testing.T`, so testify works on it directly. Creates client connections via `s.Client(...)` and fetches mock backends via `s.Backend(name)`. |
+| `ConnectionHandle` | A WebSocket connection with `Read`, `Send`, `ReadControl`, `SendClose`, `Drop`. Returned by both `s.Client()` (client side) and `backend.Accept()` (backend side). |
+| `HarnessConfig` | Wires a scenario to a target: `TargetAddr` plus a map of mock `Backends`. |
+
+## Writing a Scenario
+
+```go
+var Handshake = speedtrap.Scenario{
+ Name: "connection_init / connection_ack",
+ Run: func(s *speedtrap.S) {
+ c, err := s.Client(speedtrap.WithClientSubprotocol("graphql-transport-ws"))
+ require.NoError(s, err)
+
+ require.NoError(s, c.Send(`{"type":"connection_init"}`))
+
+ msg, err := c.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_ack","payload":null}`, msg)
+ },
+}
+```
+
+## Running in Go Tests
+
+`RequireScenario` runs a scenario and fails the test if it doesn't pass. `AssertScenario` reports failures without stopping the test.
+
+```go
+func TestScenarios(t *testing.T) {
+ cfg := speedtrap.HarnessConfig{
+ TargetAddr: "ws://localhost:8080/graphql",
+ Backends: map[string]*speedtrap.Backend{"subgraph-a": backendA},
+ }
+ for _, sc := range myScenarios {
+ t.Run(sc.Name, func(t *testing.T) {
+ speedtrap.RequireScenario(t, cfg, sc)
+ })
+ }
+}
+```
+
+## Targets With Backends (Router or Gateway)
+
+When the target is a router, it opens its own connections to the subgraphs you register in `HarnessConfig.Backends`. The scenario drives the client, accepts each mock backend's side of the conversation, and asserts that the target routed messages correctly.
+
+```go
+var EchoRoundTrip = speedtrap.Scenario{
+ Name: "echo round-trip",
+ Run: func(s *speedtrap.S) {
+ c, err := s.Client(speedtrap.WithClientSubprotocol("graphql-transport-ws"))
+ require.NoError(s, err)
+
+ b, err := s.Backend("subgraph-a").Accept()
+ require.NoError(s, err)
+
+ require.NoError(s, c.Send(`{"type":"ping"}`))
+
+ msg, err := b.Read()
+ require.NoError(s, err)
+ require.Equal(s, `{"type":"ping"}`, msg)
+ },
+}
+```
+
+`s.Backend(name)` panics if `name` wasn't registered in `HarnessConfig.Backends`. The set of backend names a scenario uses is part of its contract with whoever runs it.
+
+## Targets Without Backends (Direct WebSocket)
+
+If the target is a WebSocket server you want to test end-to-end (no proxying), omit `Backends` and drive only the client.
+
+```go
+var DirectHandshake = speedtrap.Scenario{
+ Name: "direct handshake",
+ Run: func(s *speedtrap.S) {
+ c, err := s.Client(speedtrap.WithClientSubprotocol("graphql-transport-ws"))
+ require.NoError(s, err)
+
+ require.NoError(s, c.Send(`{"type":"connection_init"}`))
+
+ msg, err := c.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_ack","payload":null}`, msg)
+ },
+}
+```
+
+## Shipped Scenarios
+
+`scenarios/graphql/` contains reusable scenario suites for `graphql-transport-ws` and `graphql-ws`, plus the subgraph schemas they expect:
+
+- `scenarios/graphql/subgraph-a.graphqls`: the default subgraph. Every shipped scenario uses it.
+- `scenarios/graphql/subgraph-b.graphqls`: a second subgraph, present in the composed graph to support future multi-subgraph scenarios. Not currently exercised by any shipped scenario.
+
+To run the shipped suites, the consuming test harness must register a backend named `subgraph-a` in `HarnessConfig.Backends`.
+
+## testing.T Compatibility
+
+`S` implements the failure-reporting surface of `testing.T` (`Fail`, `FailNow`, `Error`, `Errorf`, `Fatal`, `Fatalf`, `Log`, `Logf`). Libraries that accept `testing.T`, including testify and jsonassert, work against `s` with no adapter.
+
+## Running
+
+During Cosmo development, the scenarios can be run against the Cosmo router via `router-tests/subscriptions/speedtrap_test.go` (`TestSpeedtrapScenarios`). That test stands up the router with a real subgraph HTTP server backed by a speedtrap mock, then runs each scenario. It is part of the integration test suite and thus runs in CI alongside the rest of those tests.
diff --git a/speedtrap/assert.go b/speedtrap/assert.go
new file mode 100644
index 0000000000..13a248b720
--- /dev/null
+++ b/speedtrap/assert.go
@@ -0,0 +1,32 @@
+package speedtrap
+
+import "testing"
+
+// reportFailures logs each failure as a t.Errorf call.
+func reportFailures(t *testing.T, failures []Failure) {
+ t.Helper()
+ for _, f := range failures {
+ t.Errorf("%s", f.Message)
+ }
+}
+
+// AssertScenario runs a scenario and reports failures with t.Error (non-fatal).
+// Returns the ScenarioResult for further inspection.
+func AssertScenario(t *testing.T, cfg HarnessConfig, s Scenario) ScenarioResult {
+ t.Helper()
+ result := RunScenario(cfg, s)
+ if !result.Passed {
+ reportFailures(t, result.Failures)
+ }
+ return result
+}
+
+// RequireScenario runs a scenario and stops the test with t.FailNow if it fails.
+func RequireScenario(t *testing.T, cfg HarnessConfig, s Scenario) {
+ t.Helper()
+ result := RunScenario(cfg, s)
+ if !result.Passed {
+ reportFailures(t, result.Failures)
+ t.FailNow()
+ }
+}
diff --git a/speedtrap/backend.go b/speedtrap/backend.go
new file mode 100644
index 0000000000..d3a1160e0b
--- /dev/null
+++ b/speedtrap/backend.go
@@ -0,0 +1,180 @@
+package speedtrap
+
+import (
+ "fmt"
+ "net"
+ "net/http"
+ "slices"
+ "sync"
+ "time"
+
+ "github.com/gobwas/ws"
+)
+
+const (
+ defaultBackendAddr = ":0"
+ defaultBackendTimeout = 5 * time.Second
+)
+
+// Backend accepts WebSocket connections from the proxy, auto-upgrades them,
+// captures request headers, and makes the resulting connections available via Accept.
+type Backend struct {
+ server *http.Server
+ listener net.Listener
+ pending chan *ConnectionHandle
+ subprotocols []string
+ addr string
+ timeout time.Duration
+ done chan struct{}
+ stopOnce sync.Once
+}
+
+// BackendOption configures a Backend.
+type BackendOption func(*Backend)
+
+// WithAddr sets the listen address for standalone mode. Default is ":0".
+func WithAddr(addr string) BackendOption {
+ return func(b *Backend) {
+ b.addr = addr
+ }
+}
+
+// WithSubprotocol sets the subprotocols the backend accepts during upgrade.
+// If any are configured and the client offers a subprotocol that doesn't match,
+// the upgrade is rejected. Clients that offer no subprotocol are accepted.
+func WithSubprotocol(protos ...string) BackendOption {
+ return func(b *Backend) {
+ b.subprotocols = protos
+ }
+}
+
+// WithTimeout sets the timeout for Accept calls. Default is 5 seconds.
+func WithTimeout(timeout time.Duration) BackendOption {
+ return func(b *Backend) {
+ b.timeout = timeout
+ }
+}
+
+func applyOpts(b *Backend, opts []BackendOption) {
+ for _, o := range opts {
+ o(b)
+ }
+}
+
+// StartBackend creates a standalone backend that listens on a TCP address
+// and serves an HTTP handler that upgrades WebSocket connections.
+func StartBackend(opts ...BackendOption) (*Backend, error) {
+ b := &Backend{
+ pending: make(chan *ConnectionHandle, 16),
+
+ addr: defaultBackendAddr,
+ timeout: defaultBackendTimeout,
+ done: make(chan struct{}),
+ }
+ applyOpts(b, opts)
+
+ ln, err := net.Listen("tcp", b.addr)
+ if err != nil {
+ return nil, fmt.Errorf("listen: %w", err)
+ }
+ b.listener = ln
+ b.addr = ln.Addr().String()
+
+ b.server = &http.Server{Handler: b.Handler()}
+ go b.server.Serve(ln)
+
+ return b, nil
+}
+
+// NewBackend creates a backend without a listener, for use in middleware mode.
+// Call Handler() to get the http.Handler for mounting in a server.
+func NewBackend(opts ...BackendOption) *Backend {
+ b := &Backend{
+ pending: make(chan *ConnectionHandle, 16),
+
+ timeout: defaultBackendTimeout,
+ done: make(chan struct{}),
+ }
+ applyOpts(b, opts)
+ return b
+}
+
+// Handler returns an http.Handler that upgrades incoming WebSocket connections
+// using ws.HTTPUpgrader, captures request headers, and pushes the resulting
+// ConnectionHandle to the pending channel. Both standalone and middleware modes
+// use this same handler.
+func (b *Backend) Handler() http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ var upgrader ws.HTTPUpgrader
+ if len(b.subprotocols) > 0 {
+ upgrader.Protocol = func(proto string) bool {
+ return slices.Contains(b.subprotocols, proto)
+ }
+ }
+
+ conn, _, hs, err := upgrader.Upgrade(r, w)
+ if err != nil {
+ return
+ }
+
+ headers := r.Header.Clone()
+ handle := newConnectionHandle(conn, ws.StateServerSide, hs, headers, b.timeout)
+ b.pending <- handle
+ })
+}
+
+func (b *Backend) drain() {
+ for {
+ select {
+ case h := <-b.pending:
+ h.Drop()
+ default:
+ return
+ }
+ }
+}
+
+// Accept waits for the next upgraded connection from the proxy.
+func (b *Backend) Accept() (*ConnectionHandle, error) {
+ select {
+ case h := <-b.pending:
+ return h, nil
+ case <-b.done:
+ return nil, fmt.Errorf("backend stopped")
+ case <-time.After(b.timeout):
+ return nil, fmt.Errorf("accept timed out after %s", b.timeout)
+ }
+}
+
+// TryAccept waits briefly (500ms) for a new connection. It is useful when the
+// proxy may or may not open a new upstream connection (e.g. it might multiplex
+// onto an existing one instead).
+func (b *Backend) TryAccept() (*ConnectionHandle, error) {
+ select {
+ case h := <-b.pending:
+ return h, nil
+ case <-b.done:
+ return nil, fmt.Errorf("backend stopped")
+ case <-time.After(500 * time.Millisecond):
+ return nil, fmt.Errorf("no new connection within 500ms")
+ }
+}
+
+// Addr returns the listen address (standalone mode only).
+func (b *Backend) Addr() string {
+ return b.addr
+}
+
+// Stop shuts down the backend, closing the listener and draining pending connections.
+// Safe to call multiple times.
+func (b *Backend) Stop() {
+ b.stopOnce.Do(func() {
+ close(b.done)
+ if b.server != nil {
+ b.server.Close()
+ } else if b.listener != nil {
+ b.listener.Close()
+ }
+ b.drain()
+ })
+}
diff --git a/speedtrap/backend_test.go b/speedtrap/backend_test.go
new file mode 100644
index 0000000000..173b2cd66f
--- /dev/null
+++ b/speedtrap/backend_test.go
@@ -0,0 +1,122 @@
+package speedtrap
+
+import (
+ "context"
+ "net/http"
+ "net/http/httptest"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/gobwas/ws"
+ "github.com/stretchr/testify/require"
+)
+
+func TestBackend(t *testing.T) {
+ t.Run("standalone accepts and upgrades connection", func(t *testing.T) {
+ b, err := StartBackend()
+ require.NoError(t, err)
+ t.Cleanup(b.Stop)
+
+ dialer := ws.Dialer{
+ Header: ws.HandshakeHeaderHTTP(http.Header{
+ "X-Test": {"hello"},
+ }),
+ }
+ conn, _, _, err := dialer.Dial(context.Background(), "ws://"+b.Addr())
+ require.NoError(t, err)
+ defer conn.Close()
+
+ handle, err := b.Accept()
+ require.NoError(t, err)
+
+ require.NotNil(t, handle.UpgradeHeaders)
+ require.Equal(t, "hello", handle.UpgradeHeaders.Get("X-Test"))
+
+ err = handle.Send("hello")
+ require.NoError(t, err)
+ })
+
+ t.Run("standalone captures upgrade headers", func(t *testing.T) {
+ b, err := StartBackend()
+ require.NoError(t, err)
+ t.Cleanup(b.Stop)
+
+ dialer := ws.Dialer{
+ Header: ws.HandshakeHeaderHTTP(map[string][]string{"X-Test": {"hello"}}),
+ }
+ conn, _, _, err := dialer.Dial(context.Background(), "ws://"+b.Addr())
+ require.NoError(t, err)
+ defer conn.Close()
+
+ handle, err := b.Accept()
+ require.NoError(t, err)
+
+ got := handle.UpgradeHeaders.Get("X-Test")
+ require.Equal(t, "hello", got)
+ })
+
+ t.Run("handler mode accepts and upgrades connection", func(t *testing.T) {
+ b := NewBackend()
+
+ srv := httptest.NewServer(b.Handler())
+ defer srv.Close()
+
+ addr := strings.TrimPrefix(srv.URL, "http://")
+ dialer := ws.Dialer{}
+ conn, _, _, err := dialer.Dial(context.Background(), "ws://"+addr)
+ require.NoError(t, err)
+ defer conn.Close()
+
+ handle, err := b.Accept()
+ require.NoError(t, err)
+
+ require.NotNil(t, handle.UpgradeHeaders)
+
+ err = handle.Send("hello")
+ require.NoError(t, err)
+ })
+
+ t.Run("accept returns error on timeout", func(t *testing.T) {
+ b, err := StartBackend(WithTimeout(50 * time.Millisecond))
+ require.NoError(t, err)
+ t.Cleanup(b.Stop)
+
+ // No connections made — Accept should time out
+ _, err = b.Accept()
+ require.Error(t, err)
+ })
+
+ t.Run("accept returns error after stop", func(t *testing.T) {
+ b, err := StartBackend()
+ require.NoError(t, err)
+
+ b.Stop()
+
+ _, err = b.Accept()
+ require.Error(t, err)
+ })
+
+ t.Run("options apply addr, subprotocol, and timeout", func(t *testing.T) {
+ b, err := StartBackend(
+ WithAddr("127.0.0.1:0"),
+ WithSubprotocol("graphql-ws"),
+ WithTimeout(1*time.Second),
+ )
+ require.NoError(t, err)
+ t.Cleanup(b.Stop)
+
+ require.Equal(t, []string{"graphql-ws"}, b.subprotocols)
+ require.Equal(t, 1*time.Second, b.timeout)
+
+ dialer := ws.Dialer{
+ Protocols: []string{"graphql-ws"},
+ }
+ conn, _, _, err := dialer.Dial(context.Background(), "ws://"+b.Addr())
+ require.NoError(t, err)
+ defer conn.Close()
+
+ _, err = b.Accept()
+ require.NoError(t, err)
+ })
+}
diff --git a/speedtrap/go.mod b/speedtrap/go.mod
new file mode 100644
index 0000000000..ee8bdee8ac
--- /dev/null
+++ b/speedtrap/go.mod
@@ -0,0 +1,24 @@
+module github.com/wundergraph/cosmo/speedtrap
+
+go 1.25
+
+require (
+ github.com/gobwas/ws v1.4.0
+ github.com/kinbiko/jsonassert v1.2.0
+ github.com/stretchr/testify v1.11.1
+ github.com/tidwall/gjson v1.18.0
+)
+
+require (
+ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
+ github.com/gobwas/httphead v0.1.0 // indirect
+ github.com/gobwas/pool v0.2.1 // indirect
+ github.com/kr/pretty v0.3.1 // indirect
+ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
+ github.com/rogpeppe/go-internal v1.13.1 // indirect
+ github.com/tidwall/match v1.1.1 // indirect
+ github.com/tidwall/pretty v1.2.0 // indirect
+ golang.org/x/sys v0.37.0 // indirect
+ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
+)
diff --git a/speedtrap/go.sum b/speedtrap/go.sum
new file mode 100644
index 0000000000..0f3a440b5b
--- /dev/null
+++ b/speedtrap/go.sum
@@ -0,0 +1,40 @@
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
+github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
+github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
+github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
+github.com/gobwas/ws v1.4.0 h1:CTaoG1tojrh4ucGPcoJFiAQUAsEWekEWvLy7GsVNqGs=
+github.com/gobwas/ws v1.4.0/go.mod h1:G3gNqMNtPppf5XUz7O4shetPpcZ1VJ7zt18dlUeakrc=
+github.com/kinbiko/jsonassert v1.2.0 h1:+/JthIVXdIrThrOtSN9ry0mNtWKXMWuvxR0nU7gQ+tI=
+github.com/kinbiko/jsonassert v1.2.0/go.mod h1:pCc3uudOt+lVAbkji9O0uw8MSVt4s+1ZJ0y8Ux2F1Og=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
+github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
+github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
+github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
+github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
+github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
+github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
+github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
+github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
+github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
+golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/speedtrap/handle.go b/speedtrap/handle.go
new file mode 100644
index 0000000000..6021274db8
--- /dev/null
+++ b/speedtrap/handle.go
@@ -0,0 +1,141 @@
+package speedtrap
+
+import (
+ "fmt"
+ "io"
+ "net"
+ "net/http"
+ "time"
+
+ "github.com/gobwas/ws"
+ "github.com/gobwas/ws/wsutil"
+)
+
+// ControlFrame holds a WebSocket control frame (close, ping, or pong).
+type ControlFrame struct {
+ OpCode ws.OpCode
+ Payload []byte
+}
+
+// CloseData parses a close frame's status code and reason.
+// Returns an empty status code and empty reason if the payload is too short.
+func (cf ControlFrame) CloseData() (ws.StatusCode, string) {
+ return ws.ParseCloseFrameData(cf.Payload)
+}
+
+// ConnectionHandle wraps a WebSocket connection with buffered read channels.
+// It is used for both client-side and backend-side connections. The state field
+// determines masking behavior per RFC 6455.
+type ConnectionHandle struct {
+ conn net.Conn
+ state ws.State
+ inbox chan string
+ control chan ControlFrame
+ done chan struct{}
+ timeout time.Duration
+
+ // Handshake holds the result of the WebSocket handshake (client side only).
+ Handshake ws.Handshake
+
+ // UpgradeHeaders holds the HTTP headers from the upgrade request (backend side only).
+ UpgradeHeaders http.Header
+}
+
+func newConnectionHandle(conn net.Conn, state ws.State, hs ws.Handshake, headers http.Header, timeout time.Duration) *ConnectionHandle {
+ h := &ConnectionHandle{
+ conn: conn,
+ state: state,
+ inbox: make(chan string, 64),
+ control: make(chan ControlFrame, 16),
+ done: make(chan struct{}),
+ timeout: timeout,
+ Handshake: hs,
+ UpgradeHeaders: headers,
+ }
+ go h.readLoop()
+ return h
+}
+
+func (h *ConnectionHandle) readLoop() {
+ reader := wsutil.NewReader(h.conn, h.state)
+ for {
+ hdr, err := reader.NextFrame()
+ if err != nil {
+ close(h.done)
+ return
+ }
+
+ payload, err := io.ReadAll(reader)
+ if err != nil {
+ close(h.done)
+ return
+ }
+
+ switch hdr.OpCode {
+ case ws.OpText, ws.OpBinary:
+ h.inbox <- string(payload)
+ case ws.OpClose, ws.OpPing, ws.OpPong:
+ h.control <- ControlFrame{OpCode: hdr.OpCode, Payload: payload}
+ }
+ }
+}
+
+// Read blocks until a text or binary frame arrives or the timeout expires.
+func (h *ConnectionHandle) Read() (string, error) {
+ select {
+ case msg := <-h.inbox:
+ return msg, nil
+ case <-h.done:
+ // Connection closed, but there may be buffered data frames
+ // that arrived before the read loop exited.
+ select {
+ case msg := <-h.inbox:
+ return msg, nil
+ default:
+ return "", fmt.Errorf("connection closed")
+ }
+ case <-time.After(h.timeout):
+ return "", fmt.Errorf("read timed out after %s", h.timeout)
+ }
+}
+
+// ReadControl blocks until a control frame (close/ping/pong) arrives or the timeout expires.
+func (h *ConnectionHandle) ReadControl() (ControlFrame, error) {
+ select {
+ case cf := <-h.control:
+ return cf, nil
+ case <-h.done:
+ // Connection closed, but there may be buffered control frames
+ // (e.g. close frame) that arrived before the read loop exited.
+ select {
+ case cf := <-h.control:
+ return cf, nil
+ default:
+ return ControlFrame{}, fmt.Errorf("connection closed")
+ }
+ case <-time.After(h.timeout):
+ return ControlFrame{}, fmt.Errorf("read control timed out after %s", h.timeout)
+ }
+}
+
+// Send writes a text frame. Masking is applied automatically based on side.
+func (h *ConnectionHandle) Send(raw string) error {
+ if h.state == ws.StateClientSide {
+ return wsutil.WriteClientMessage(h.conn, ws.OpText, []byte(raw))
+ }
+ return wsutil.WriteServerMessage(h.conn, ws.OpText, []byte(raw))
+}
+
+// SendClose sends a close frame with the given status code and reason.
+func (h *ConnectionHandle) SendClose(code int, reason string) error {
+ frame := ws.NewCloseFrame(ws.NewCloseFrameBody(ws.StatusCode(code), reason))
+ if h.state == ws.StateClientSide {
+ frame = ws.MaskFrameInPlace(frame)
+ }
+ return ws.WriteFrame(h.conn, frame)
+}
+
+// Drop forcibly closes the underlying TCP connection without a close frame.
+func (h *ConnectionHandle) Drop() error {
+ return h.conn.Close()
+}
diff --git a/speedtrap/handle_test.go b/speedtrap/handle_test.go
new file mode 100644
index 0000000000..6f850c6907
--- /dev/null
+++ b/speedtrap/handle_test.go
@@ -0,0 +1,264 @@
+package speedtrap
+
+import (
+ "context"
+ "fmt"
+ "net"
+ "net/http"
+ "testing"
+ "time"
+
+ "github.com/gobwas/ws"
+ "github.com/stretchr/testify/require"
+)
+
+const testTimeout = 2 * time.Second
+
+// connectedPair creates a WebSocket-upgraded pair of ConnectionHandles
+// using a local TCP listener and gobwas/ws Dialer+Upgrader.
+func connectedPair(t *testing.T) (client, server *ConnectionHandle) {
+ t.Helper()
+
+ ln, err := net.Listen("tcp", "127.0.0.1:0")
+ require.NoError(t, err)
+ t.Cleanup(func() { ln.Close() })
+
+ type result struct {
+ handle *ConnectionHandle
+ err error
+ }
+
+ serverCh := make(chan result, 1)
+ go func() {
+ conn, err := ln.Accept()
+ if err != nil {
+ serverCh <- result{err: err}
+ return
+ }
+
+ headers := make(http.Header)
+ u := ws.Upgrader{
+ OnHeader: func(key, value []byte) error {
+ headers.Add(string(key), string(value))
+ return nil
+ },
+ }
+
+ hs, err := u.Upgrade(conn)
+ if err != nil {
+ conn.Close()
+ serverCh <- result{err: err}
+ return
+ }
+
+ h := newConnectionHandle(conn, ws.StateServerSide, hs, headers, testTimeout)
+ serverCh <- result{handle: h}
+ }()
+
+ dialer := ws.Dialer{}
+ conn, _, hs, err := dialer.Dial(context.Background(), "ws://"+ln.Addr().String())
+ require.NoError(t, err)
+
+ clientHandle := newConnectionHandle(conn, ws.StateClientSide, hs, nil, testTimeout)
+
+ res := <-serverCh
+ require.NoError(t, res.err)
+
+ t.Cleanup(func() {
+ clientHandle.Drop()
+ res.handle.Drop()
+ })
+
+ return clientHandle, res.handle
+}
+
+func TestConnectionHandle(t *testing.T) {
+ t.Run("handshake captures negotiated protocol for client", func(t *testing.T) {
+ b, err := StartBackend(WithSubprotocol("test"))
+ require.NoError(t, err)
+ t.Cleanup(b.Stop)
+
+ dialer := ws.Dialer{
+ Protocols: []string{"test"},
+ }
+ conn, _, hs, err := dialer.Dial(context.Background(), "ws://"+b.Addr())
+ require.NoError(t, err)
+
+ client := newConnectionHandle(conn, ws.StateClientSide, hs, nil, testTimeout)
+ t.Cleanup(func() { client.Drop() })
+
+ require.Equal(t, "test", client.Handshake.Protocol)
+ })
+
+ t.Run("upgrade headers are captured for backend", func(t *testing.T) {
+ b, err := StartBackend()
+ require.NoError(t, err)
+ t.Cleanup(b.Stop)
+
+ dialer := ws.Dialer{
+ Header: ws.HandshakeHeaderHTTP(map[string][]string{"X-Custom": {"test-value"}}),
+ }
+ conn, _, _, err := dialer.Dial(context.Background(), "ws://"+b.Addr())
+ require.NoError(t, err)
+ defer conn.Close()
+
+ handle, err := b.Accept()
+ require.NoError(t, err)
+
+ require.Equal(t, "test-value", handle.UpgradeHeaders.Get("X-Custom"))
+ })
+
+ t.Run("send delivers message to other side", func(t *testing.T) {
+ client, server := connectedPair(t)
+
+ err := client.Send(`{"type":"hello"}`)
+ require.NoError(t, err)
+
+ msg, err := server.Read()
+ require.NoError(t, err)
+ require.Equal(t, `{"type":"hello"}`, msg)
+
+ err = server.Send(`{"type":"world"}`)
+ require.NoError(t, err)
+
+ msg, err = client.Read()
+ require.NoError(t, err)
+ require.Equal(t, `{"type":"world"}`, msg)
+ })
+
+ t.Run("send close delivers code and reason to other side", func(t *testing.T) {
+ client, server := connectedPair(t)
+
+ err := server.SendClose(4400, "rate limited")
+ require.NoError(t, err)
+
+ cf, err := client.ReadControl()
+ require.NoError(t, err)
+
+ require.Equal(t, ws.OpClose, cf.OpCode)
+
+ code, reason := cf.CloseData()
+ require.Equal(t, ws.StatusCode(4400), code)
+ require.Equal(t, "rate limited", reason)
+ })
+
+ t.Run("drop closes connection and terminates read loop", func(t *testing.T) {
+ client, server := connectedPair(t)
+
+ err := client.Drop()
+ require.NoError(t, err)
+
+ select {
+ case <-server.done:
+ // expected
+ case <-time.After(testTimeout):
+ t.Fatal("readLoop did not terminate after Drop")
+ }
+ })
+
+ t.Run("read returns buffered messages when multiple sent before reading", func(t *testing.T) {
+ client, server := connectedPair(t)
+
+ for i := range 5 {
+ msg := fmt.Sprintf(`{"n":%d}`, i)
+ err := client.Send(msg)
+ require.NoError(t, err)
+ }
+
+ time.Sleep(50 * time.Millisecond)
+
+ for range 5 {
+ _, err := server.Read()
+ require.NoError(t, err)
+ }
+ })
+
+ t.Run("read returns error after connection dropped", func(t *testing.T) {
+ client, server := connectedPair(t)
+
+ err := server.Drop()
+ require.NoError(t, err)
+
+ // Wait for readLoop to detect the close
+ <-client.done
+
+ _, err = client.Read()
+ require.Error(t, err)
+ })
+
+ t.Run("read returns error on timeout", func(t *testing.T) {
+ shortTimeout := 50 * time.Millisecond
+
+ ln, err := net.Listen("tcp", "127.0.0.1:0")
+ require.NoError(t, err)
+ t.Cleanup(func() { ln.Close() })
+
+ serverCh := make(chan *ConnectionHandle, 1)
+ go func() {
+ conn, err := ln.Accept()
+ if err != nil {
+ return
+ }
+ u := ws.Upgrader{}
+ hs, err := u.Upgrade(conn)
+ if err != nil {
+ conn.Close()
+ return
+ }
+ serverCh <- newConnectionHandle(conn, ws.StateServerSide, hs, nil, shortTimeout)
+ }()
+
+ dialer := ws.Dialer{}
+ conn, _, hs, err := dialer.Dial(context.Background(), "ws://"+ln.Addr().String())
+ require.NoError(t, err)
+ t.Cleanup(func() { conn.Close() })
+
+ client := newConnectionHandle(conn, ws.StateClientSide, hs, nil, shortTimeout)
+ t.Cleanup(func() { client.Drop() })
+
+ server := <-serverCh
+ t.Cleanup(func() { server.Drop() })
+
+ // No messages sent — Read should time out
+ _, err = client.Read()
+ require.Error(t, err)
+ })
+
+ t.Run("read control returns error on timeout", func(t *testing.T) {
+ shortTimeout := 50 * time.Millisecond
+
+ ln, err := net.Listen("tcp", "127.0.0.1:0")
+ require.NoError(t, err)
+ t.Cleanup(func() { ln.Close() })
+
+ serverCh := make(chan *ConnectionHandle, 1)
+ go func() {
+ conn, err := ln.Accept()
+ if err != nil {
+ return
+ }
+ u := ws.Upgrader{}
+ hs, err := u.Upgrade(conn)
+ if err != nil {
+ conn.Close()
+ return
+ }
+ serverCh <- newConnectionHandle(conn, ws.StateServerSide, hs, nil, shortTimeout)
+ }()
+
+ dialer := ws.Dialer{}
+ conn, _, hs, err := dialer.Dial(context.Background(), "ws://"+ln.Addr().String())
+ require.NoError(t, err)
+ t.Cleanup(func() { conn.Close() })
+
+ client := newConnectionHandle(conn, ws.StateClientSide, hs, nil, shortTimeout)
+ t.Cleanup(func() { client.Drop() })
+
+ server := <-serverCh
+ t.Cleanup(func() { server.Drop() })
+
+ // No control frames sent — ReadControl should time out
+ _, err = client.ReadControl()
+ require.Error(t, err)
+ })
+}
diff --git a/speedtrap/readswitch.go b/speedtrap/readswitch.go
new file mode 100644
index 0000000000..6005c01f80
--- /dev/null
+++ b/speedtrap/readswitch.go
@@ -0,0 +1,104 @@
+package speedtrap
+
+import (
+ "iter"
+ "maps"
+
+ "github.com/stretchr/testify/require"
+)
+
+// SwitchCase pairs a key with a callback for ReadSwitch.
+type SwitchCase[K comparable, V any] struct {
+ Key K
+ Fn func(V)
+}
+
+// Case creates a SwitchCase for use with ReadSwitch.
+func Case[K comparable, V any](key K, fn func(V)) SwitchCase[K, V] {
+ return SwitchCase[K, V]{Key: key, Fn: fn}
+}
+
+// ReadSwitch reads exactly len(cases) values from the iterator, dispatching
+// each to the case whose key matches. Every value must match a case and every
+// case must be matched exactly once.
+//
+// Failures:
+// - Unexpected value: key doesn't match any remaining case
+// - Timeout/close: iterator yields an error before all cases are matched
+func ReadSwitch[K comparable, V any](s *S, items iter.Seq2[V, error], key func(V) K, cases ...SwitchCase[K, V]) {
+ remaining := make(map[K]func(V), len(cases))
+ for _, c := range cases {
+ remaining[c.Key] = c.Fn
+ }
+
+ for item, err := range items {
+ if err != nil {
+ require.NoError(s, err, "ReadSwitch: waiting for keys %v", maps.Keys(remaining))
+ }
+
+ k := key(item)
+ fn, ok := remaining[k]
+ require.True(s, ok, "ReadSwitch: unexpected key %v in value: %v", k, item)
+
+ fn(item)
+ delete(remaining, k)
+
+ if len(remaining) == 0 {
+ return
+ }
+ }
+}
+
+// Filter wraps an iterator, dropping values that match skip.
+func Filter[V any](items iter.Seq2[V, error], skip func(V) bool) iter.Seq2[V, error] {
+ return func(yield func(V, error) bool) {
+ for item, err := range items {
+ if err != nil {
+ yield(item, err)
+ return
+ }
+ if skip(item) {
+ continue
+ }
+ if !yield(item, err) {
+ return
+ }
+ }
+ }
+}
+
+// Tagged pairs a message with the connection it was read from.
+type Tagged struct {
+ Conn *ConnectionHandle
+ Msg string
+}
+
+// Messages returns an iterator that reads messages from the connection.
+func (h *ConnectionHandle) Messages() iter.Seq2[string, error] {
+ return func(yield func(string, error) bool) {
+ for {
+ msg, err := h.Read()
+ if !yield(msg, err) {
+ return
+ }
+ if err != nil {
+ return
+ }
+ }
+ }
+}
+
+// MergeMessages reads one message from each connection sequentially, yielding
+// Tagged values that pair the message with its source connection. This is safe
+// when each connection will independently have a message available (no
+// cross-connection dependencies).
+func MergeMessages(conns ...*ConnectionHandle) iter.Seq2[Tagged, error] {
+ return func(yield func(Tagged, error) bool) {
+ for _, c := range conns {
+ msg, err := c.Read()
+ if !yield(Tagged{Conn: c, Msg: msg}, err) {
+ return
+ }
+ }
+ }
+}
diff --git a/speedtrap/result.go b/speedtrap/result.go
new file mode 100644
index 0000000000..17070970ce
--- /dev/null
+++ b/speedtrap/result.go
@@ -0,0 +1,17 @@
+package speedtrap
+
+import "time"
+
+// Failure represents a single test failure within a scenario.
+type Failure struct {
+ Message string `json:"message"`
+ Fatal bool `json:"fatal"`
+}
+
+// ScenarioResult captures the outcome of running a single scenario.
+type ScenarioResult struct {
+ Name string `json:"name"`
+ Passed bool `json:"passed"`
+ Duration time.Duration `json:"duration"`
+ Failures []Failure `json:"failures,omitempty"`
+}
diff --git a/speedtrap/runner.go b/speedtrap/runner.go
new file mode 100644
index 0000000000..3ce862d6f8
--- /dev/null
+++ b/speedtrap/runner.go
@@ -0,0 +1,42 @@
+package speedtrap
+
+import "time"
+
+const defaultTimeout = 5 * time.Second
+
+// RunScenario executes a single scenario against the configured proxy and backends.
+// It returns the result including pass/fail status, duration, and any collected failures.
+func RunScenario(cfg HarnessConfig, s Scenario) ScenarioResult {
+ timeout := cfg.Timeout
+ if timeout == 0 {
+ timeout = defaultTimeout
+ }
+
+ t := &S{
+ targetAddr: cfg.TargetAddr,
+ backends: cfg.Backends,
+ timeout: timeout,
+ }
+
+ start := time.Now()
+
+ done := make(chan struct{})
+ go func() {
+ defer close(done)
+ s.Run(t)
+ }()
+ <-done
+
+ t.cleanup()
+
+ for _, b := range cfg.Backends {
+ b.drain()
+ }
+
+ return ScenarioResult{
+ Name: s.Name,
+ Passed: !t.failed(),
+ Duration: time.Since(start),
+ Failures: t.failures,
+ }
+}
diff --git a/speedtrap/scenario.go b/speedtrap/scenario.go
new file mode 100644
index 0000000000..7908364e26
--- /dev/null
+++ b/speedtrap/scenario.go
@@ -0,0 +1,171 @@
+package speedtrap
+
+import (
+ "context"
+ "fmt"
+ "net/http"
+ "runtime"
+ "sync"
+ "time"
+
+ "github.com/gobwas/ws"
+)
+
+// Scenario is a named test case. The Run callback receives a test context
+// and imperatively scripts the entire WebSocket conversation.
+type Scenario struct {
+ Name string
+ Run func(t *S)
+}
+
+// HarnessConfig configures the test harness for running scenarios.
+type HarnessConfig struct {
+ TargetAddr string
+ Backends map[string]*Backend
+ Timeout time.Duration
+}
+
+// clientConfig holds resolved client connection options.
+type clientConfig struct {
+ subprotocols []string
+ headers http.Header
+}
+
+// ClientOption configures a client connection to the proxy.
+type ClientOption func(*clientConfig)
+
+// WithClientSubprotocol sets the subprotocols the client offers during upgrade.
+func WithClientSubprotocol(protos ...string) ClientOption {
+ return func(c *clientConfig) {
+ c.subprotocols = protos
+ }
+}
+
+// WithClientHeaders sets additional headers sent during the upgrade request.
+func WithClientHeaders(h http.Header) ClientOption {
+ return func(c *clientConfig) {
+ c.headers = h
+ }
+}
+
+// S is the test context passed to scenario callbacks. It provides methods for
+// creating connections, recording failures, and accessing backends.
+//
+// The failure-reporting API mirrors [testing.T]:
+//
+// Fail / FailNow — mark failed (no message)
+// Log / Logf — record a message
+// Error / Errorf — Log + Fail (non-fatal)
+// Fatal / Fatalf — Log + FailNow (fatal, stops execution)
+type S struct {
+ targetAddr string
+ backends map[string]*Backend
+ handles []*ConnectionHandle
+ timeout time.Duration
+
+ mu sync.Mutex
+ hasFailed bool
+ failures []Failure
+}
+
+// Client dials the proxy and returns a client-side connection handle.
+func (t *S) Client(opts ...ClientOption) (*ConnectionHandle, error) {
+ var cfg clientConfig
+ for _, o := range opts {
+ o(&cfg)
+ }
+
+ dialer := ws.Dialer{
+ Timeout: t.timeout,
+ }
+ if len(cfg.subprotocols) > 0 {
+ dialer.Protocols = cfg.subprotocols
+ }
+ if cfg.headers != nil {
+ dialer.Header = ws.HandshakeHeaderHTTP(cfg.headers)
+ }
+
+ conn, _, hs, err := dialer.Dial(context.Background(), t.targetAddr)
+ if err != nil {
+ return nil, fmt.Errorf("dial %s: %w", t.targetAddr, err)
+ }
+
+ h := newConnectionHandle(conn, ws.StateClientSide, hs, nil, t.timeout)
+
+ t.mu.Lock()
+ t.handles = append(t.handles, h)
+ t.mu.Unlock()
+
+ return h, nil
+}
+
+// Backend returns the named mock backend. Panics if the name was not registered.
+func (t *S) Backend(name string) *Backend {
+ b, ok := t.backends[name]
+ if !ok {
+ panic(fmt.Sprintf("speedtrap: unknown backend %q", name))
+ }
+ return b
+}
+
+// log records a failure message.
+func (t *S) log(msg string) {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ t.failures = append(t.failures, Failure{Message: msg})
+}
+
+// Fail marks the scenario as failed but continues execution.
+func (t *S) Fail() {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ t.hasFailed = true
+}
+
+// FailNow marks the scenario as failed and stops execution via runtime.Goexit.
+func (t *S) FailNow() {
+ t.mu.Lock()
+ t.hasFailed = true
+ if n := len(t.failures); n > 0 {
+ t.failures[n-1].Fatal = true
+ } else {
+ t.failures = append(t.failures, Failure{Fatal: true})
+ }
+ t.mu.Unlock()
+ runtime.Goexit()
+}
+
+// Log records a message without marking the scenario as failed.
+func (t *S) Log(args ...any) { t.log(fmt.Sprint(args...)) }
+
+// Logf records a formatted message without marking the scenario as failed.
+func (t *S) Logf(format string, args ...any) { t.log(fmt.Sprintf(format, args...)) }
+
+// Error is equivalent to Log followed by Fail.
+func (t *S) Error(args ...any) { t.Log(args...); t.Fail() }
+
+// Errorf is equivalent to Logf followed by Fail.
+func (t *S) Errorf(format string, args ...any) { t.Logf(format, args...); t.Fail() }
+
+// Fatal is equivalent to Log followed by FailNow.
+func (t *S) Fatal(args ...any) { t.Log(args...); t.FailNow() }
+
+// Fatalf is equivalent to Logf followed by FailNow.
+func (t *S) Fatalf(format string, args ...any) { t.Logf(format, args...); t.FailNow() }
+
+// failed reports whether the scenario has been marked as failed.
+func (t *S) failed() bool {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ return t.hasFailed
+}
+
+func (t *S) cleanup() {
+ t.mu.Lock()
+ handles := t.handles
+ t.mu.Unlock()
+
+ for _, h := range handles {
+ h.Drop()
+ }
+}
diff --git a/speedtrap/scenarios/graphql/configs/cosmo/config.go b/speedtrap/scenarios/graphql/configs/cosmo/config.go
new file mode 100644
index 0000000000..39df719c0a
--- /dev/null
+++ b/speedtrap/scenarios/graphql/configs/cosmo/config.go
@@ -0,0 +1,11 @@
+package cosmo
+
+import _ "embed"
+
+const (
+ SubgraphAPlaceholderURL = "http://localhost:14001/graphql"
+ SubgraphBPlaceholderURL = "http://localhost:14002/graphql"
+)
+
+//go:embed config.json
+var ConfigJSON string
diff --git a/speedtrap/scenarios/graphql/configs/cosmo/config.json b/speedtrap/scenarios/graphql/configs/cosmo/config.json
new file mode 100644
index 0000000000..ad46ee6a40
--- /dev/null
+++ b/speedtrap/scenarios/graphql/configs/cosmo/config.json
@@ -0,0 +1 @@
+{"engineConfig":{"defaultFlushInterval":"500","datasourceConfigurations":[{"kind":"GRAPHQL","rootNodes":[{"typeName":"Query","fieldNames":["_empty"]},{"typeName":"Subscription","fieldNames":["streamA"]}],"childNodes":[{"typeName":"StreamEvent","fieldNames":["key","contents"]}],"overrideFieldPathFromAlias":true,"customGraphql":{"fetch":{"url":{"staticVariableContent":"http://localhost:14001/graphql"},"method":"POST","body":{},"baseUrl":{},"path":{}},"subscription":{"enabled":true,"url":{"staticVariableContent":"http://localhost:14001/graphql"},"protocol":"GRAPHQL_SUBSCRIPTION_PROTOCOL_WS","websocketSubprotocol":"GRAPHQL_WEBSOCKET_SUBPROTOCOL_AUTO"},"federation":{"enabled":true,"serviceSdl":"extend schema\n @link(\n url: \"https://specs.apollo.dev/federation/v2.5\"\n import: [\"@shareable\"]\n )\n\ntype Query {\n _empty: Boolean @shareable\n}\n\nscalar JSON\n\ntype Subscription {\n streamA(key: String): StreamEvent\n}\n\ntype StreamEvent @shareable {\n key: String\n contents: JSON\n}\n"},"upstreamSchema":{"key":"9786cf1d663fd14f29625298f1b112c817720395"}},"requestTimeoutSeconds":"10","id":"0"},{"kind":"GRAPHQL","rootNodes":[{"typeName":"Query","fieldNames":["_empty"]},{"typeName":"Subscription","fieldNames":["streamB"]}],"childNodes":[{"typeName":"StreamEvent","fieldNames":["key","contents"]}],"overrideFieldPathFromAlias":true,"customGraphql":{"fetch":{"url":{"staticVariableContent":"http://localhost:14002/graphql"},"method":"POST","body":{},"baseUrl":{},"path":{}},"subscription":{"enabled":true,"url":{"staticVariableContent":"http://localhost:14002/graphql"},"protocol":"GRAPHQL_SUBSCRIPTION_PROTOCOL_WS","websocketSubprotocol":"GRAPHQL_WEBSOCKET_SUBPROTOCOL_AUTO"},"federation":{"enabled":true,"serviceSdl":"extend schema\n @link(\n url: \"https://specs.apollo.dev/federation/v2.5\"\n import: [\"@shareable\"]\n )\n\ntype Query {\n _empty: Boolean @shareable\n}\n\nscalar JSON\n\ntype Subscription {\n streamB(key: String): StreamEvent\n}\n\ntype StreamEvent @shareable {\n key: String\n contents: JSON\n}\n"},"upstreamSchema":{"key":"887e4dd1780bb19c98ac8afed32bce3614275f9d"}},"requestTimeoutSeconds":"10","id":"1"}],"fieldConfigurations":[{"typeName":"Subscription","fieldName":"streamA","argumentsConfiguration":[{"name":"key","sourceType":"FIELD_ARGUMENT"}]},{"typeName":"Subscription","fieldName":"streamB","argumentsConfiguration":[{"name":"key","sourceType":"FIELD_ARGUMENT"}]}],"graphqlSchema":"schema {\n query: Query\n subscription: Subscription\n}\n\ntype Query {\n _empty: Boolean\n}\n\nscalar JSON\n\ntype Subscription {\n streamA(key: String): StreamEvent\n streamB(key: String): StreamEvent\n}\n\ntype StreamEvent {\n key: String\n contents: JSON\n}","stringStorage":{"9786cf1d663fd14f29625298f1b112c817720395":"schema {\n query: Query\n subscription: Subscription\n}\n\ndirective @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA\n\ndirective @shareable repeatable on FIELD_DEFINITION | OBJECT\n\nscalar JSON\n\ntype Query {\n _empty: Boolean @shareable\n}\n\ntype StreamEvent {\n contents: JSON @shareable\n key: String @shareable\n}\n\ntype Subscription {\n streamA(key: String): StreamEvent\n}\n\nscalar link__Import\n\nenum link__Purpose {\n EXECUTION\n SECURITY\n}","887e4dd1780bb19c98ac8afed32bce3614275f9d":"schema {\n query: Query\n subscription: Subscription\n}\n\ndirective @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA\n\ndirective @shareable repeatable on FIELD_DEFINITION | OBJECT\n\nscalar JSON\n\ntype Query {\n _empty: Boolean @shareable\n}\n\ntype StreamEvent {\n contents: JSON @shareable\n key: String @shareable\n}\n\ntype Subscription {\n streamB(key: String): StreamEvent\n}\n\nscalar link__Import\n\nenum link__Purpose {\n EXECUTION\n SECURITY\n}"}},"version":"00000000-0000-0000-0000-000000000000","subgraphs":[{"id":"0","name":"subgraph-a","routingUrl":"http://localhost:14001/graphql"},{"id":"1","name":"subgraph-b","routingUrl":"http://localhost:14002/graphql"}],"compatibilityVersion":"1:{{$COMPOSITION__VERSION}}"}
\ No newline at end of file
diff --git a/speedtrap/scenarios/graphql/configs/cosmo/graph.yaml b/speedtrap/scenarios/graphql/configs/cosmo/graph.yaml
new file mode 100644
index 0000000000..daf7602ee1
--- /dev/null
+++ b/speedtrap/scenarios/graphql/configs/cosmo/graph.yaml
@@ -0,0 +1,10 @@
+version: 1
+subgraphs:
+ - name: subgraph-a
+ routing_url: http://localhost:14001/graphql
+ schema:
+ file: ../../subgraph-a.graphqls
+ - name: subgraph-b
+ routing_url: http://localhost:14002/graphql
+ schema:
+ file: ../../subgraph-b.graphqls
diff --git a/speedtrap/scenarios/graphql/proxy/PROTOCOL_AMENDMENTS.md b/speedtrap/scenarios/graphql/proxy/PROTOCOL_AMENDMENTS.md
new file mode 100644
index 0000000000..6ba526b0eb
--- /dev/null
+++ b/speedtrap/scenarios/graphql/proxy/PROTOCOL_AMENDMENTS.md
@@ -0,0 +1,68 @@
+# Protocol amendments
+
+The speedtrap proxy scenarios intentionally deviate from the reference server
+implementations in several cases. This document records each deviation, the
+reference behavior it replaces, and the rationale.
+
+# subscriptions-transport-ws (graphql-ws subprotocol)
+
+Deviations from the subscriptions-transport-ws reference server (v0.11.0).
+These apply graphql-transport-ws close semantics to the legacy protocol for
+consistency, safety, and lower implementation complexity.
+
+## Unknown message types close the connection
+
+**Reference behavior:** Returns `{"type":"error","payload":{"message":"Invalid
+message type!"}}` and keeps the connection alive.
+
+**Speedtrap expectation:** Closes the connection (mirrors graphql-transport-ws
+close with 4400).
+
+**Scenario:** `UnknownMessageTypeClosesSocket`
+
+**Rationale:** The error-and-continue approach creates an infinite loop risk — a
+misbehaving client can spam unknown messages indefinitely. Closing on unknown
+types is consistent with the modern protocol and avoids this problem.
+
+## Duplicate connection_init closes the connection
+
+**Reference behavior:** Silently re-acks every `connection_init`, keeping the
+connection alive.
+
+**Speedtrap expectation:** The protocol layer closes with 4429 (mirrors
+graphql-transport-ws "Too many initialisation requests").
+
+**Scenario:** `DuplicateConnectionInitClosesSocket`
+
+**Rationale:** Silently re-acking is permissive to the point of being dangerous.
+A client sending repeated `connection_init` messages is either buggy or
+malicious.
+
+## Subscribe before connection_init closes the connection
+
+**Reference behavior:** Processes the subscription without requiring a
+handshake — sends data back immediately.
+
+**Speedtrap expectation:** The protocol layer closes with 4401 (mirrors
+graphql-transport-ws "Unauthorized").
+
+**Scenario:** `SubscribeBeforeAckClosesSocket`
+
+**Rationale:** Skipping the handshake bypasses any authentication or
+authorization that may be attached to `connection_init`. The reference server's
+permissiveness here is a security concern.
+
+## Duplicate subscription ID closes the connection
+
+**Reference behavior:** Completes the existing subscription for that ID, then
+starts a new one with the same ID (replace semantics). The connection stays
+alive.
+
+**Speedtrap expectation:** Closes the connection (matches graphql-transport-ws
+close with 4409 "Subscriber for already exists").
+
+**Scenario:** `DuplicateStartIDClosesSocket`
+
+**Rationale:** Implicit replacement adds complexity and can mask client bugs. A
+client reusing an active ID is almost certainly a bug. Closing is the safest
+response and keeps behavior consistent across protocols.
diff --git a/speedtrap/scenarios/graphql/proxy/graphqltransportws/README.md b/speedtrap/scenarios/graphql/proxy/graphqltransportws/README.md
new file mode 100644
index 0000000000..cb7e9b3a0a
--- /dev/null
+++ b/speedtrap/scenarios/graphql/proxy/graphqltransportws/README.md
@@ -0,0 +1,36 @@
+# graphql-transport-ws proxy scenarios
+
+Protocol: [graphql-transport-ws](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md) (subprotocol `graphql-transport-ws`)
+
+These scenarios verify the router's behavior as a WebSocket proxy for the
+modern graphql-transport-ws protocol. Both the client and the upstream
+subgraph speak this protocol. The router remaps subscription IDs between
+client and upstream.
+
+The test harness must register a backend named `"subgraph-a"`.
+
+## Connection phase (`connect.go`)
+
+| Scenario | Asserts |
+|-|-|
+| `DuplicateConnectionInitClosesSocket` | A second `connection_init` after ack terminates the connection (close 4429 when a close frame is sent; TCP drop also accepted) |
+| `SubscribeBeforeAckClosesSocket` | Sending `subscribe` without a prior `connection_init` terminates the connection (close 4401 when a close frame is sent; TCP drop also accepted) |
+
+## Ping/pong (`pingpong.go`)
+
+| Scenario | Asserts |
+|-|-|
+| `PingReceivesPongResponse` | A protocol-level `{"type":"ping"}` receives a `{"type":"pong"}` response |
+| `PongCarriesPingPayload` | The pong message echoes the ping's `payload` field verbatim |
+
+## Subscribe lifecycle (`scenarios.go`, `lifecycle.go`)
+
+| Scenario | Asserts |
+|-|-|
+| `SubscribeRoundTrip` | Full lifecycle: init/ack, subscribe, backend receives remapped ID, `next` forwarded with original client ID, `complete` forwarded |
+| `SubscribeWithVariablesAndOperationName` | Subscribe payload containing `variables` and `operationName` is forwarded to the backend; `next` and `complete` round-trip correctly |
+| `MultipleNextMessagesBeforeComplete` | Three `next` messages are forwarded in order before `complete` |
+| `DuplicateSubscriptionIDClosesSocket` | A second `subscribe` with an already-active ID closes the connection with 4409 and reason `"Subscriber for 1 already exists"` |
+| `ClientCompleteStopsSubscription` | Client-sent `complete` is forwarded to the backend with the remapped upstream ID |
+| `ServerErrorTerminatesOperation` | Backend `error` message is forwarded to the client with the original ID and payload |
+| `MultipleConcurrentSubscriptions` | Two subscriptions (IDs `"1"` and `"2"`) on one connection receive independent `next` and `complete` messages with correct ID mapping |
diff --git a/speedtrap/scenarios/graphql/proxy/graphqltransportws/connect.go b/speedtrap/scenarios/graphql/proxy/graphqltransportws/connect.go
new file mode 100644
index 0000000000..387d22c4f0
--- /dev/null
+++ b/speedtrap/scenarios/graphql/proxy/graphqltransportws/connect.go
@@ -0,0 +1,67 @@
+package graphqltransportws
+
+import (
+ "github.com/gobwas/ws"
+ "github.com/stretchr/testify/require"
+ "github.com/wundergraph/cosmo/speedtrap"
+)
+
+// DuplicateConnectionInitClosesSocket verifies that sending a second
+// connection_init after acknowledgment terminates the connection with close
+// code 4429 per the graphql-transport-ws spec.
+var DuplicateConnectionInitClosesSocket = speedtrap.Scenario{
+ Name: "duplicate connection init closes socket with 4429",
+ Run: func(s *speedtrap.S) {
+ c := clientHandshake(s)
+
+ // Second init — server must close with 4429
+ require.NoError(s, c.Send(`{"type":"connection_init"}`))
+
+ cf, err := c.ReadControl()
+ require.NoError(s, err)
+ require.Equal(s, ws.OpClose, cf.OpCode)
+ code, reason := cf.CloseData()
+ require.Equal(s, ws.StatusCode(4429), code, "close code should be 4429, got %d", int(code))
+ require.Equal(s, "Too many initialisation requests", reason)
+ },
+}
+
+// SubscribeBeforeAckClosesSocket verifies that sending a subscribe message
+// before the connection is acknowledged terminates the connection with close
+// code 4401 per the graphql-transport-ws spec.
+var SubscribeBeforeAckClosesSocket = speedtrap.Scenario{
+ Name: "subscribe before connection ack closes socket with 4401",
+ Run: func(s *speedtrap.S) {
+ c, err := s.Client(speedtrap.WithClientSubprotocol("graphql-transport-ws"))
+ require.NoError(s, err)
+
+ // Send subscribe without init — server must close with 4401
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription{streamA {key}}"}}`))
+
+ cf, err := c.ReadControl()
+ require.NoError(s, err)
+ require.Equal(s, ws.OpClose, cf.OpCode)
+ code, reason := cf.CloseData()
+ require.Equal(s, ws.StatusCode(4401), code)
+ require.Equal(s, "Unauthorized", reason)
+ },
+}
+
+// UnknownMessageTypeClosesSocket verifies that sending an unknown message
+// type results in an immediate close with code 4400 per the
+// graphql-transport-ws spec.
+var UnknownMessageTypeClosesSocket = speedtrap.Scenario{
+ Name: "unknown message type closes socket with 4400",
+ Run: func(s *speedtrap.S) {
+ c := clientHandshake(s)
+
+ // Send a bogus message type — server must close with 4400
+ require.NoError(s, c.Send(`{"type":"bogus"}`))
+
+ cf, err := c.ReadControl()
+ require.NoError(s, err)
+ require.Equal(s, ws.OpClose, cf.OpCode)
+ code, _ := cf.CloseData()
+ require.Equal(s, ws.StatusCode(4400), code)
+ },
+}
diff --git a/speedtrap/scenarios/graphql/proxy/graphqltransportws/disruption.go b/speedtrap/scenarios/graphql/proxy/graphqltransportws/disruption.go
new file mode 100644
index 0000000000..5c30c09f2d
--- /dev/null
+++ b/speedtrap/scenarios/graphql/proxy/graphqltransportws/disruption.go
@@ -0,0 +1,148 @@
+package graphqltransportws
+
+import (
+ "fmt"
+
+ "github.com/kinbiko/jsonassert"
+ "github.com/stretchr/testify/require"
+ "github.com/wundergraph/cosmo/speedtrap"
+)
+
+// BackendTCPDropDuringActiveSubscription verifies that when the backend
+// forcibly drops TCP during an active subscription, the client receives an
+// error for the affected subscription.
+var BackendTCPDropDuringActiveSubscription = speedtrap.Scenario{
+ Name: "backend TCP drop during active subscription",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"drop"}}}`))
+
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"drop"}}}`)
+
+ // Forcibly close TCP — no close frame
+ require.NoError(s, b.Drop())
+
+ // Client must receive exactly one error from the upstream
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"error","id":"1","payload":[{"message":"upstream service error","extensions":{"code":"<>"}}]}`)
+ },
+}
+
+// BackendCloseFrameDuringActiveSubscription verifies that when the backend
+// sends a close frame during an active subscription, the client receives an
+// error for the affected subscription.
+var BackendCloseFrameDuringActiveSubscription = speedtrap.Scenario{
+ Name: "backend close frame during active subscription",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"bclose"}}}`))
+
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"bclose"}}}`)
+
+ // Backend sends close frame
+ require.NoError(s, b.SendClose(1011, "internal error"))
+
+ // Client must receive exactly one error from the upstream with close info
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"error","id":"1","payload":[{"message":"upstream service error","extensions":{"code":"<>","closeCode":1011,"closeReason":"internal error"}}]}`)
+ },
+}
+
+// ClientTCPDropCleansUpBackendSubscription verifies the proxy cleans up the
+// backend subscription when the client forcibly drops TCP.
+var ClientTCPDropCleansUpBackendSubscription = speedtrap.Scenario{
+ Name: "client TCP drop cleans up backend subscription",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"cdrop"}}}`))
+
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"cdrop"}}}`)
+ subID := ExtractID(msg)
+
+ // Client forcibly drops TCP
+ require.NoError(s, c.Drop())
+
+ // Backend must receive complete for the active subscription
+ msg, err = b.Read()
+ if err != nil {
+ return // connection closed — acceptable
+ }
+ require.JSONEq(s, fmt.Sprintf(`{"type":"complete","id":"%s"}`, subID), msg)
+ },
+}
+
+// ClientCloseFrameCleansUpBackendSubscription verifies the proxy cleans up the
+// backend subscription when the client sends a close frame.
+var ClientCloseFrameCleansUpBackendSubscription = speedtrap.Scenario{
+ Name: "client close frame cleans up backend subscription",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"cclose"}}}`))
+
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"cclose"}}}`)
+ subID := ExtractID(msg)
+
+ // Client sends close frame
+ require.NoError(s, c.SendClose(1000, "going away"))
+
+ // Backend must receive complete for the active subscription
+ msg, err = b.Read()
+ if err != nil {
+ return // connection closed — acceptable
+ }
+ require.JSONEq(s, fmt.Sprintf(`{"type":"complete","id":"%s"}`, subID), msg)
+ },
+}
+
+// BackendNeverAcksConnectionInitTimesOut verifies that when the backend accepts
+// the connection but never sends connection_ack, the client receives an error
+// for the pending subscribe.
+var BackendNeverAcksConnectionInitTimesOut = speedtrap.Scenario{
+ Name: "backend never acks connection init times out",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"noack"}}}`))
+
+ // Backend accepts but never sends connection_ack
+ b, err := s.Backend("subgraph-a").Accept()
+ require.NoError(s, err)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_init"}`, msg)
+ // Deliberately do NOT send connection_ack
+
+ // Client must receive an error for the pending subscribe
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"error","id":"1","payload":[{"message":"upstream service error","extensions":{"code":"<>"}}]}`)
+ },
+}
diff --git a/speedtrap/scenarios/graphql/proxy/graphqltransportws/headers.go b/speedtrap/scenarios/graphql/proxy/graphqltransportws/headers.go
new file mode 100644
index 0000000000..9b3f4b981d
--- /dev/null
+++ b/speedtrap/scenarios/graphql/proxy/graphqltransportws/headers.go
@@ -0,0 +1,142 @@
+package graphqltransportws
+
+import (
+ "fmt"
+ "net/http"
+
+ "github.com/kinbiko/jsonassert"
+ "github.com/stretchr/testify/require"
+ "github.com/wundergraph/cosmo/speedtrap"
+)
+
+// AllowlistedHeadersForwardedToBackend verifies that client upgrade headers
+// matching the router's header propagation rules are forwarded as HTTP headers
+// on the upstream WebSocket dial.
+var AllowlistedHeadersForwardedToBackend = speedtrap.Scenario{
+ Name: "allowlisted headers forwarded to backend",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ headers := http.Header{
+ "Authorization": {"Bearer tok"},
+ "X-Custom-Trace": {"abc123"},
+ }
+ c, err := s.Client(
+ speedtrap.WithClientSubprotocol("graphql-transport-ws"),
+ speedtrap.WithClientHeaders(headers),
+ )
+ require.NoError(s, err)
+ require.NoError(s, c.Send(`{"type":"connection_init"}`))
+ msg, err := c.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_ack"}`, msg)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"hdr"}}}`))
+
+ b, err := s.Backend("subgraph-a").Accept()
+ require.NoError(s, err)
+
+ require.Equal(s, "Bearer tok", b.UpgradeHeaders.Get("Authorization"))
+ require.Equal(s, "abc123", b.UpgradeHeaders.Get("X-Custom-Trace"))
+
+ msg, err = b.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_init"}`, msg)
+ require.NoError(s, b.Send(`{"type":"connection_ack"}`))
+
+ // Read the forwarded subscribe and complete the conversation
+ msg, err = b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"hdr"}}}`)
+ subID := ExtractID(msg)
+
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID)))
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"complete","id":"1"}`)
+ },
+}
+
+// NonAllowlistedHeadersFilteredOut verifies that client upgrade headers NOT
+// matching the router's header propagation rules are stripped before the
+// upstream WebSocket dial.
+var NonAllowlistedHeadersFilteredOut = speedtrap.Scenario{
+ Name: "non-allowlisted headers filtered out",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ headers := http.Header{
+ "Authorization": {"Bearer tok"},
+ "X-Secret-Internal": {"should-be-stripped"},
+ }
+ c, err := s.Client(
+ speedtrap.WithClientSubprotocol("graphql-transport-ws"),
+ speedtrap.WithClientHeaders(headers),
+ )
+ require.NoError(s, err)
+ require.NoError(s, c.Send(`{"type":"connection_init"}`))
+ msg, err := c.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_ack"}`, msg)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"filter"}}}`))
+
+ b, err := s.Backend("subgraph-a").Accept()
+ require.NoError(s, err)
+
+ require.Equal(s, "Bearer tok", b.UpgradeHeaders.Get("Authorization"))
+ require.Empty(s, b.UpgradeHeaders.Get("X-Secret-Internal"))
+
+ msg, err = b.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_init"}`, msg)
+ require.NoError(s, b.Send(`{"type":"connection_ack"}`))
+
+ // Read the forwarded subscribe and complete the conversation
+ msg, err = b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"filter"}}}`)
+ subID := ExtractID(msg)
+
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID)))
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"complete","id":"1"}`)
+ },
+}
+
+// ConnectionInitPayloadForwardedToBackend verifies that the connection_init
+// payload from the client is forwarded to the backend.
+var ConnectionInitPayloadForwardedToBackend = speedtrap.Scenario{
+ Name: "connection init payload forwarded to backend",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c, err := s.Client(speedtrap.WithClientSubprotocol("graphql-transport-ws"))
+ require.NoError(s, err)
+ require.NoError(s, c.Send(`{"type":"connection_init","payload":{"token":"abc"}}`))
+ msg, err := c.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_ack"}`, msg)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"init"}}}`))
+
+ b, err := s.Backend("subgraph-a").Accept()
+ require.NoError(s, err)
+ msg, err = b.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_init","payload":{"token":"abc"}}`, msg)
+ require.NoError(s, b.Send(`{"type":"connection_ack"}`))
+
+ // Read the forwarded subscribe and complete the conversation
+ msg, err = b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"init"}}}`)
+ subID := ExtractID(msg)
+
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID)))
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"complete","id":"1"}`)
+ },
+}
diff --git a/speedtrap/scenarios/graphql/proxy/graphqltransportws/lifecycle.go b/speedtrap/scenarios/graphql/proxy/graphqltransportws/lifecycle.go
new file mode 100644
index 0000000000..b03025a8c8
--- /dev/null
+++ b/speedtrap/scenarios/graphql/proxy/graphqltransportws/lifecycle.go
@@ -0,0 +1,319 @@
+package graphqltransportws
+
+import (
+ "fmt"
+
+ "github.com/kinbiko/jsonassert"
+ "github.com/stretchr/testify/require"
+ "github.com/tidwall/gjson"
+ "github.com/wundergraph/cosmo/speedtrap"
+)
+
+// MultipleNextMessagesBeforeComplete verifies the proxy forwards multiple next
+// messages for a single subscription before the final complete.
+var MultipleNextMessagesBeforeComplete = speedtrap.Scenario{
+ Name: "multiple next messages before complete",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key contents}}","variables":{"key":"multi"}}}`))
+
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ subID := ExtractID(msg)
+
+ // Backend sends 3 next messages
+ for i := 1; i <= 3; i++ {
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"next","payload":{"data":{"streamA":{"key":"multi","contents":%d}}}}`, subID, i)))
+ }
+
+ // Client receives all 3 next messages with original ID
+ for i := 1; i <= 3; i++ {
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"next","id":"1","payload":{"data":{"streamA":{"key":"multi","contents":%d}}}}`, i)
+ }
+
+ // Backend sends complete
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID)))
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"complete","id":"1"}`)
+ },
+}
+
+// ClientCompleteStopsSubscription verifies that when the client sends a
+// complete message, the proxy forwards it to the backend (stopping the
+// upstream subscription).
+var ClientCompleteStopsSubscription = speedtrap.Scenario{
+ Name: "client complete stops upstream subscription",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"stop"}}}`))
+
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"stop"}}}`)
+ subID := ExtractID(msg)
+
+ // Client sends complete to cancel
+ require.NoError(s, c.Send(`{"id":"1","type":"complete"}`))
+
+ // Server echoes complete back to client
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"complete","id":"1"}`)
+
+ // Backend should receive a complete with remapped ID
+ msg, err = b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"complete","id":"%s"}`, subID)
+ },
+}
+
+// ServerErrorTerminatesOperation verifies that when the backend sends an error
+// message, it is forwarded to the client and terminates the subscription
+// (no separate complete message follows the error).
+var ServerErrorTerminatesOperation = speedtrap.Scenario{
+ Name: "server error terminates operation",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"err"}}}`))
+
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ subID := ExtractID(msg)
+
+ // Backend sends error (terminates the operation per spec)
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"error","payload":[{"message":"something went wrong"}]}`, subID)))
+
+ // Client receives error with original ID
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"error","id":"1","payload":[{"message":"something went wrong"}]}`)
+ },
+}
+
+// SubscribeWithVariablesAndOperationName verifies that when a client sends a
+// document with multiple named operations, the proxy selects the one matching
+// operationName, strips the name, and forwards only that operation with its
+// variables.
+var SubscribeWithVariablesAndOperationName = speedtrap.Scenario{
+ Name: "subscribe with variables and operation name",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ // Client sends a document with two named subscriptions and selects WatchStream
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription WatchStream($k: String){streamA(key: $k){key contents}} subscription Other{streamA(key: \"unused\"){key}}","variables":{"k":"vars-test"},"operationName":"WatchStream"}}`))
+
+ // Backend receives the selected operation only, with the name stripped
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($k: String){streamA(key: $k){key contents}}","variables":{"k":"vars-test"}}}`)
+ subID := ExtractID(msg)
+
+ // Backend sends next, client receives it
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"next","payload":{"data":{"streamA":{"key":"vars-test","contents":"hello"}}}}`, subID)))
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"next","id":"1","payload":{"data":{"streamA":{"key":"vars-test","contents":"hello"}}}}`)
+
+ // Complete
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID)))
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"complete","id":"1"}`)
+ },
+}
+
+// IDReuseAfterOperationCompletes verifies that a client can reuse a
+// subscription ID after the server has completed that operation. Per the
+// graphql-transport-ws spec, once a server-initiated complete is received
+// for an ID, the client is free to subscribe again with that same ID.
+// The proxy must deliver the new subscribe on the same upstream connection
+// (same client, same init payload, same subgraph — multiplexing applies).
+var IDReuseAfterOperationCompletes = speedtrap.Scenario{
+ Name: "ID reuse after operation completes",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ // First subscription with id "1"
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"reuse1"}}}`))
+
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ subID1 := ExtractID(msg)
+
+ // Backend sends next then complete for the first subscription
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"next","payload":{"data":{"streamA":{"key":"reuse1"}}}}`, subID1)))
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"next","id":"1","payload":{"data":{"streamA":{"key":"reuse1"}}}}`)
+
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID1)))
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"complete","id":"1"}`)
+
+ // Reuse id "1" for a new subscription
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"reuse2"}}}`))
+
+ // The previous upstream connection was closed after the last subscription
+ // completed, so the proxy opens a fresh one for the new subscribe.
+ b, err = s.Backend("subgraph-a").Accept()
+ require.NoError(s, err)
+ msg, err = b.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_init"}`, msg)
+ require.NoError(s, b.Send(`{"type":"connection_ack"}`))
+
+ msg, err = b.Read()
+ require.NoError(s, err)
+ require.Equal(s, "subscribe", ExtractType(msg))
+ subID2 := ExtractID(msg)
+
+ // Backend sends next for the reused ID
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"next","payload":{"data":{"streamA":{"key":"reuse2"}}}}`, subID2)))
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"next","id":"1","payload":{"data":{"streamA":{"key":"reuse2"}}}}`)
+
+ // Complete
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID2)))
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"complete","id":"1"}`)
+ },
+}
+
+// MultipleConcurrentSubscriptions verifies that the proxy correctly multiplexes
+// multiple active subscriptions on a single client connection, each with its
+// own ID and independent data flow.
+var MultipleConcurrentSubscriptions = speedtrap.Scenario{
+ Name: "multiple concurrent subscriptions on one connection",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ // Subscribe with id "1"
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"a"}}}`))
+
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ subID1 := ExtractID(msg)
+
+ // Subscribe with id "2"
+ require.NoError(s, c.Send(`{"id":"2","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"b"}}}`))
+
+ // Proxy must multiplex onto the same upstream connection
+ _, err = s.Backend("subgraph-a").TryAccept()
+ require.Error(s, err, "expected no second upstream connection (multiplexing)")
+
+ msg, err = b.Read()
+ require.NoError(s, err)
+ subID2 := ExtractID(msg)
+
+ // Backend sends next for both subscriptions
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"next","payload":{"data":{"streamA":{"key":"a"}}}}`, subID1)))
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"next","id":"1","payload":{"data":{"streamA":{"key":"a"}}}}`)
+
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"next","payload":{"data":{"streamA":{"key":"b"}}}}`, subID2)))
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"next","id":"2","payload":{"data":{"streamA":{"key":"b"}}}}`)
+
+ // Complete both
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID1)))
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"complete","id":"1"}`)
+
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID2)))
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"complete","id":"2"}`)
+ },
+}
+
+// OneSubscriptionErrorDoesNotAffectAnother verifies that an error on one
+// subscription does not disrupt a concurrent subscription on the same connection.
+var OneSubscriptionErrorDoesNotAffectAnother = speedtrap.Scenario{
+ Name: "one subscription error does not affect another",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ // Two concurrent subscriptions
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"err1"}}}`))
+ require.NoError(s, c.Send(`{"id":"2","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"err2"}}}`))
+
+ b := backendHandshake(s)
+
+ // Proxy must multiplex onto the same upstream connection
+ _, err := s.Backend("subgraph-a").TryAccept()
+ require.Error(s, err, "expected no second upstream connection (multiplexing)")
+
+ // Read both subscribes (order is non-deterministic)
+ var subID1, subID2 string
+ varKey := func(msg string) string { return gjson.Get(msg, "payload.variables.key").String() }
+ speedtrap.ReadSwitch(s, b.Messages(), varKey,
+ speedtrap.Case("err1", func(msg string) { subID1 = ExtractID(msg) }),
+ speedtrap.Case("err2", func(msg string) { subID2 = ExtractID(msg) }),
+ )
+
+ // Error on subscription 1
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"error","payload":[{"message":"sub1 failed"}]}`, subID1)))
+
+ // Next on subscription 2 — should still work
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"next","payload":{"data":{"streamA":{"key":"err2"}}}}`, subID2)))
+
+ // Client receives error for "1" and next for "2" (unordered).
+ idType := func(msg string) string { return ExtractID(msg) + ":" + ExtractType(msg) }
+ speedtrap.ReadSwitch(s, c.Messages(), idType,
+ speedtrap.Case("1:error", func(msg string) {
+ ja.Assertf(msg, `{"type":"error","id":"1","payload":[{"message":"sub1 failed"}]}`)
+ }),
+ speedtrap.Case("2:next", func(msg string) {
+ ja.Assertf(msg, `{"type":"next","id":"2","payload":{"data":{"streamA":{"key":"err2"}}}}`)
+ }),
+ )
+
+ // Complete subscription 2
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID2)))
+
+ completeMsg, completeErr := c.Read()
+ require.NoError(s, completeErr)
+ ja.Assertf(completeMsg, `{"type":"complete","id":"2"}`)
+ },
+}
diff --git a/speedtrap/scenarios/graphql/proxy/graphqltransportws/multiplex.go b/speedtrap/scenarios/graphql/proxy/graphqltransportws/multiplex.go
new file mode 100644
index 0000000000..f68d8f8f93
--- /dev/null
+++ b/speedtrap/scenarios/graphql/proxy/graphqltransportws/multiplex.go
@@ -0,0 +1,146 @@
+package graphqltransportws
+
+import (
+ "fmt"
+
+ "github.com/kinbiko/jsonassert"
+ "github.com/stretchr/testify/require"
+ "github.com/tidwall/gjson"
+ "github.com/wundergraph/cosmo/speedtrap"
+)
+
+// MultipleSubscriptionsShareOneUpstreamConnection verifies that the proxy
+// multiplexes multiple subscriptions from a single client connection onto one
+// upstream backend connection.
+var MultipleSubscriptionsShareOneUpstreamConnection = speedtrap.Scenario{
+ Name: "multiple subscriptions share one upstream connection",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ // Two subscribes on the same connection
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"mux1"}}}`))
+ require.NoError(s, c.Send(`{"id":"2","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"mux2"}}}`))
+
+ // First backend connection
+ b := backendHandshake(s)
+
+ // Read both subscribes (order is non-deterministic)
+ var subIDMux1, subIDMux2 string
+ varKey := func(msg string) string { return gjson.Get(msg, "payload.variables.key").String() }
+ speedtrap.ReadSwitch(s, b.Messages(), varKey,
+ speedtrap.Case("mux1", func(msg string) {
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"mux1"}}}`)
+ subIDMux1 = ExtractID(msg)
+ }),
+ speedtrap.Case("mux2", func(msg string) {
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"mux2"}}}`)
+ subIDMux2 = ExtractID(msg)
+ }),
+ )
+
+ // Try to accept a second connection — should fail (multiplexed)
+ _, err := s.Backend("subgraph-a").TryAccept()
+ require.Error(s, err, "expected no second upstream connection (multiplexing)")
+
+ // Send next for mux1, verify client receives it with client ID "1"
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"next","payload":{"data":{"streamA":{"key":"mux1"}}}}`, subIDMux1)))
+ msg, err := c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"next","id":"1","payload":{"data":{"streamA":{"key":"mux1"}}}}`)
+
+ // Send next for mux2, verify client receives it with client ID "2"
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"next","payload":{"data":{"streamA":{"key":"mux2"}}}}`, subIDMux2)))
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"next","id":"2","payload":{"data":{"streamA":{"key":"mux2"}}}}`)
+
+ // Complete mux1
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subIDMux1)))
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"complete","id":"1"}`)
+
+ // Complete mux2
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subIDMux2)))
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"complete","id":"2"}`)
+ },
+}
+
+// DifferentInitPayloadsGetSeparateUpstreamConnections verifies that two client
+// connections with different connection_init payloads result in separate upstream
+// connections (the proxy keys connection pools by init payload).
+var DifferentInitPayloadsGetSeparateUpstreamConnections = speedtrap.Scenario{
+ Name: "different init payloads get separate upstream connections",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ // Client 1 with token "aaa"
+ c1, err := s.Client(speedtrap.WithClientSubprotocol("graphql-transport-ws"))
+ require.NoError(s, err)
+ require.NoError(s, c1.Send(`{"type":"connection_init","payload":{"token":"aaa"}}`))
+ msg, err := c1.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_ack"}`, msg)
+
+ require.NoError(s, c1.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"sep1"}}}`))
+
+ // Client 2 with token "bbb"
+ c2, err := s.Client(speedtrap.WithClientSubprotocol("graphql-transport-ws"))
+ require.NoError(s, err)
+ require.NoError(s, c2.Send(`{"type":"connection_init","payload":{"token":"bbb"}}`))
+ msg, err = c2.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_ack"}`, msg)
+
+ require.NoError(s, c2.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"sep2"}}}`))
+
+ // Two separate backend connections expected — accept order is non-deterministic
+ conns := make([]*speedtrap.ConnectionHandle, 2)
+ for i := range conns {
+ conns[i], err = s.Backend("subgraph-a").Accept()
+ require.NoError(s, err)
+ }
+
+ var b1, b2 *speedtrap.ConnectionHandle
+ token := func(t speedtrap.Tagged) string { return gjson.Get(t.Msg, "payload.token").String() }
+ speedtrap.ReadSwitch(s, speedtrap.MergeMessages(conns...), token,
+ speedtrap.Case("aaa", func(t speedtrap.Tagged) {
+ require.JSONEq(s, `{"type":"connection_init","payload":{"token":"aaa"}}`, t.Msg)
+ require.NoError(s, t.Conn.Send(`{"type":"connection_ack"}`))
+ b1 = t.Conn
+ }),
+ speedtrap.Case("bbb", func(t speedtrap.Tagged) {
+ require.JSONEq(s, `{"type":"connection_init","payload":{"token":"bbb"}}`, t.Msg)
+ require.NoError(s, t.Conn.Send(`{"type":"connection_ack"}`))
+ b2 = t.Conn
+ }),
+ )
+
+ // Read forwarded subscribes and complete both conversations
+ msg, err = b1.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"sep1"}}}`)
+ subID1 := ExtractID(msg)
+
+ msg, err = b2.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"sep2"}}}`)
+ subID2 := ExtractID(msg)
+
+ require.NoError(s, b1.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID1)))
+ msg, err = c1.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"complete","id":"1"}`)
+
+ require.NoError(s, b2.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID2)))
+ msg, err = c2.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"complete","id":"1"}`)
+ },
+}
diff --git a/speedtrap/scenarios/graphql/proxy/graphqltransportws/pingpong.go b/speedtrap/scenarios/graphql/proxy/graphqltransportws/pingpong.go
new file mode 100644
index 0000000000..d01e683e54
--- /dev/null
+++ b/speedtrap/scenarios/graphql/proxy/graphqltransportws/pingpong.go
@@ -0,0 +1,40 @@
+package graphqltransportws
+
+import (
+ "github.com/stretchr/testify/require"
+ "github.com/wundergraph/cosmo/speedtrap"
+)
+
+// PingReceivesPongResponse verifies that the proxy responds to a
+// graphql-transport-ws ping message with a pong message.
+var PingReceivesPongResponse = speedtrap.Scenario{
+ Name: "ping receives pong response",
+ Run: func(s *speedtrap.S) {
+ c := clientHandshake(s)
+
+ // Send protocol-level ping
+ require.NoError(s, c.Send(`{"type":"ping"}`))
+
+ // Expect protocol-level pong
+ msg, err := c.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"pong"}`, msg)
+ },
+}
+
+// PongCarriesPingPayload verifies that the proxy echoes the ping message's
+// payload in the pong response per the graphql-transport-ws spec.
+var PongCarriesPingPayload = speedtrap.Scenario{
+ Name: "pong carries ping payload",
+ Run: func(s *speedtrap.S) {
+ c := clientHandshake(s)
+
+ // Send ping with payload
+ require.NoError(s, c.Send(`{"type":"ping","payload":{"hello":"world"}}`))
+
+ // Pong must carry the same payload
+ msg, err := c.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"pong","payload":{"hello":"world"}}`, msg)
+ },
+}
diff --git a/speedtrap/scenarios/graphql/proxy/graphqltransportws/scenarios.go b/speedtrap/scenarios/graphql/proxy/graphqltransportws/scenarios.go
new file mode 100644
index 0000000000..51399eeeac
--- /dev/null
+++ b/speedtrap/scenarios/graphql/proxy/graphqltransportws/scenarios.go
@@ -0,0 +1,153 @@
+package graphqltransportws
+
+import (
+ "fmt"
+
+ "github.com/gobwas/ws"
+ "github.com/kinbiko/jsonassert"
+ "github.com/stretchr/testify/require"
+ "github.com/tidwall/gjson"
+ "github.com/wundergraph/cosmo/speedtrap"
+)
+
+// clientHandshake performs the graphql-transport-ws connection handshake.
+func clientHandshake(s *speedtrap.S) *speedtrap.ConnectionHandle {
+ c, err := s.Client(speedtrap.WithClientSubprotocol("graphql-transport-ws"))
+ require.NoError(s, err)
+
+ require.NoError(s, c.Send(`{"type":"connection_init"}`))
+ msg, err := c.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_ack"}`, msg)
+
+ return c
+}
+
+// backendHandshake accepts a backend connection and completes the
+// graphql-transport-ws handshake.
+func backendHandshake(s *speedtrap.S) *speedtrap.ConnectionHandle {
+ b, err := s.Backend("subgraph-a").Accept()
+ require.NoError(s, err)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_init"}`, msg)
+ require.NoError(s, b.Send(`{"type":"connection_ack"}`))
+ return b
+}
+
+// Scenarios contains all graphql-transport-ws proxy scenarios.
+// The test harness must register a backend named "subgraph-a".
+var Scenarios = []speedtrap.Scenario{
+ // Connection phase
+ DuplicateConnectionInitClosesSocket,
+ SubscribeBeforeAckClosesSocket,
+ UnknownMessageTypeClosesSocket,
+
+ // Ping/pong
+ PingReceivesPongResponse,
+ PongCarriesPingPayload,
+
+ // Subscribe lifecycle
+ SubscribeRoundTrip,
+ SubscribeWithVariablesAndOperationName,
+ MultipleNextMessagesBeforeComplete,
+ DuplicateSubscriptionIDClosesSocket,
+ ClientCompleteStopsSubscription,
+ ServerErrorTerminatesOperation,
+ IDReuseAfterOperationCompletes,
+ MultipleConcurrentSubscriptions,
+ OneSubscriptionErrorDoesNotAffectAnother,
+
+ // Disruption
+ BackendTCPDropDuringActiveSubscription,
+ BackendCloseFrameDuringActiveSubscription,
+ ClientTCPDropCleansUpBackendSubscription,
+ ClientCloseFrameCleansUpBackendSubscription,
+ BackendNeverAcksConnectionInitTimesOut,
+
+ // Headers and init payload
+ AllowlistedHeadersForwardedToBackend,
+ NonAllowlistedHeadersFilteredOut,
+ ConnectionInitPayloadForwardedToBackend,
+
+ // Multiplexing
+ MultipleSubscriptionsShareOneUpstreamConnection,
+ DifferentInitPayloadsGetSeparateUpstreamConnections,
+}
+
+// ExtractID parses the "id" field from a JSON message.
+func ExtractID(msg string) string {
+ return gjson.Get(msg, "id").String()
+}
+
+// ExtractType parses the "type" field from a JSON message.
+func ExtractType(msg string) string {
+ return gjson.Get(msg, "type").String()
+}
+
+// SubscribeRoundTrip verifies the full subscribe, next, complete lifecycle
+// through a proxy, including subscription ID remapping.
+var SubscribeRoundTrip = speedtrap.Scenario{
+ Name: "subscribe round-trip",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ // Client subscribes
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription($key: String){streamA(key: $key){key contents}}","variables":{"key":"test"}}}`))
+
+ // Backend receives forwarded subscribe (proxy may remap the ID)
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key contents}}","variables":{"key":"test"}}}`)
+ subID := ExtractID(msg)
+
+ // Backend sends next, client receives it with its original ID
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"next","payload":{"data":{"streamA":{"key":"test","contents":null}}}}`, subID)))
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"next","id":"1","payload":{"data":{"streamA":{"key":"test","contents":null}}}}`)
+
+ // Backend sends complete, client receives it
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"complete"}`, subID)))
+ msg, err = c.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"complete","id":"1"}`)
+ },
+}
+
+// DuplicateSubscriptionIDClosesSocket verifies that sending a subscribe with
+// an ID that is already active causes the server to close the socket with
+// 4409 per the graphql-transport-ws spec.
+var DuplicateSubscriptionIDClosesSocket = speedtrap.Scenario{
+ Name: "duplicate subscription ID closes socket with 4409",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ // First subscribe with id "1"
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription{streamA {key}}"}}`))
+
+ // Backend receives the forwarded subscribe
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription{streamA {key}}"}}`)
+
+ // Duplicate subscribe with same id "1"
+ require.NoError(s, c.Send(`{"id":"1","type":"subscribe","payload":{"query":"subscription{streamA {key}}"}}`))
+
+ // Per spec: server must close with 4409 "Subscriber for already exists"
+ cf, err := c.ReadControl()
+ require.NoError(s, err)
+ require.Equal(s, ws.OpClose, cf.OpCode)
+ code, reason := cf.CloseData()
+ require.Equal(s, ws.StatusCode(4409), code)
+ require.Equal(s, "Subscriber for 1 already exists", reason)
+ },
+}
diff --git a/speedtrap/scenarios/graphql/proxy/graphqlws/README.md b/speedtrap/scenarios/graphql/proxy/graphqlws/README.md
new file mode 100644
index 0000000000..ff2cc51735
--- /dev/null
+++ b/speedtrap/scenarios/graphql/proxy/graphqlws/README.md
@@ -0,0 +1,33 @@
+# graphql-ws (subscriptions-transport-ws) proxy scenarios
+
+Protocol: [subscriptions-transport-ws](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md) (subprotocol `graphql-ws`)
+
+These scenarios verify the router's behavior as a protocol-translating
+proxy. The client speaks the legacy `graphql-ws` protocol while the
+upstream subgraph speaks the modern `graphql-transport-ws` protocol.
+The router translates message types in both directions:
+
+- Client `start` becomes upstream `subscribe`
+- Client `stop` becomes upstream `complete`
+- Upstream `next` becomes client `data`
+- Upstream `error` becomes client `data` with `{"errors":[...]}` payload
+
+The router may interleave `ka` (keep-alive) messages at any time;
+scenarios use a `readSkippingKA` helper to drain them transparently.
+
+The test harness must register a backend named `"subgraph-a"`.
+
+## Connection phase (`connect.go`)
+
+| Scenario | Asserts |
+|-|-|
+| `ConnectionInitAndAck` | `connection_init` receives `connection_ack` with the legacy `graphql-ws` subprotocol |
+
+## Operation lifecycle (`lifecycle.go`)
+
+| Scenario | Asserts |
+|-|-|
+| `StartDataCompleteRoundTrip` | Full lifecycle: client `start` is translated to upstream `subscribe`, upstream `next` arrives as client `data`, upstream `complete` arrives as client `complete` |
+| `MultipleDataMessagesBeforeComplete` | Three upstream `next` messages arrive as three `data` messages on the client, in order |
+| `StopCancelsSubscription` | Client `stop` is translated to upstream `complete` with the remapped upstream ID |
+| `ServerErrorInDataPayload` | Upstream `error` is delivered to the client as a `data` message with `{"errors":[...]}` in the payload (per the subscriptions-transport-ws convention) |
diff --git a/speedtrap/scenarios/graphql/proxy/graphqlws/connect.go b/speedtrap/scenarios/graphql/proxy/graphqlws/connect.go
new file mode 100644
index 0000000000..4ed0e54ac7
--- /dev/null
+++ b/speedtrap/scenarios/graphql/proxy/graphqlws/connect.go
@@ -0,0 +1,96 @@
+package graphqlws
+
+import (
+ "github.com/gobwas/ws"
+ "github.com/stretchr/testify/require"
+ "github.com/wundergraph/cosmo/speedtrap"
+)
+
+// ConnectionInitAndAck verifies the basic connection_init → connection_ack
+// handshake for the legacy graphql-ws (subscriptions-transport-ws) protocol.
+var ConnectionInitAndAck = speedtrap.Scenario{
+ Name: "connection init and ack",
+ Run: func(s *speedtrap.S) {
+ c, err := s.Client(speedtrap.WithClientSubprotocol("graphql-ws"))
+ require.NoError(s, err)
+
+ require.NoError(s, c.Send(`{"type":"connection_init"}`))
+ msg, err := c.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_ack"}`, msg)
+ },
+}
+
+// DuplicateConnectionInitClosesSocket verifies that sending a second
+// connection_init after acknowledgment closes the connection with 4429. This
+// mirrors graphql-transport-ws behavior rather than the reference server which
+// silently re-acks. See PROTOCOL_AMENDMENTS.md.
+var DuplicateConnectionInitClosesSocket = speedtrap.Scenario{
+ Name: "duplicate connection init closes socket with 4429",
+ Run: func(s *speedtrap.S) {
+ c, err := s.Client(speedtrap.WithClientSubprotocol("graphql-ws"))
+ require.NoError(s, err)
+
+ require.NoError(s, c.Send(`{"type":"connection_init"}`))
+ msg, err := c.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_ack"}`, msg)
+
+ // Second init — server must close with 4429
+ require.NoError(s, c.Send(`{"type":"connection_init"}`))
+
+ cf, err := c.ReadControl()
+ require.NoError(s, err)
+ require.Equal(s, ws.OpClose, cf.OpCode)
+ code, reason := cf.CloseData()
+ require.Equal(s, ws.StatusCode(4429), code, "expected close code 4429, got %d", int(code))
+ require.Equal(s, "Too many initialisation requests", reason)
+ },
+}
+
+// SubscribeBeforeAckClosesSocket verifies that sending a start message before
+// the connection is acknowledged closes the connection with 4401. This mirrors
+// graphql-transport-ws behavior rather than the reference server which processes
+// the subscription without a handshake. See PROTOCOL_AMENDMENTS.md.
+var SubscribeBeforeAckClosesSocket = speedtrap.Scenario{
+ Name: "subscribe before connection ack closes socket with 4401",
+ Run: func(s *speedtrap.S) {
+ c, err := s.Client(speedtrap.WithClientSubprotocol("graphql-ws"))
+ require.NoError(s, err)
+
+ // Send start without connection_init — server must close with 4401
+ require.NoError(s, c.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"noack"}}}`))
+
+ cf, err := c.ReadControl()
+ require.NoError(s, err)
+ require.Equal(s, ws.OpClose, cf.OpCode)
+ code, _ := cf.CloseData()
+ require.Equal(s, ws.StatusCode(4401), code, "expected close code 4401, got %d", int(code))
+ },
+}
+
+// UnknownMessageTypeClosesSocket verifies that sending an unknown message type
+// closes the connection with 4400. This mirrors graphql-transport-ws behavior
+// rather than the reference server which returns an error message and keeps
+// the connection alive. See PROTOCOL_AMENDMENTS.md.
+var UnknownMessageTypeClosesSocket = speedtrap.Scenario{
+ Name: "unknown message type closes socket with 4400",
+ Run: func(s *speedtrap.S) {
+ c, err := s.Client(speedtrap.WithClientSubprotocol("graphql-ws"))
+ require.NoError(s, err)
+
+ require.NoError(s, c.Send(`{"type":"connection_init"}`))
+ msg, err := c.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_ack"}`, msg)
+
+ // Send a bogus message type — server must close with 4400
+ require.NoError(s, c.Send(`{"type":"bogus"}`))
+
+ cf, err := c.ReadControl()
+ require.NoError(s, err)
+ require.Equal(s, ws.OpClose, cf.OpCode)
+ code, _ := cf.CloseData()
+ require.Equal(s, ws.StatusCode(4400), code, "expected close code 4400, got %d", int(code))
+ },
+}
diff --git a/speedtrap/scenarios/graphql/proxy/graphqlws/disruption.go b/speedtrap/scenarios/graphql/proxy/graphqlws/disruption.go
new file mode 100644
index 0000000000..79dd2198c9
--- /dev/null
+++ b/speedtrap/scenarios/graphql/proxy/graphqlws/disruption.go
@@ -0,0 +1,142 @@
+package graphqlws
+
+import (
+ "fmt"
+
+ "github.com/kinbiko/jsonassert"
+ "github.com/stretchr/testify/require"
+ "github.com/wundergraph/cosmo/speedtrap"
+)
+
+// BackendTCPDropDuringActiveSubscription verifies that when the backend
+// forcibly drops TCP during an active subscription, the client receives an
+// error for the affected subscription.
+var BackendTCPDropDuringActiveSubscription = speedtrap.Scenario{
+ Name: "backend TCP drop during active subscription",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"drop"}}}`))
+
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"drop"}}}`)
+
+ // Forcibly close TCP — no close frame
+ require.NoError(s, b.Drop())
+
+ // Client must receive exactly one error from the upstream
+ msg = readSkippingKA(s, c)
+ ja.Assertf(msg, `{"type":"data","id":"1","payload":{"errors":[{"message":"upstream service error","extensions":{"code":"<>"}}]}}`)
+ },
+}
+
+// BackendCloseFrameDuringActiveSubscription verifies that when the backend
+// sends a close frame during an active subscription, the client receives an
+// error for the affected subscription.
+var BackendCloseFrameDuringActiveSubscription = speedtrap.Scenario{
+ Name: "backend close frame during active subscription",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"bclose"}}}`))
+
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"bclose"}}}`)
+
+ require.NoError(s, b.SendClose(1011, "internal error"))
+
+ // Client must receive exactly one error from the upstream with close info
+ msg = readSkippingKA(s, c)
+ ja.Assertf(msg, `{"type":"data","id":"1","payload":{"errors":[{"message":"upstream service error","extensions":{"code":"<>","closeCode":1011,"closeReason":"internal error"}}]}}`)
+ },
+}
+
+// ClientTCPDropCleansUpBackendSubscription verifies the proxy cleans up the
+// backend subscription when the client forcibly drops TCP.
+var ClientTCPDropCleansUpBackendSubscription = speedtrap.Scenario{
+ Name: "client TCP drop cleans up backend subscription",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"cdrop"}}}`))
+
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"cdrop"}}}`)
+ subID := extractID(msg)
+
+ require.NoError(s, c.Drop())
+
+ // Backend must receive complete for the active subscription
+ msg, err = b.Read()
+ if err != nil {
+ return // connection closed — acceptable
+ }
+ require.JSONEq(s, fmt.Sprintf(`{"type":"complete","id":"%s"}`, subID), msg)
+ },
+}
+
+// ClientCloseFrameCleansUpBackendSubscription verifies the proxy cleans up the
+// backend subscription when the client sends a close frame.
+var ClientCloseFrameCleansUpBackendSubscription = speedtrap.Scenario{
+ Name: "client close frame cleans up backend subscription",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"cclose"}}}`))
+
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"cclose"}}}`)
+ subID := extractID(msg)
+
+ require.NoError(s, c.SendClose(1000, "going away"))
+
+ // Backend must receive complete for the active subscription
+ msg, err = b.Read()
+ if err != nil {
+ return // connection closed — acceptable
+ }
+ require.JSONEq(s, fmt.Sprintf(`{"type":"complete","id":"%s"}`, subID), msg)
+ },
+}
+
+// BackendNeverAcksConnectionInitTimesOut verifies that when the backend accepts
+// the connection but never sends connection_ack, the client receives an error
+// for the pending subscribe.
+var BackendNeverAcksConnectionInitTimesOut = speedtrap.Scenario{
+ Name: "backend never acks connection init times out",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"noack"}}}`))
+
+ // Backend accepts but never sends connection_ack
+ b, err := s.Backend("subgraph-a").Accept()
+ require.NoError(s, err)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_init"}`, msg)
+ // Deliberately do NOT send connection_ack
+
+ // Client must receive an error for the pending subscribe
+ msg = readSkippingKA(s, c)
+ ja.Assertf(msg, `{"type":"data","id":"1","payload":{"errors":[{"message":"upstream service error","extensions":{"code":"<>"}}]}}`)
+ },
+}
diff --git a/speedtrap/scenarios/graphql/proxy/graphqlws/headers.go b/speedtrap/scenarios/graphql/proxy/graphqlws/headers.go
new file mode 100644
index 0000000000..32bea1ec87
--- /dev/null
+++ b/speedtrap/scenarios/graphql/proxy/graphqlws/headers.go
@@ -0,0 +1,139 @@
+package graphqlws
+
+import (
+ "fmt"
+ "net/http"
+
+ "github.com/kinbiko/jsonassert"
+ "github.com/stretchr/testify/require"
+ "github.com/wundergraph/cosmo/speedtrap"
+)
+
+// AllowlistedHeadersForwardedToBackend verifies that client upgrade headers
+// matching the router's header propagation rules are forwarded as HTTP headers
+// on the upstream WebSocket dial (legacy protocol variant).
+var AllowlistedHeadersForwardedToBackend = speedtrap.Scenario{
+ Name: "allowlisted headers forwarded to backend",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ headers := http.Header{
+ "Authorization": {"Bearer tok"},
+ "X-Custom-Trace": {"abc123"},
+ }
+ c, err := s.Client(
+ speedtrap.WithClientSubprotocol("graphql-ws"),
+ speedtrap.WithClientHeaders(headers),
+ )
+ require.NoError(s, err)
+ require.NoError(s, c.Send(`{"type":"connection_init"}`))
+ msg, err := c.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_ack"}`, msg)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"hdr"}}}`))
+
+ b, err := s.Backend("subgraph-a").Accept()
+ require.NoError(s, err)
+
+ require.Equal(s, "Bearer tok", b.UpgradeHeaders.Get("Authorization"))
+ require.Equal(s, "abc123", b.UpgradeHeaders.Get("X-Custom-Trace"))
+
+ msg, err = b.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_init"}`, msg)
+ require.NoError(s, b.Send(`{"type":"connection_ack"}`))
+
+ // Read the forwarded subscribe and complete the conversation
+ msg, err = b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"hdr"}}}`)
+ subID := extractID(msg)
+
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID)))
+ msg = readSkippingKA(s, c)
+ ja.Assertf(msg, `{"id":"1","type":"complete"}`)
+ },
+}
+
+// NonAllowlistedHeadersFilteredOut verifies that client upgrade headers NOT
+// matching the router's header propagation rules are stripped before the
+// upstream WebSocket dial (legacy protocol variant).
+var NonAllowlistedHeadersFilteredOut = speedtrap.Scenario{
+ Name: "non-allowlisted headers filtered out",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ headers := http.Header{
+ "Authorization": {"Bearer tok"},
+ "X-Secret-Internal": {"should-be-stripped"},
+ }
+ c, err := s.Client(
+ speedtrap.WithClientSubprotocol("graphql-ws"),
+ speedtrap.WithClientHeaders(headers),
+ )
+ require.NoError(s, err)
+ require.NoError(s, c.Send(`{"type":"connection_init"}`))
+ msg, err := c.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_ack"}`, msg)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"filter"}}}`))
+
+ b, err := s.Backend("subgraph-a").Accept()
+ require.NoError(s, err)
+
+ require.Equal(s, "Bearer tok", b.UpgradeHeaders.Get("Authorization"))
+ require.Empty(s, b.UpgradeHeaders.Get("X-Secret-Internal"))
+
+ msg, err = b.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_init"}`, msg)
+ require.NoError(s, b.Send(`{"type":"connection_ack"}`))
+
+ // Read the forwarded subscribe and complete the conversation
+ msg, err = b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"filter"}}}`)
+ subID := extractID(msg)
+
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID)))
+ msg = readSkippingKA(s, c)
+ ja.Assertf(msg, `{"id":"1","type":"complete"}`)
+ },
+}
+
+// ConnectionInitPayloadForwardedToBackend verifies that the connection_init
+// payload from the client is forwarded to the backend (legacy protocol variant).
+var ConnectionInitPayloadForwardedToBackend = speedtrap.Scenario{
+ Name: "connection init payload forwarded to backend",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c, err := s.Client(speedtrap.WithClientSubprotocol("graphql-ws"))
+ require.NoError(s, err)
+ require.NoError(s, c.Send(`{"type":"connection_init","payload":{"token":"abc"}}`))
+ msg, err := c.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_ack"}`, msg)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"init"}}}`))
+
+ b, err := s.Backend("subgraph-a").Accept()
+ require.NoError(s, err)
+ msg, err = b.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_init","payload":{"token":"abc"}}`, msg)
+ require.NoError(s, b.Send(`{"type":"connection_ack"}`))
+
+ // Read the forwarded subscribe and complete the conversation
+ msg, err = b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"init"}}}`)
+ subID := extractID(msg)
+
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID)))
+ msg = readSkippingKA(s, c)
+ ja.Assertf(msg, `{"id":"1","type":"complete"}`)
+ },
+}
diff --git a/speedtrap/scenarios/graphql/proxy/graphqlws/lifecycle.go b/speedtrap/scenarios/graphql/proxy/graphqlws/lifecycle.go
new file mode 100644
index 0000000000..8791335db7
--- /dev/null
+++ b/speedtrap/scenarios/graphql/proxy/graphqlws/lifecycle.go
@@ -0,0 +1,350 @@
+package graphqlws
+
+import (
+ "fmt"
+
+ "github.com/kinbiko/jsonassert"
+ "github.com/stretchr/testify/require"
+ "github.com/tidwall/gjson"
+ "github.com/wundergraph/cosmo/speedtrap"
+)
+
+// clientHandshake performs the legacy graphql-ws connection handshake.
+// It may also read and discard ka (keep-alive) messages that arrive
+// immediately after connection_ack.
+func clientHandshake(s *speedtrap.S) *speedtrap.ConnectionHandle {
+ c, err := s.Client(speedtrap.WithClientSubprotocol("graphql-ws"))
+ require.NoError(s, err)
+
+ require.NoError(s, c.Send(`{"type":"connection_init"}`))
+ msg, err := c.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_ack"}`, msg)
+
+ // The router may send a ka immediately after ack; drain it.
+ return c
+}
+
+// backendHandshake accepts a backend connection and completes the
+// graphql-transport-ws handshake (the router always speaks modern
+// protocol upstream).
+func backendHandshake(s *speedtrap.S) *speedtrap.ConnectionHandle {
+ b, err := s.Backend("subgraph-a").Accept()
+ require.NoError(s, err)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_init"}`, msg)
+ require.NoError(s, b.Send(`{"type":"connection_ack"}`))
+ return b
+}
+
+// readSkippingKA reads the next message from the client, skipping any
+// ka (keep-alive) messages that the router may interleave.
+func readSkippingKA(s *speedtrap.S, c *speedtrap.ConnectionHandle) string {
+ for {
+ msg, err := c.Read()
+ require.NoError(s, err)
+ if msg == `{"type":"ka"}` {
+ continue
+ }
+ return msg
+ }
+}
+
+// StartDataCompleteRoundTrip verifies the full start → data → complete
+// lifecycle through the proxy. The client speaks legacy graphql-ws while
+// the backend speaks graphql-transport-ws (the router translates).
+var StartDataCompleteRoundTrip = speedtrap.Scenario{
+ Name: "start data complete round-trip",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ // Client sends "start" (legacy subscribe)
+ require.NoError(s, c.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key contents}}","variables":{"key":"test"}}}`))
+
+ // Backend receives modern "subscribe" (router translates)
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key contents}}","variables":{"key":"test"}}}`)
+ subID := extractID(msg)
+
+ // Backend sends modern "next" → client receives legacy "data"
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"next","payload":{"data":{"streamA":{"key":"test","contents":null}}}}`, subID)))
+ msg = readSkippingKA(s, c)
+ ja.Assertf(msg, `{"id":"1","type":"data","payload":{"data":{"streamA":{"key":"test","contents":null}}}}`)
+
+ // Backend sends "complete" → client receives "complete"
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID)))
+ msg = readSkippingKA(s, c)
+ ja.Assertf(msg, `{"id":"1","type":"complete"}`)
+ },
+}
+
+// MultipleDataMessagesBeforeComplete verifies the proxy forwards multiple
+// data messages for a single subscription before the final complete.
+var MultipleDataMessagesBeforeComplete = speedtrap.Scenario{
+ Name: "multiple data messages before complete",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key contents}}","variables":{"key":"multi"}}}`))
+
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ subID := extractID(msg)
+
+ // Backend sends 3 next messages
+ for i := 1; i <= 3; i++ {
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"next","payload":{"data":{"streamA":{"key":"multi","contents":%d}}}}`, subID, i)))
+ }
+
+ // Client receives all 3 as "data" messages
+ for i := 1; i <= 3; i++ {
+ msg = readSkippingKA(s, c)
+ ja.Assertf(msg, `{"id":"1","type":"data","payload":{"data":{"streamA":{"key":"multi","contents":%d}}}}`, i)
+ }
+
+ // Complete
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID)))
+ msg = readSkippingKA(s, c)
+ ja.Assertf(msg, `{"id":"1","type":"complete"}`)
+ },
+}
+
+// StopCancelsSubscription verifies that the client sending a "stop" message
+// causes the proxy to forward a "complete" to the upstream backend.
+var StopCancelsSubscription = speedtrap.Scenario{
+ Name: "stop cancels upstream subscription",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"stop"}}}`))
+
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"stop"}}}`)
+ subID := extractID(msg)
+
+ // Client sends "stop" (legacy complete)
+ require.NoError(s, c.Send(`{"id":"1","type":"stop"}`))
+
+ // Backend should receive a "complete" with remapped ID
+ msg, err = b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"complete","id":"%s"}`, subID)
+ },
+}
+
+// ServerErrorInDataPayload verifies that when the backend sends a terminal
+// error, the router delivers it to the legacy client as a "data" message with
+// errors in the payload followed by a "complete" frame. subscriptions-transport-ws
+// reserves "error" for pre-execution failures, so terminal runtime errors are
+// expressed as data+errors plus a terminal complete.
+var ServerErrorInDataPayload = speedtrap.Scenario{
+ Name: "server error delivered in data payload",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"err"}}}`))
+
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ subID := extractID(msg)
+
+ // Backend sends terminal error (modern protocol)
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"error","payload":[{"message":"something went wrong"}]}`, subID)))
+
+ msg = readSkippingKA(s, c)
+ ja.Assertf(msg, `{"id":"1","type":"data","payload":{"errors":[{"message":"something went wrong"}]}}`)
+
+ msg = readSkippingKA(s, c)
+ ja.Assertf(msg, `{"id":"1","type":"complete"}`)
+ },
+}
+
+// MultipleConcurrentSubscriptions verifies that the proxy correctly handles
+// multiple active subscriptions on a single legacy graphql-ws connection.
+var MultipleConcurrentSubscriptions = speedtrap.Scenario{
+ Name: "multiple concurrent subscriptions on one connection",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ // Start subscription 1
+ require.NoError(s, c.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"a"}}}`))
+
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ subID1 := extractID(msg)
+
+ // Start subscription 2
+ require.NoError(s, c.Send(`{"id":"2","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"b"}}}`))
+
+ // Proxy must multiplex onto the same upstream connection
+ _, err = s.Backend("subgraph-a").TryAccept()
+ require.Error(s, err, "expected no second upstream connection (multiplexing)")
+
+ msg, err = b.Read()
+ require.NoError(s, err)
+ subID2 := extractID(msg)
+
+ // Backend sends next for both subscriptions
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"next","payload":{"data":{"streamA":{"key":"a"}}}}`, subID1)))
+ msg = readSkippingKA(s, c)
+ ja.Assertf(msg, `{"id":"1","type":"data","payload":{"data":{"streamA":{"key":"a"}}}}`)
+
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"next","payload":{"data":{"streamA":{"key":"b"}}}}`, subID2)))
+ msg = readSkippingKA(s, c)
+ ja.Assertf(msg, `{"id":"2","type":"data","payload":{"data":{"streamA":{"key":"b"}}}}`)
+
+ // Complete both
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID1)))
+ msg = readSkippingKA(s, c)
+ ja.Assertf(msg, `{"id":"1","type":"complete"}`)
+
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID2)))
+ msg = readSkippingKA(s, c)
+ ja.Assertf(msg, `{"id":"2","type":"complete"}`)
+ },
+}
+
+// OneSubscriptionErrorDoesNotAffectAnother verifies that an error on one
+// subscription does not disrupt a concurrent subscription on the same connection.
+var OneSubscriptionErrorDoesNotAffectAnother = speedtrap.Scenario{
+ Name: "one subscription error does not affect another",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ // Two concurrent subscriptions
+ require.NoError(s, c.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"err1"}}}`))
+ require.NoError(s, c.Send(`{"id":"2","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"err2"}}}`))
+
+ b := backendHandshake(s)
+
+ // Read both subscribes (order is non-deterministic)
+ var subID1, subID2 string
+ varKey := func(msg string) string { return gjson.Get(msg, "payload.variables.key").String() }
+ speedtrap.ReadSwitch(s, b.Messages(), varKey,
+ speedtrap.Case("err1", func(msg string) { subID1 = extractID(msg) }),
+ speedtrap.Case("err2", func(msg string) { subID2 = extractID(msg) }),
+ )
+
+ // Proxy must multiplex onto the same upstream connection
+ _, err := s.Backend("subgraph-a").TryAccept()
+ require.Error(s, err, "expected no second upstream connection (multiplexing)")
+
+ // Error on subscription 1
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"error","payload":[{"message":"sub1 failed"}]}`, subID1)))
+
+ // Next on subscription 2 — should still work
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"next","payload":{"data":{"streamA":{"key":"err2"}}}}`, subID2)))
+
+ // Client receives terminal error for "1" (data+errors then complete) and
+ // data for "2" (unordered, interspersed with possible ka messages).
+ isKA := func(msg string) bool { return msg == `{"type":"ka"}` }
+ idType := func(msg string) string { return extractID(msg) + ":" + extractType(msg) }
+ speedtrap.ReadSwitch(s, speedtrap.Filter(c.Messages(), isKA), idType,
+ speedtrap.Case("1:data", func(msg string) {
+ ja.Assertf(msg, `{"id":"1","type":"data","payload":{"errors":[{"message":"sub1 failed"}]}}`)
+ }),
+ speedtrap.Case("1:complete", func(msg string) {
+ ja.Assertf(msg, `{"id":"1","type":"complete"}`)
+ }),
+ speedtrap.Case("2:data", func(msg string) {
+ ja.Assertf(msg, `{"id":"2","type":"data","payload":{"data":{"streamA":{"key":"err2"}}}}`)
+ }),
+ )
+
+ // Complete subscription 2
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID2)))
+
+ msg := readSkippingKA(s, c)
+ ja.Assertf(msg, `{"id":"2","type":"complete"}`)
+ },
+}
+
+// DuplicateStartIDClosesSocket verifies that sending a "start" with an ID that
+// is already active causes the server to close the connection.
+//
+// NOTE: This diverges from the subscriptions-transport-ws reference server
+// (v0.11.0), which silently completes the existing subscription and starts a
+// new one with the same ID (replace semantics). We intentionally treat
+// duplicate IDs as an error to match the graphql-transport-ws behavior (close
+// with 4409) and avoid the complexity of implicit replacement.
+var DuplicateStartIDClosesSocket = speedtrap.Scenario{
+ Name: "duplicate start ID closes socket",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ // Start subscription with id "1"
+ require.NoError(s, c.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"dup"}}}`))
+
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"dup"}}}`)
+
+ // Duplicate start with same id "1"
+ require.NoError(s, c.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"dup"}}}`))
+
+ // Connection should be closed
+ _, err = c.Read()
+ require.Error(s, err, "expected connection to be closed after duplicate start ID")
+ },
+}
+
+// ConnectionTerminateCleansUp verifies that sending connection_terminate causes
+// the proxy to clean up backend subscriptions and close the connection.
+var ConnectionTerminateCleansUp = speedtrap.Scenario{
+ Name: "connection terminate cleans up",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ require.NoError(s, c.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"term"}}}`))
+
+ b := backendHandshake(s)
+ msg, err := b.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"term"}}}`)
+ subID := extractID(msg)
+
+ // Client sends connection_terminate
+ require.NoError(s, c.Send(`{"type":"connection_terminate"}`))
+
+ // Backend receives a complete for the active subscription
+ msg, err = b.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, fmt.Sprintf(`{"type":"complete","id":"%s"}`, subID), msg)
+
+ // Client connection is closed
+ _, err = c.Read()
+ require.Error(s, err, "expected client connection to be closed after connection_terminate")
+ },
+}
diff --git a/speedtrap/scenarios/graphql/proxy/graphqlws/multiplex.go b/speedtrap/scenarios/graphql/proxy/graphqlws/multiplex.go
new file mode 100644
index 0000000000..503bfa5a8f
--- /dev/null
+++ b/speedtrap/scenarios/graphql/proxy/graphqlws/multiplex.go
@@ -0,0 +1,140 @@
+package graphqlws
+
+import (
+ "fmt"
+
+ "github.com/kinbiko/jsonassert"
+ "github.com/stretchr/testify/require"
+ "github.com/tidwall/gjson"
+ "github.com/wundergraph/cosmo/speedtrap"
+)
+
+// MultipleSubscriptionsShareOneUpstreamConnection verifies that the proxy
+// multiplexes multiple subscriptions from a single client connection onto one
+// upstream backend connection (legacy protocol variant).
+var MultipleSubscriptionsShareOneUpstreamConnection = speedtrap.Scenario{
+ Name: "multiple subscriptions share one upstream connection",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ c := clientHandshake(s)
+
+ // Two starts on the same connection
+ require.NoError(s, c.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"mux1"}}}`))
+ require.NoError(s, c.Send(`{"id":"2","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"mux2"}}}`))
+
+ // First backend connection
+ b := backendHandshake(s)
+
+ // Read both subscribes (order is non-deterministic)
+ var subIDMux1, subIDMux2 string
+ varKey := func(msg string) string { return gjson.Get(msg, "payload.variables.key").String() }
+ speedtrap.ReadSwitch(s, b.Messages(), varKey,
+ speedtrap.Case("mux1", func(msg string) {
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"mux1"}}}`)
+ subIDMux1 = extractID(msg)
+ }),
+ speedtrap.Case("mux2", func(msg string) {
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"mux2"}}}`)
+ subIDMux2 = extractID(msg)
+ }),
+ )
+
+ // Try to accept a second connection — should fail (multiplexed)
+ _, err := s.Backend("subgraph-a").TryAccept()
+ require.Error(s, err, "expected no second upstream connection (multiplexing)")
+
+ // Send next for mux1, verify client receives it with client ID "1"
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"next","payload":{"data":{"streamA":{"key":"mux1"}}}}`, subIDMux1)))
+ msg := readSkippingKA(s, c)
+ ja.Assertf(msg, `{"id":"1","type":"data","payload":{"data":{"streamA":{"key":"mux1"}}}}`)
+
+ // Send next for mux2, verify client receives it with client ID "2"
+ require.NoError(s, b.Send(fmt.Sprintf(
+ `{"id":"%s","type":"next","payload":{"data":{"streamA":{"key":"mux2"}}}}`, subIDMux2)))
+ msg = readSkippingKA(s, c)
+ ja.Assertf(msg, `{"id":"2","type":"data","payload":{"data":{"streamA":{"key":"mux2"}}}}`)
+
+ // Complete mux1
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subIDMux1)))
+ msg = readSkippingKA(s, c)
+ ja.Assertf(msg, `{"id":"1","type":"complete"}`)
+
+ // Complete mux2
+ require.NoError(s, b.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subIDMux2)))
+ msg = readSkippingKA(s, c)
+ ja.Assertf(msg, `{"id":"2","type":"complete"}`)
+ },
+}
+
+// DifferentInitPayloadsGetSeparateUpstreamConnections verifies that two client
+// connections with different connection_init payloads result in separate upstream
+// connections (legacy protocol variant).
+var DifferentInitPayloadsGetSeparateUpstreamConnections = speedtrap.Scenario{
+ Name: "different init payloads get separate upstream connections",
+ Run: func(s *speedtrap.S) {
+ ja := jsonassert.New(s)
+
+ // Client 1 with token "aaa"
+ c1, err := s.Client(speedtrap.WithClientSubprotocol("graphql-ws"))
+ require.NoError(s, err)
+ require.NoError(s, c1.Send(`{"type":"connection_init","payload":{"token":"aaa"}}`))
+ msg, err := c1.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_ack"}`, msg)
+
+ require.NoError(s, c1.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"sep1"}}}`))
+
+ // Client 2 with token "bbb"
+ c2, err := s.Client(speedtrap.WithClientSubprotocol("graphql-ws"))
+ require.NoError(s, err)
+ require.NoError(s, c2.Send(`{"type":"connection_init","payload":{"token":"bbb"}}`))
+ msg, err = c2.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"connection_ack"}`, msg)
+
+ require.NoError(s, c2.Send(`{"id":"1","type":"start","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"sep2"}}}`))
+
+ // Two separate backend connections expected — accept order is non-deterministic
+ conns := make([]*speedtrap.ConnectionHandle, 2)
+ for i := range conns {
+ conns[i], err = s.Backend("subgraph-a").Accept()
+ require.NoError(s, err)
+ }
+
+ var b1, b2 *speedtrap.ConnectionHandle
+ token := func(t speedtrap.Tagged) string { return gjson.Get(t.Msg, "payload.token").String() }
+ speedtrap.ReadSwitch(s, speedtrap.MergeMessages(conns...), token,
+ speedtrap.Case("aaa", func(t speedtrap.Tagged) {
+ require.JSONEq(s, `{"type":"connection_init","payload":{"token":"aaa"}}`, t.Msg)
+ require.NoError(s, t.Conn.Send(`{"type":"connection_ack"}`))
+ b1 = t.Conn
+ }),
+ speedtrap.Case("bbb", func(t speedtrap.Tagged) {
+ require.JSONEq(s, `{"type":"connection_init","payload":{"token":"bbb"}}`, t.Msg)
+ require.NoError(s, t.Conn.Send(`{"type":"connection_ack"}`))
+ b2 = t.Conn
+ }),
+ )
+
+ // Read forwarded subscribes and complete both conversations
+ msg, err = b1.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"sep1"}}}`)
+ subID1 := extractID(msg)
+
+ msg, err = b2.Read()
+ require.NoError(s, err)
+ ja.Assertf(msg, `{"type":"subscribe","id":"<>","payload":{"query":"subscription($key: String){streamA(key: $key){key}}","variables":{"key":"sep2"}}}`)
+ subID2 := extractID(msg)
+
+ require.NoError(s, b1.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID1)))
+ msg = readSkippingKA(s, c1)
+ ja.Assertf(msg, `{"id":"1","type":"complete"}`)
+
+ require.NoError(s, b2.Send(fmt.Sprintf(`{"id":"%s","type":"complete"}`, subID2)))
+ msg = readSkippingKA(s, c2)
+ ja.Assertf(msg, `{"id":"1","type":"complete"}`)
+ },
+}
diff --git a/speedtrap/scenarios/graphql/proxy/graphqlws/scenarios.go b/speedtrap/scenarios/graphql/proxy/graphqlws/scenarios.go
new file mode 100644
index 0000000000..fbc86cac72
--- /dev/null
+++ b/speedtrap/scenarios/graphql/proxy/graphqlws/scenarios.go
@@ -0,0 +1,53 @@
+package graphqlws
+
+import (
+ "github.com/tidwall/gjson"
+ "github.com/wundergraph/cosmo/speedtrap"
+)
+
+// Scenarios contains all subscriptions-transport-ws ("graphql-ws" subprotocol)
+// proxy scenarios. The test harness must register a backend named "subgraph-a"
+// that speaks graphql-transport-ws (the router translates between protocols).
+var Scenarios = []speedtrap.Scenario{
+ // Connection phase
+ ConnectionInitAndAck,
+ DuplicateConnectionInitClosesSocket,
+ SubscribeBeforeAckClosesSocket,
+ UnknownMessageTypeClosesSocket,
+
+ // Operation lifecycle
+ StartDataCompleteRoundTrip,
+ MultipleDataMessagesBeforeComplete,
+ StopCancelsSubscription,
+ ServerErrorInDataPayload,
+ MultipleConcurrentSubscriptions,
+ OneSubscriptionErrorDoesNotAffectAnother,
+ DuplicateStartIDClosesSocket,
+ ConnectionTerminateCleansUp,
+
+ // Disruption
+ BackendTCPDropDuringActiveSubscription,
+ BackendCloseFrameDuringActiveSubscription,
+ ClientTCPDropCleansUpBackendSubscription,
+ ClientCloseFrameCleansUpBackendSubscription,
+ BackendNeverAcksConnectionInitTimesOut,
+
+ // Headers and init payload
+ AllowlistedHeadersForwardedToBackend,
+ NonAllowlistedHeadersFilteredOut,
+ ConnectionInitPayloadForwardedToBackend,
+
+ // Multiplexing
+ MultipleSubscriptionsShareOneUpstreamConnection,
+ DifferentInitPayloadsGetSeparateUpstreamConnections,
+}
+
+// extractID parses the "id" field from a JSON message.
+func extractID(msg string) string {
+ return gjson.Get(msg, "id").String()
+}
+
+// extractType parses the "type" field from a JSON message.
+func extractType(msg string) string {
+ return gjson.Get(msg, "type").String()
+}
diff --git a/speedtrap/scenarios/graphql/subgraph-a.graphqls b/speedtrap/scenarios/graphql/subgraph-a.graphqls
new file mode 100644
index 0000000000..2ea06124b0
--- /dev/null
+++ b/speedtrap/scenarios/graphql/subgraph-a.graphqls
@@ -0,0 +1,20 @@
+extend schema
+ @link(
+ url: "https://specs.apollo.dev/federation/v2.5"
+ import: ["@shareable"]
+ )
+
+type Query {
+ _empty: Boolean @shareable
+}
+
+scalar JSON
+
+type Subscription {
+ streamA(key: String): StreamEvent
+}
+
+type StreamEvent @shareable {
+ key: String
+ contents: JSON
+}
diff --git a/speedtrap/scenarios/graphql/subgraph-b.graphqls b/speedtrap/scenarios/graphql/subgraph-b.graphqls
new file mode 100644
index 0000000000..986f931fd7
--- /dev/null
+++ b/speedtrap/scenarios/graphql/subgraph-b.graphqls
@@ -0,0 +1,20 @@
+extend schema
+ @link(
+ url: "https://specs.apollo.dev/federation/v2.5"
+ import: ["@shareable"]
+ )
+
+type Query {
+ _empty: Boolean @shareable
+}
+
+scalar JSON
+
+type Subscription {
+ streamB(key: String): StreamEvent
+}
+
+type StreamEvent @shareable {
+ key: String
+ contents: JSON
+}
diff --git a/speedtrap/scenarios_test.go b/speedtrap/scenarios_test.go
new file mode 100644
index 0000000000..0a011b0183
--- /dev/null
+++ b/speedtrap/scenarios_test.go
@@ -0,0 +1,261 @@
+package speedtrap
+
+import (
+ "net/http"
+ "testing"
+
+ "github.com/gobwas/ws"
+ "github.com/kinbiko/jsonassert"
+ "github.com/stretchr/testify/require"
+)
+
+const testSubprotocol = "test"
+
+// directConfig returns a HarnessConfig that points the client directly at a
+// standalone backend (no proxy). The backend address is used as ProxyAddr so
+// that t.Client dials the backend's listener.
+func directConfig(t *testing.T) (HarnessConfig, *Backend) {
+ t.Helper()
+ b, err := StartBackend(WithSubprotocol(testSubprotocol))
+ require.NoError(t, err)
+ t.Cleanup(b.Stop)
+
+ cfg := HarnessConfig{
+ TargetAddr: "ws://" + b.Addr(),
+ Backends: map[string]*Backend{
+ "default": b,
+ },
+ }
+ return cfg, b
+}
+
+func TestRunScenario(t *testing.T) {
+ t.Run("relays messages in both directions", func(t *testing.T) {
+ cfg, _ := directConfig(t)
+
+ RequireScenario(t, cfg, Scenario{
+ Name: "message relay",
+ Run: func(st *S) {
+ c, err := st.Client(WithClientSubprotocol(testSubprotocol))
+ require.NoError(st, err, "dial")
+
+ b, err := st.Backend("default").Accept()
+ require.NoError(st, err, "accept")
+
+ // Send message from client to backend
+ require.NoError(st, c.Send("ping"))
+
+ // Expect to receive it
+ msg, err := b.Read()
+ require.NoError(st, err, "read")
+ require.Equal(st, "ping", msg)
+
+ // Send message from backend to client
+ require.NoError(st, b.Send("pong"))
+
+ // Expect to receive it
+ msg, err = c.Read()
+ require.NoError(st, err, "read")
+ require.Equal(st, "pong", msg)
+ },
+ })
+ })
+
+ t.Run("delivers close code from client to backend", func(t *testing.T) {
+ cfg, _ := directConfig(t)
+
+ RequireScenario(t, cfg, Scenario{
+ Name: "client to backend close",
+ Run: func(st *S) {
+ c, err := st.Client(WithClientSubprotocol(testSubprotocol))
+ require.NoError(st, err, "dial")
+
+ b, err := st.Backend("default").Accept()
+ require.NoError(st, err, "accept")
+
+ require.NoError(st, c.SendClose(4999, "goodbye"))
+
+ cf, err := b.ReadControl()
+ require.NoError(st, err)
+ require.Equal(st, ws.OpClose, cf.OpCode)
+
+ code, reason := cf.CloseData()
+ require.Equal(st, ws.StatusCode(4999), code)
+ require.Equal(st, "goodbye", reason)
+ },
+ })
+ })
+
+ t.Run("delivers close code from backend to client", func(t *testing.T) {
+ cfg, _ := directConfig(t)
+
+ RequireScenario(t, cfg, Scenario{
+ Name: "backend to client close",
+ Run: func(st *S) {
+ c, err := st.Client(WithClientSubprotocol(testSubprotocol))
+ require.NoError(st, err, "dial")
+
+ b, err := st.Backend("default").Accept()
+ require.NoError(st, err, "accept")
+
+ require.NoError(st, b.SendClose(4999, "goodbye"))
+
+ cf, err := c.ReadControl()
+ require.NoError(st, err)
+ require.Equal(st, ws.OpClose, cf.OpCode)
+
+ code, reason := cf.CloseData()
+ require.Equal(st, ws.StatusCode(4999), code)
+ require.Equal(st, "goodbye", reason)
+ },
+ })
+ })
+
+ t.Run("client handshake captures negotiated subprotocol", func(t *testing.T) {
+ cfg, _ := directConfig(t)
+
+ RequireScenario(t, cfg, Scenario{
+ Name: "client handshake",
+ Run: func(st *S) {
+ c, err := st.Client(WithClientSubprotocol(testSubprotocol))
+ require.NoError(st, err, "dial")
+ require.Equal(st, testSubprotocol, c.Handshake.Protocol)
+
+ b, err := st.Backend("default").Accept()
+ require.NoError(st, err, "accept")
+ require.Equal(st, testSubprotocol, b.Handshake.Protocol)
+ },
+ })
+ })
+
+ t.Run("accepts client with no subprotocol when backend requires one", func(t *testing.T) {
+ cfg, _ := directConfig(t)
+
+ RequireScenario(t, cfg, Scenario{
+ Name: "no subprotocol offered",
+ Run: func(st *S) {
+ c, err := st.Client()
+ require.NoError(st, err, "dial")
+ require.Empty(st, c.Handshake.Protocol)
+
+ b, err := st.Backend("default").Accept()
+ require.NoError(st, err, "accept")
+ require.Empty(st, b.Handshake.Protocol)
+ },
+ })
+ })
+
+ t.Run("backend handle captures upgrade headers", func(t *testing.T) {
+ cfg, _ := directConfig(t)
+
+ RequireScenario(t, cfg, Scenario{
+ Name: "backend upgrade headers",
+ Run: func(st *S) {
+ _, err := st.Client(
+ WithClientSubprotocol(testSubprotocol),
+ WithClientHeaders(http.Header{"X-Request-Id": {"abc-123"}}),
+ )
+ require.NoError(st, err, "dial")
+
+ b, err := st.Backend("default").Accept()
+ require.NoError(st, err, "accept")
+ require.Equal(st, "abc-123", b.UpgradeHeaders.Get("X-Request-Id"))
+ },
+ })
+ })
+
+ t.Run("continues execution after non-fatal fail", func(t *testing.T) {
+ cfg, _ := directConfig(t)
+
+ canary := false
+ result := RunScenario(cfg, Scenario{
+ Name: "non-fatal failure",
+ Run: func(st *S) {
+ st.Error("something went wrong")
+ canary = true
+ },
+ })
+
+ require.False(t, result.Passed)
+ require.True(t, canary, "expected execution to continue after Fail")
+ require.Len(t, result.Failures, 1)
+ require.False(t, result.Failures[0].Fatal, "expected non-fatal failure")
+ })
+
+ t.Run("stops execution on fatal", func(t *testing.T) {
+ cfg, _ := directConfig(t)
+
+ canary := false
+ result := RunScenario(cfg, Scenario{
+ Name: "fatal stops execution",
+ Run: func(st *S) {
+ st.Fatal("critical error")
+ canary = true
+ },
+ })
+
+ require.False(t, result.Passed)
+ require.False(t, canary, "expected execution to stop after Fatal")
+ require.Len(t, result.Failures, 1)
+ require.True(t, result.Failures[0].Fatal, "expected fatal failure")
+ })
+
+ t.Run("records formatted message from errorf", func(t *testing.T) {
+ cfg, _ := directConfig(t)
+
+ result := RunScenario(cfg, Scenario{
+ Name: "errorf formatting",
+ Run: func(st *S) {
+ st.Errorf("got %d, want %d", 1, 2)
+ },
+ })
+
+ require.False(t, result.Passed)
+ require.Len(t, result.Failures, 1)
+ require.Equal(t, "got 1, want 2", result.Failures[0].Message)
+ })
+
+ t.Run("stops execution on fatalf", func(t *testing.T) {
+ cfg, _ := directConfig(t)
+
+ canary := false
+ result := RunScenario(cfg, Scenario{
+ Name: "fatalf stops execution",
+ Run: func(st *S) {
+ st.Fatalf("code %d: %s", 500, "internal error")
+ canary = true
+ },
+ })
+
+ require.False(t, result.Passed)
+ require.False(t, canary, "expected execution to stop after Fatalf")
+ require.Equal(t, "code 500: internal error", result.Failures[0].Message)
+ require.True(t, result.Failures[0].Fatal, "expected fatal failure")
+ })
+
+ t.Run("passes when matchers succeed", func(t *testing.T) {
+ cfg, _ := directConfig(t)
+
+ RequireScenario(t, cfg, Scenario{
+ Name: "matchers work",
+ Run: func(s *S) {
+ c, err := s.Client(WithClientSubprotocol(testSubprotocol))
+ require.NoError(s, err, "dial")
+ b, err := s.Backend("default").Accept()
+ require.NoError(s, err, "accept")
+
+ require.NoError(s, c.Send(`{"type":"subscribe","id":"1","payload":{"query":"{ hello }"}}`))
+
+ msg, err := b.Read()
+ require.NoError(s, err)
+ jsonassert.New(s).Assertf(msg, `{"type":"subscribe","id":"1","payload":"<>"}`)
+
+ require.NoError(s, b.Send(`{"type":"next","id":"1","payload":{"data":{"hello":"world"}}}`))
+
+ msg, err = c.Read()
+ require.NoError(s, err)
+ require.JSONEq(s, `{"type":"next","id":"1","payload":{"data":{"hello":"world"}}}`, msg)
+ },
+ })
+ })
+}