From b79a8095c2914e3546b27f1be23a81f23ad1aac5 Mon Sep 17 00:00:00 2001 From: Jens Neuse Date: Wed, 18 Feb 2026 19:40:57 +0100 Subject: [PATCH 1/4] fix(introspection): resolve ofType.fields returning null (#991) The introspection data model uses two Go types: FullType (rich, with fields/description/etc.) and TypeRef (sparse, only kind/name/ofType). When a query navigates ofType { fields { name } }, the JSON had no fields key and the resolver returned null. Build self-contained JSON directly from Go structs using astjson, resolving each TypeRef to its full type data on the fly. Self-referencing types are handled by a visited set per DFS path to break cycles. Pre-computed once at startup for Source.Load to return. Co-Authored-By: Claude Opus 4.6 --- .../engine/federation_integration_test.go | 10 + .../queries/introspection_oftype_fields.query | 20 + .../config_factory.go | 4 + .../comprehensive_config_input.golden | 75 + .../fixtures/comprehensive_node.golden | 230 + .../fixtures/comprehensive_review.golden | 230 + .../fixtures/comprehensive_schema.golden | 4288 +++++++++++++++++ .../comprehensive_search_result.golden | 472 ++ .../fixtures/comprehensive_user.golden | 230 + .../fixtures/oftype_mutation.golden | 135 + .../fixtures/oftype_schema.golden | 769 +++ .../fixtures/oftype_user.golden | 86 + .../fixtures/schema_introspection.golden | 166 +- ...on_with_custom_root_operation_types.golden | 252 +- .../fixtures/type_introspection.golden | 68 +- .../introspection_datasource/source.go | 31 +- .../introspection_datasource/source_test.go | 153 +- v2/pkg/introspection/enrich.go | 251 + v2/pkg/introspection/introspection.go | 39 +- 19 files changed, 7440 insertions(+), 69 deletions(-) create mode 100644 execution/federationtesting/testdata/queries/introspection_oftype_fields.query create mode 100644 v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_config_input.golden create mode 100644 v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_node.golden create mode 100644 v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_review.golden create mode 100644 v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_schema.golden create mode 100644 v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_search_result.golden create mode 100644 v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_user.golden create mode 100644 v2/pkg/engine/datasource/introspection_datasource/fixtures/oftype_mutation.golden create mode 100644 v2/pkg/engine/datasource/introspection_datasource/fixtures/oftype_schema.golden create mode 100644 v2/pkg/engine/datasource/introspection_datasource/fixtures/oftype_user.golden create mode 100644 v2/pkg/introspection/enrich.go diff --git a/execution/engine/federation_integration_test.go b/execution/engine/federation_integration_test.go index 9b749cda2b..85655064a1 100644 --- a/execution/engine/federation_integration_test.go +++ b/execution/engine/federation_integration_test.go @@ -507,6 +507,16 @@ func TestFederationIntegrationTest(t *testing.T) { expected := `{"data":{"cat":{"name":"Pepper"},"me":{"id":"1234","username":"Me","realName":"User Usington","reviews":[{"body":"A highly effective form of birth control."},{"body":"Fedoras are one of the most fashionable hats around and can look great with a variety of outfits."}],"history":[{},{"rating":5},{}]}}}` assert.Equal(t, compact(expected), string(resp)) }) + + // Regression test for https://github.com/wundergraph/cosmo/issues/991 + t.Run("introspection ofType returns fields", func(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(cancel) + resp := gqlClient.Query(ctx, setup.GatewayServer.URL, testQueryPath("queries/introspection_oftype_fields.query"), nil, t) + expected := `{"data":{"__type":{"name":"User","kind":"OBJECT","fields":[{"name":"id","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","fields":null}}},{"name":"username","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","fields":null}}},{"name":"history","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"fields":null}}},{"name":"realName","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","fields":null}}},{"name":"reviews","type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Review","fields":[{"name":"body"},{"name":"author"},{"name":"product"},{"name":"attachments"},{"name":"comment"}]}}}]}}}` + assert.Equal(t, compact(expected), string(resp)) + }) } func compact(input string) string { diff --git a/execution/federationtesting/testdata/queries/introspection_oftype_fields.query b/execution/federationtesting/testdata/queries/introspection_oftype_fields.query new file mode 100644 index 0000000000..f867d8bc3d --- /dev/null +++ b/execution/federationtesting/testdata/queries/introspection_oftype_fields.query @@ -0,0 +1,20 @@ +{ + __type(name: "User") { + name + kind + fields { + name + type { + kind + name + ofType { + kind + name + fields { + name + } + } + } + } + } +} \ No newline at end of file diff --git a/v2/pkg/engine/datasource/introspection_datasource/config_factory.go b/v2/pkg/engine/datasource/introspection_datasource/config_factory.go index 0952d3f62f..7cc0917fcf 100644 --- a/v2/pkg/engine/datasource/introspection_datasource/config_factory.go +++ b/v2/pkg/engine/datasource/introspection_datasource/config_factory.go @@ -23,6 +23,10 @@ func NewIntrospectionConfigFactory(schema *ast.Document) (*IntrospectionConfigFa return nil, report } + if err := data.Schema.BuildJSON(); err != nil { + return nil, err + } + return &IntrospectionConfigFactory{introspectionData: &data}, nil } diff --git a/v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_config_input.golden b/v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_config_input.golden new file mode 100644 index 0000000000..97b1325dfb --- /dev/null +++ b/v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_config_input.golden @@ -0,0 +1,75 @@ +{ + "kind": "INPUT_OBJECT", + "name": "ConfigInput", + "description": "", + "inputFields": [ + { + "name": "key", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + }, + { + "name": "nested", + "description": "", + "type": { + "kind": "INPUT_OBJECT", + "name": "NestedInput", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [ + { + "name": "value", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null, + "__typename": "__Type", + "description": "The 'Int' scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "interfaces": [], + "possibleTypes": [] + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" +} \ No newline at end of file diff --git a/v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_node.golden b/v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_node.golden new file mode 100644 index 0000000000..f19221e4ba --- /dev/null +++ b/v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_node.golden @@ -0,0 +1,230 @@ +{ + "kind": "INTERFACE", + "name": "Node", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "reviews", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "body", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "author", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type" + } + ], + "possibleTypes": [] + } + ], + "__typename": "__Type" +} \ No newline at end of file diff --git a/v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_review.golden b/v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_review.golden new file mode 100644 index 0000000000..ef9103321f --- /dev/null +++ b/v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_review.golden @@ -0,0 +1,230 @@ +{ + "kind": "OBJECT", + "name": "Review", + "description": "", + "fields": [ + { + "name": "body", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "author", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "reviews", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + } + ] + } + ], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" +} \ No newline at end of file diff --git a/v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_schema.golden b/v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_schema.golden new file mode 100644 index 0000000000..3bd25edc98 --- /dev/null +++ b/v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_schema.golden @@ -0,0 +1,4288 @@ +{ + "queryType": { + "kind": "OBJECT", + "name": "Query", + "description": "", + "fields": [ + { + "name": "user", + "description": "", + "args": [], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "reviews", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "body", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "author", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + } + ] + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "search", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "UNION", + "name": "SearchResult", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "reviews", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "body", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "author", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + } + ] + } + ], + "possibleTypes": [] + }, + { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "body", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "author", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "reviews", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + } + ] + } + ], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + } + ] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "node", + "description": "", + "args": [], + "type": { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "reviews", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "body", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "author", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type" + } + ], + "possibleTypes": [] + } + ] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "configure", + "description": "", + "args": [ + { + "name": "input", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "ConfigInput", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [ + { + "name": "key", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + }, + { + "name": "nested", + "description": "", + "type": { + "kind": "INPUT_OBJECT", + "name": "NestedInput", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [ + { + "name": "value", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null, + "__typename": "__Type", + "description": "The 'Int' scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "interfaces": [], + "possibleTypes": [] + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + }, + "mutationType": { + "kind": "OBJECT", + "name": "Mutation", + "description": "", + "fields": [ + { + "name": "createUser", + "description": "", + "args": [ + { + "name": "name", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "reviews", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "body", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "author", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + } + ] + } + ], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + }, + "subscriptionType": null, + "types": [ + { + "kind": "OBJECT", + "name": "Query", + "description": "", + "fields": [ + { + "name": "user", + "description": "", + "args": [], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "reviews", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "body", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "author", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + } + ] + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "search", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "UNION", + "name": "SearchResult", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "reviews", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "body", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "author", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + } + ] + } + ], + "possibleTypes": [] + }, + { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "body", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "author", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "reviews", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + } + ] + } + ], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + } + ] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "node", + "description": "", + "args": [], + "type": { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "reviews", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "body", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "author", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type" + } + ], + "possibleTypes": [] + } + ] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "configure", + "description": "", + "args": [ + { + "name": "input", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "ConfigInput", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [ + { + "name": "key", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + }, + { + "name": "nested", + "description": "", + "type": { + "kind": "INPUT_OBJECT", + "name": "NestedInput", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [ + { + "name": "value", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null, + "__typename": "__Type", + "description": "The 'Int' scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "interfaces": [], + "possibleTypes": [] + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + }, + { + "kind": "OBJECT", + "name": "Mutation", + "description": "", + "fields": [ + { + "name": "createUser", + "description": "", + "args": [ + { + "name": "name", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "reviews", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "body", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "author", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + } + ] + } + ], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + }, + { + "kind": "OBJECT", + "name": "User", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "reviews", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "body", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "author", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + } + ] + } + ], + "possibleTypes": [], + "__typename": "__Type" + }, + { + "kind": "OBJECT", + "name": "Review", + "description": "", + "fields": [ + { + "name": "body", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "author", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "reviews", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + } + ] + } + ], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + }, + { + "kind": "INTERFACE", + "name": "Node", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "reviews", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "body", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "author", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type" + } + ], + "possibleTypes": [] + } + ], + "__typename": "__Type" + }, + { + "kind": "UNION", + "name": "SearchResult", + "description": "", + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "reviews", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "body", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "author", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + } + ] + } + ], + "possibleTypes": [] + }, + { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "body", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "author", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "reviews", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + } + ] + } + ], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + } + ], + "__typename": "__Type" + }, + { + "kind": "ENUM", + "name": "Status", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [], + "__typename": "__Type" + }, + { + "kind": "INPUT_OBJECT", + "name": "ConfigInput", + "description": "", + "inputFields": [ + { + "name": "key", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + }, + { + "name": "nested", + "description": "", + "type": { + "kind": "INPUT_OBJECT", + "name": "NestedInput", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [ + { + "name": "value", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null, + "__typename": "__Type", + "description": "The 'Int' scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "interfaces": [], + "possibleTypes": [] + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + }, + { + "kind": "INPUT_OBJECT", + "name": "NestedInput", + "description": "", + "inputFields": [ + { + "name": "value", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null, + "__typename": "__Type", + "description": "The 'Int' scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + }, + { + "kind": "SCALAR", + "name": "Int", + "description": "The 'Int' scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + }, + { + "kind": "SCALAR", + "name": "Float", + "description": "The 'Float' scalar type represents signed double-precision fractional values as specified by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point).", + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + }, + { + "kind": "SCALAR", + "name": "String", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + }, + { + "kind": "SCALAR", + "name": "Boolean", + "description": "The 'Boolean' scalar type represents 'true' or 'false' .", + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + }, + { + "kind": "SCALAR", + "name": "ID", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + } + ], + "directives": [ + { + "name": "include", + "description": "Directs the executor to include this field or fragment only when the argument is true.", + "locations": [ + "FIELD", + "FRAGMENT_SPREAD", + "INLINE_FRAGMENT" + ], + "args": [ + { + "name": "if", + "description": "Included when true.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null, + "__typename": "__Type", + "description": "The 'Boolean' scalar type represents 'true' or 'false' .", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "isRepeatable": false, + "__typename": "__Directive" + }, + { + "name": "skip", + "description": "Directs the executor to skip this field or fragment when the argument is true.", + "locations": [ + "FIELD", + "FRAGMENT_SPREAD", + "INLINE_FRAGMENT" + ], + "args": [ + { + "name": "if", + "description": "Skipped when true.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null, + "__typename": "__Type", + "description": "The 'Boolean' scalar type represents 'true' or 'false' .", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "isRepeatable": false, + "__typename": "__Directive" + }, + { + "name": "deprecated", + "description": "Marks an element of a GraphQL schema as no longer supported.", + "locations": [ + "FIELD_DEFINITION", + "ARGUMENT_DEFINITION", + "ENUM_VALUE", + "INPUT_FIELD_DEFINITION" + ], + "args": [ + { + "name": "reason", + "description": "Explains why this element was deprecated, usually also including a suggestion\n for how to access supported similar data. Formatted in\n [Markdown](https://daringfireball.net/projects/markdown/).", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "defaultValue": "\"No longer supported\"", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "isRepeatable": false, + "__typename": "__Directive" + }, + { + "name": "specifiedBy", + "description": "", + "locations": [ + "SCALAR" + ], + "args": [ + { + "name": "url", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "isRepeatable": false, + "__typename": "__Directive" + }, + { + "name": "oneOf", + "description": "The @oneOf built-in directive marks an input object as a OneOf Input Object.\nExactly one field must be provided and its value must be non-null at runtime.\nAll fields defined within a @oneOf input must be nullable in the schema.", + "locations": [ + "INPUT_OBJECT" + ], + "args": [], + "isRepeatable": false, + "__typename": "__Directive" + } + ], + "__typename": "__Schema" +} \ No newline at end of file diff --git a/v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_search_result.golden b/v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_search_result.golden new file mode 100644 index 0000000000..e6138bc5b1 --- /dev/null +++ b/v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_search_result.golden @@ -0,0 +1,472 @@ +{ + "kind": "UNION", + "name": "SearchResult", + "description": "", + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "reviews", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "body", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "author", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + } + ] + } + ], + "possibleTypes": [] + }, + { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "body", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "author", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "reviews", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + } + ] + } + ], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + } + ], + "__typename": "__Type" +} \ No newline at end of file diff --git a/v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_user.golden b/v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_user.golden new file mode 100644 index 0000000000..4a47d99148 --- /dev/null +++ b/v2/pkg/engine/datasource/introspection_datasource/fixtures/comprehensive_user.golden @@ -0,0 +1,230 @@ +{ + "kind": "OBJECT", + "name": "User", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "reviews", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Review", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "body", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "author", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "status", + "description": "", + "args": [], + "type": { + "kind": "ENUM", + "name": "Status", + "ofType": null, + "__typename": "__Type", + "description": "", + "inputFields": [], + "interfaces": [], + "enumValues": [ + { + "name": "ACTIVE", + "description": "", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__EnumValue" + }, + { + "name": "INACTIVE", + "description": "", + "isDeprecated": true, + "deprecationReason": "Use ACTIVE", + "__typename": "__EnumValue" + } + ], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + } + ] + } + ], + "possibleTypes": [], + "__typename": "__Type" +} \ No newline at end of file diff --git a/v2/pkg/engine/datasource/introspection_datasource/fixtures/oftype_mutation.golden b/v2/pkg/engine/datasource/introspection_datasource/fixtures/oftype_mutation.golden new file mode 100644 index 0000000000..d6ea8c2b8b --- /dev/null +++ b/v2/pkg/engine/datasource/introspection_datasource/fixtures/oftype_mutation.golden @@ -0,0 +1,135 @@ +{ + "kind": "OBJECT", + "name": "Mutation", + "description": "", + "fields": [ + { + "name": "createUser", + "description": "", + "args": [ + { + "name": "name", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" +} \ No newline at end of file diff --git a/v2/pkg/engine/datasource/introspection_datasource/fixtures/oftype_schema.golden b/v2/pkg/engine/datasource/introspection_datasource/fixtures/oftype_schema.golden new file mode 100644 index 0000000000..e4dee03358 --- /dev/null +++ b/v2/pkg/engine/datasource/introspection_datasource/fixtures/oftype_schema.golden @@ -0,0 +1,769 @@ +{ + "queryType": { + "kind": "OBJECT", + "name": "Query", + "description": "", + "fields": [ + { + "name": "user", + "description": "", + "args": [], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + }, + "mutationType": { + "kind": "OBJECT", + "name": "Mutation", + "description": "", + "fields": [ + { + "name": "createUser", + "description": "", + "args": [ + { + "name": "name", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + }, + "subscriptionType": null, + "types": [ + { + "kind": "OBJECT", + "name": "Query", + "description": "", + "fields": [ + { + "name": "user", + "description": "", + "args": [], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + }, + { + "kind": "OBJECT", + "name": "Mutation", + "description": "", + "fields": [ + { + "name": "createUser", + "description": "", + "args": [ + { + "name": "name", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + }, + { + "kind": "OBJECT", + "name": "User", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + }, + { + "kind": "SCALAR", + "name": "Int", + "description": "The 'Int' scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + }, + { + "kind": "SCALAR", + "name": "Float", + "description": "The 'Float' scalar type represents signed double-precision fractional values as specified by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point).", + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + }, + { + "kind": "SCALAR", + "name": "String", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + }, + { + "kind": "SCALAR", + "name": "Boolean", + "description": "The 'Boolean' scalar type represents 'true' or 'false' .", + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + }, + { + "kind": "SCALAR", + "name": "ID", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" + } + ], + "directives": [ + { + "name": "include", + "description": "Directs the executor to include this field or fragment only when the argument is true.", + "locations": [ + "FIELD", + "FRAGMENT_SPREAD", + "INLINE_FRAGMENT" + ], + "args": [ + { + "name": "if", + "description": "Included when true.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null, + "__typename": "__Type", + "description": "The 'Boolean' scalar type represents 'true' or 'false' .", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "isRepeatable": false, + "__typename": "__Directive" + }, + { + "name": "skip", + "description": "Directs the executor to skip this field or fragment when the argument is true.", + "locations": [ + "FIELD", + "FRAGMENT_SPREAD", + "INLINE_FRAGMENT" + ], + "args": [ + { + "name": "if", + "description": "Skipped when true.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null, + "__typename": "__Type", + "description": "The 'Boolean' scalar type represents 'true' or 'false' .", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "isRepeatable": false, + "__typename": "__Directive" + }, + { + "name": "deprecated", + "description": "Marks an element of a GraphQL schema as no longer supported.", + "locations": [ + "FIELD_DEFINITION", + "ARGUMENT_DEFINITION", + "ENUM_VALUE", + "INPUT_FIELD_DEFINITION" + ], + "args": [ + { + "name": "reason", + "description": "Explains why this element was deprecated, usually also including a suggestion\n for how to access supported similar data. Formatted in\n [Markdown](https://daringfireball.net/projects/markdown/).", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "defaultValue": "\"No longer supported\"", + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "isRepeatable": false, + "__typename": "__Directive" + }, + { + "name": "specifiedBy", + "description": "", + "locations": [ + "SCALAR" + ], + "args": [ + { + "name": "url", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__InputValue" + } + ], + "isRepeatable": false, + "__typename": "__Directive" + }, + { + "name": "oneOf", + "description": "The @oneOf built-in directive marks an input object as a OneOf Input Object.\nExactly one field must be provided and its value must be non-null at runtime.\nAll fields defined within a @oneOf input must be nullable in the schema.", + "locations": [ + "INPUT_OBJECT" + ], + "args": [], + "isRepeatable": false, + "__typename": "__Directive" + } + ], + "__typename": "__Schema" +} \ No newline at end of file diff --git a/v2/pkg/engine/datasource/introspection_datasource/fixtures/oftype_user.golden b/v2/pkg/engine/datasource/introspection_datasource/fixtures/oftype_user.golden new file mode 100644 index 0000000000..4c3e44df9e --- /dev/null +++ b/v2/pkg/engine/datasource/introspection_datasource/fixtures/oftype_user.golden @@ -0,0 +1,86 @@ +{ + "kind": "OBJECT", + "name": "User", + "description": "", + "fields": [ + { + "name": "id", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null, + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + }, + { + "name": "friends", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [], + "__typename": "__Type" +} \ No newline at end of file diff --git a/v2/pkg/engine/datasource/introspection_datasource/fixtures/schema_introspection.golden b/v2/pkg/engine/datasource/introspection_datasource/fixtures/schema_introspection.golden index d6f62343c4..d906860d47 100644 --- a/v2/pkg/engine/datasource/introspection_datasource/fixtures/schema_introspection.golden +++ b/v2/pkg/engine/datasource/introspection_datasource/fixtures/schema_introspection.golden @@ -12,7 +12,36 @@ "kind": "OBJECT", "name": "Droid", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "isDeprecated": true, "deprecationReason": "No longer supported", @@ -32,7 +61,11 @@ "kind": "SCALAR", "name": "ID", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "__typename": "__Type" }, @@ -46,7 +79,36 @@ "kind": "OBJECT", "name": "Droid", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "isDeprecated": false, "deprecationReason": null, @@ -74,7 +136,36 @@ "kind": "OBJECT", "name": "Droid", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "isDeprecated": true, "deprecationReason": "No longer supported", @@ -94,7 +185,11 @@ "kind": "SCALAR", "name": "ID", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "__typename": "__Type" }, @@ -108,7 +203,36 @@ "kind": "OBJECT", "name": "Droid", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "isDeprecated": false, "deprecationReason": null, @@ -168,7 +292,11 @@ "kind": "SCALAR", "name": "String", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "__typename": "__Type" }, @@ -248,7 +376,11 @@ "kind": "SCALAR", "name": "Boolean", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "The 'Boolean' scalar type represents 'true' or 'false' .", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "__typename": "__Type" }, @@ -280,7 +412,11 @@ "kind": "SCALAR", "name": "Boolean", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "The 'Boolean' scalar type represents 'true' or 'false' .", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "__typename": "__Type" }, @@ -310,7 +446,11 @@ "kind": "SCALAR", "name": "String", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "defaultValue": "\"No longer supported\"", "isDeprecated": false, @@ -338,7 +478,11 @@ "kind": "SCALAR", "name": "String", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "__typename": "__Type" }, diff --git a/v2/pkg/engine/datasource/introspection_datasource/fixtures/schema_introspection_with_custom_root_operation_types.golden b/v2/pkg/engine/datasource/introspection_datasource/fixtures/schema_introspection_with_custom_root_operation_types.golden index f56fee360b..fd5eab0ac5 100644 --- a/v2/pkg/engine/datasource/introspection_datasource/fixtures/schema_introspection_with_custom_root_operation_types.golden +++ b/v2/pkg/engine/datasource/introspection_datasource/fixtures/schema_introspection_with_custom_root_operation_types.golden @@ -12,7 +12,36 @@ "kind": "OBJECT", "name": "Droid", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "isDeprecated": true, "deprecationReason": "No longer supported", @@ -32,7 +61,11 @@ "kind": "SCALAR", "name": "ID", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "__typename": "__Type" }, @@ -46,7 +79,36 @@ "kind": "OBJECT", "name": "Droid", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "isDeprecated": false, "deprecationReason": null, @@ -77,7 +139,11 @@ "kind": "SCALAR", "name": "ID", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "__typename": "__Type" }, @@ -94,7 +160,11 @@ "kind": "SCALAR", "name": "Boolean", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "The 'Boolean' scalar type represents 'true' or 'false' .", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "__typename": "__Type" }, @@ -121,7 +191,36 @@ "kind": "OBJECT", "name": "Droid", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "isDeprecated": false, "deprecationReason": null, @@ -147,7 +246,36 @@ "kind": "OBJECT", "name": "Droid", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "isDeprecated": true, "deprecationReason": "No longer supported", @@ -167,7 +295,11 @@ "kind": "SCALAR", "name": "ID", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "__typename": "__Type" }, @@ -181,7 +313,36 @@ "kind": "OBJECT", "name": "Droid", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "isDeprecated": false, "deprecationReason": null, @@ -212,7 +373,11 @@ "kind": "SCALAR", "name": "ID", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "__typename": "__Type" }, @@ -229,7 +394,11 @@ "kind": "SCALAR", "name": "Boolean", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "The 'Boolean' scalar type represents 'true' or 'false' .", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "__typename": "__Type" }, @@ -256,7 +425,36 @@ "kind": "OBJECT", "name": "Droid", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "isDeprecated": false, "deprecationReason": null, @@ -316,7 +514,11 @@ "kind": "SCALAR", "name": "String", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "__typename": "__Type" }, @@ -396,7 +598,11 @@ "kind": "SCALAR", "name": "Boolean", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "The 'Boolean' scalar type represents 'true' or 'false' .", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "__typename": "__Type" }, @@ -428,7 +634,11 @@ "kind": "SCALAR", "name": "Boolean", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "The 'Boolean' scalar type represents 'true' or 'false' .", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "__typename": "__Type" }, @@ -458,7 +668,11 @@ "kind": "SCALAR", "name": "String", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "defaultValue": "\"No longer supported\"", "isDeprecated": false, @@ -486,7 +700,11 @@ "kind": "SCALAR", "name": "String", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "__typename": "__Type" }, diff --git a/v2/pkg/engine/datasource/introspection_datasource/fixtures/type_introspection.golden b/v2/pkg/engine/datasource/introspection_datasource/fixtures/type_introspection.golden index 16017d1314..f918fd150c 100644 --- a/v2/pkg/engine/datasource/introspection_datasource/fixtures/type_introspection.golden +++ b/v2/pkg/engine/datasource/introspection_datasource/fixtures/type_introspection.golden @@ -11,7 +11,36 @@ "kind": "OBJECT", "name": "Droid", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "isDeprecated": true, "deprecationReason": "No longer supported", @@ -31,7 +60,11 @@ "kind": "SCALAR", "name": "ID", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "The 'ID' scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as '4') or integer (such as 4) input value will be accepted as an ID.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "__typename": "__Type" }, @@ -45,7 +78,36 @@ "kind": "OBJECT", "name": "Droid", "ofType": null, - "__typename": "__Type" + "__typename": "__Type", + "description": "", + "fields": [ + { + "name": "name", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null, + "__typename": "__Type", + "description": "The 'String' scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "inputFields": [], + "interfaces": [], + "possibleTypes": [] + }, + "__typename": "__Type" + }, + "isDeprecated": false, + "deprecationReason": null, + "__typename": "__Field" + } + ], + "inputFields": [], + "interfaces": [], + "possibleTypes": [] }, "isDeprecated": false, "deprecationReason": null, diff --git a/v2/pkg/engine/datasource/introspection_datasource/source.go b/v2/pkg/engine/datasource/introspection_datasource/source.go index 67195e44a7..de79905376 100644 --- a/v2/pkg/engine/datasource/introspection_datasource/source.go +++ b/v2/pkg/engine/datasource/introspection_datasource/source.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "errors" - "io" "net/http" "github.com/wundergraph/graphql-go-tools/v2/pkg/engine/datasource/httpclient" @@ -29,40 +28,22 @@ func (s *Source) Load(ctx context.Context, headers http.Header, input []byte) (d return s.singleTypeBytes(req.TypeName) } - return json.Marshal(s.introspectionData.Schema) + return s.introspectionData.Schema.EnrichedSchemaJSON(), nil } func (s *Source) LoadWithFiles(ctx context.Context, headers http.Header, input []byte, files []*httpclient.FileUpload) (data []byte, err error) { return nil, errors.New("introspection data source does not support file uploads") } -func (s *Source) typeInfo(typeName *string) *introspection.FullType { +func (s *Source) singleTypeBytes(typeName *string) ([]byte, error) { if typeName == nil { - return nil - } - - return s.introspectionData.Schema.TypeByName(*typeName) -} - -func (s *Source) writeNull(w io.Writer) error { - _, err := w.Write(null) - return err -} - -func (s *Source) singleType(w io.Writer, typeName *string) error { - typeInfo := s.typeInfo(typeName) - if typeInfo == nil { - return s.writeNull(w) + return null, nil } - return json.NewEncoder(w).Encode(typeInfo) -} - -func (s *Source) singleTypeBytes(typeName *string) ([]byte, error) { - typeInfo := s.typeInfo(typeName) - if typeInfo == nil { + b := s.introspectionData.Schema.EnrichedTypeJSON(*typeName) + if b == nil { return null, nil } - return json.Marshal(typeInfo) + return b, nil } diff --git a/v2/pkg/engine/datasource/introspection_datasource/source_test.go b/v2/pkg/engine/datasource/introspection_datasource/source_test.go index 9737a4ee9f..871f83d8f3 100644 --- a/v2/pkg/engine/datasource/introspection_datasource/source_test.go +++ b/v2/pkg/engine/datasource/introspection_datasource/source_test.go @@ -26,6 +26,7 @@ func TestSource_Load(t *testing.T) { gen := introspection.NewGenerator() gen.Generate(&def, &report, &data) require.False(t, report.HasErrors()) + require.NoError(t, data.Schema.BuildJSON()) source := &Source{introspectionData: &data} responseData, err := source.Load(context.Background(), nil, []byte(input)) @@ -97,4 +98,154 @@ enum Episode { type Droid { name: String! -}` +} +` + +func TestSource_Load_OfTypeFields(t *testing.T) { + // Regression test for https://github.com/wundergraph/cosmo/issues/991 + // Verifies that ofType nodes carry full type data (fields, description, etc.) + // and that self-referencing types (User -> friends -> [User!]!) don't infinite loop. + const schema = ` +schema { + query: Query + mutation: Mutation +} + +type Query { + user: User +} + +type Mutation { + createUser(name: String!): User! +} + +type User { + id: ID! + name: String! + friends: [User!]! +} +` + run := func(input string, fixtureName string) func(t *testing.T) { + return func(t *testing.T) { + def, report := astparser.ParseGraphqlDocumentString(schema) + require.False(t, report.HasErrors()) + require.NoError(t, asttransform.MergeDefinitionWithBaseSchema(&def)) + + var data introspection.Data + gen := introspection.NewGenerator() + gen.Generate(&def, &report, &data) + require.False(t, report.HasErrors()) + require.NoError(t, data.Schema.BuildJSON()) + + source := &Source{introspectionData: &data} + responseData, err := source.Load(context.Background(), nil, []byte(input)) + require.NoError(t, err) + + actualResponse := &bytes.Buffer{} + require.NoError(t, json.Indent(actualResponse, responseData, "", " ")) + responseBytes := actualResponse.Bytes() + if len(responseBytes) > 0 && responseBytes[len(responseBytes)-1] == '\n' { + responseBytes = responseBytes[:len(responseBytes)-1] + } + goldie.Assert(t, fixtureName, responseBytes) + } + } + + t.Run("ofType has fields for mutation return types", run(`{"request_type":2,"type_name":"Mutation"}`, `oftype_mutation`)) + t.Run("self-referencing type", run(`{"request_type":2,"type_name":"User"}`, `oftype_user`)) + t.Run("schema with enriched ofType", run(`{"request_type":1}`, `oftype_schema`)) +} + +func TestSource_Load_Comprehensive(t *testing.T) { + // Comprehensive test exercising all enrichment paths: + // - Interfaces (FullType.Interfaces []TypeRef) + // - Interface possibleTypes (FullType.PossibleTypes []TypeRef) + // - Union possibleTypes + // - Input objects with nested input type refs + // - Enum type refs (field returning an enum) + // - Cross-type cycles (User→Review→User) + // - Self-referencing cycles (User→friends→User) + const schema = ` +schema { + query: Query + mutation: Mutation +} + +type Query { + user: User + search: [SearchResult] + node: Node + status: Status + configure(input: ConfigInput!): String +} + +type Mutation { + createUser(name: String!): User! +} + +type User implements Node { + id: ID! + name: String! + friends: [User!]! + reviews: [Review] + status: Status +} + +type Review { + body: String! + author: User! +} + +interface Node { + id: ID! +} + +union SearchResult = User | Review + +enum Status { + ACTIVE + INACTIVE @deprecated(reason: "Use ACTIVE") +} + +input ConfigInput { + key: String! + nested: NestedInput +} + +input NestedInput { + value: Int! +} +` + run := func(input string, fixtureName string) func(t *testing.T) { + return func(t *testing.T) { + def, report := astparser.ParseGraphqlDocumentString(schema) + require.False(t, report.HasErrors()) + require.NoError(t, asttransform.MergeDefinitionWithBaseSchema(&def)) + + var data introspection.Data + gen := introspection.NewGenerator() + gen.Generate(&def, &report, &data) + require.False(t, report.HasErrors()) + require.NoError(t, data.Schema.BuildJSON()) + + source := &Source{introspectionData: &data} + responseData, err := source.Load(context.Background(), nil, []byte(input)) + require.NoError(t, err) + + actualResponse := &bytes.Buffer{} + require.NoError(t, json.Indent(actualResponse, responseData, "", " ")) + responseBytes := actualResponse.Bytes() + if len(responseBytes) > 0 && responseBytes[len(responseBytes)-1] == '\n' { + responseBytes = responseBytes[:len(responseBytes)-1] + } + goldie.Assert(t, fixtureName, responseBytes) + } + } + + t.Run("user type with interfaces and cross-cycle", run(`{"request_type":2,"type_name":"User"}`, `comprehensive_user`)) + t.Run("interface with possibleTypes", run(`{"request_type":2,"type_name":"Node"}`, `comprehensive_node`)) + t.Run("union with possibleTypes", run(`{"request_type":2,"type_name":"SearchResult"}`, `comprehensive_search_result`)) + t.Run("input object with nested input ref", run(`{"request_type":2,"type_name":"ConfigInput"}`, `comprehensive_config_input`)) + t.Run("review type with back-ref cycle", run(`{"request_type":2,"type_name":"Review"}`, `comprehensive_review`)) + t.Run("full schema", run(`{"request_type":1}`, `comprehensive_schema`)) +} diff --git a/v2/pkg/introspection/enrich.go b/v2/pkg/introspection/enrich.go new file mode 100644 index 0000000000..24da061649 --- /dev/null +++ b/v2/pkg/introspection/enrich.go @@ -0,0 +1,251 @@ +package introspection + +import ( + "github.com/wundergraph/astjson" +) + +// BuildJSON pre-computes self-contained JSON for each type and the full schema. +// +// The introspection data model has two Go types: FullType (rich, with fields, +// description, interfaces, etc.) and TypeRef (sparse, only kind/name/ofType). +// Field.Type and TypeRef.OfType are TypeRef, so a query like +// `ofType { fields { name } }` wouldn't find the expected data. +// +// This method walks the Go structs and builds JSON directly with astjson, +// resolving each TypeRef to its full type data on the fly. The result is +// self-contained JSON where every type reference carries the full type info. +// +// Self-referencing types (e.g. User with field friends: [User!]!) are handled +// by a visited set per DFS path — if a type is already being serialized in an +// ancestor, we emit only kind/name/ofType/__typename to break the cycle. +// +// Computed once at startup; Source.Load returns the pre-built bytes. +func (s *Schema) BuildJSON() error { + s.enrichedTypeJSON = make(map[string][]byte, len(s.Types)) + for _, ft := range s.Types { + visited := make(map[string]struct{}) + v := marshalFullType(ft, s.fullTypeMap, visited) + s.enrichedTypeJSON[ft.Name] = v.MarshalTo(nil) + } + + visited := make(map[string]struct{}) + v := marshalSchema(s, s.fullTypeMap, visited) + s.enrichedSchemaJSON = v.MarshalTo(nil) + + return nil +} + +func marshalSchema(s *Schema, typeMap map[string]*FullType, visited map[string]struct{}) *astjson.Value { + obj := astjson.ObjectValue(nil) + + obj.Set(nil, "queryType", marshalFullType(&s.QueryType, typeMap, visited)) + + if s.MutationType != nil { + obj.Set(nil, "mutationType", marshalFullType(s.MutationType, typeMap, visited)) + } else { + obj.Set(nil, "mutationType", astjson.NullValue) + } + + if s.SubscriptionType != nil { + obj.Set(nil, "subscriptionType", marshalFullType(s.SubscriptionType, typeMap, visited)) + } else { + obj.Set(nil, "subscriptionType", astjson.NullValue) + } + + typesArr := astjson.ArrayValue(nil) + for i, ft := range s.Types { + typesArr.SetArrayItem(nil, i, marshalFullType(ft, typeMap, visited)) + } + obj.Set(nil, "types", typesArr) + + directivesArr := astjson.ArrayValue(nil) + for i, d := range s.Directives { + directivesArr.SetArrayItem(nil, i, marshalDirective(d, typeMap, visited)) + } + obj.Set(nil, "directives", directivesArr) + + obj.Set(nil, "__typename", astjson.StringValue(nil, s.TypeName)) + + if s.Description != nil { + obj.Set(nil, "description", astjson.StringValue(nil, *s.Description)) + } + + return obj +} + +// marshalFullType serializes a FullType as a top-level JSON object. +// Key order matches json.Marshal of the FullType struct. +func marshalFullType(ft *FullType, typeMap map[string]*FullType, visited map[string]struct{}) *astjson.Value { + visited[ft.Name] = struct{}{} + + obj := astjson.ObjectValue(nil) + obj.Set(nil, "kind", kindValue(ft.Kind)) + obj.Set(nil, "name", astjson.StringValue(nil, ft.Name)) + appendFullTypeBody(obj, ft, typeMap, visited) + obj.Set(nil, "__typename", astjson.StringValue(nil, ft.TypeName)) + if ft.SpecifiedByURL != nil { + obj.Set(nil, "specifiedByURL", astjson.StringValue(nil, *ft.SpecifiedByURL)) + } + + delete(visited, ft.Name) + return obj +} + +// marshalTypeRef serializes a TypeRef. For named types (OBJECT, SCALAR, etc.), +// it resolves the reference to the full type data from typeMap. For wrapper +// types (NON_NULL, LIST), it recurses into OfType. Cycle detection prevents +// infinite expansion of self-referencing types. +func marshalTypeRef(tr TypeRef, typeMap map[string]*FullType, visited map[string]struct{}) *astjson.Value { + obj := astjson.ObjectValue(nil) + obj.Set(nil, "kind", kindValue(tr.Kind)) + obj.Set(nil, "name", ptrStringValue(tr.Name)) + + if tr.OfType != nil { + obj.Set(nil, "ofType", marshalTypeRef(*tr.OfType, typeMap, visited)) + } else { + obj.Set(nil, "ofType", astjson.NullValue) + } + + obj.Set(nil, "__typename", astjson.StringValue(nil, tr.TypeName)) + + // Wrapper types (NON_NULL, LIST) have nil Name — nothing to resolve. + if tr.Name == nil { + return obj + } + + name := *tr.Name + + // Cycle: this type is already being serialized in an ancestor. + if _, ok := visited[name]; ok { + return obj + } + + ft, ok := typeMap[name] + if !ok { + return obj + } + + // Resolve: append full type data after the TypeRef keys. + visited[name] = struct{}{} + appendFullTypeBody(obj, ft, typeMap, visited) + if ft.SpecifiedByURL != nil { + obj.Set(nil, "specifiedByURL", astjson.StringValue(nil, *ft.SpecifiedByURL)) + } + delete(visited, name) + + return obj +} + +// appendFullTypeBody appends the FullType data keys (description through +// possibleTypes) to an object. Shared between marshalFullType and the +// resolve path in marshalTypeRef. +func appendFullTypeBody(obj *astjson.Value, ft *FullType, typeMap map[string]*FullType, visited map[string]struct{}) { + obj.Set(nil, "description", astjson.StringValue(nil, ft.Description)) + + if len(ft.Fields) > 0 { + arr := astjson.ArrayValue(nil) + for i, f := range ft.Fields { + arr.SetArrayItem(nil, i, marshalField(f, typeMap, visited)) + } + obj.Set(nil, "fields", arr) + } + + obj.Set(nil, "inputFields", marshalInputValueArray(ft.InputFields, typeMap, visited)) + obj.Set(nil, "interfaces", marshalTypeRefArray(ft.Interfaces, typeMap, visited)) + + if len(ft.EnumValues) > 0 { + arr := astjson.ArrayValue(nil) + for i, ev := range ft.EnumValues { + arr.SetArrayItem(nil, i, marshalEnumValue(ev)) + } + obj.Set(nil, "enumValues", arr) + } + + obj.Set(nil, "possibleTypes", marshalTypeRefArray(ft.PossibleTypes, typeMap, visited)) +} + +func marshalField(f Field, typeMap map[string]*FullType, visited map[string]struct{}) *astjson.Value { + obj := astjson.ObjectValue(nil) + obj.Set(nil, "name", astjson.StringValue(nil, f.Name)) + obj.Set(nil, "description", astjson.StringValue(nil, f.Description)) + obj.Set(nil, "args", marshalInputValueArray(f.Args, typeMap, visited)) + obj.Set(nil, "type", marshalTypeRef(f.Type, typeMap, visited)) + obj.Set(nil, "isDeprecated", boolValue(f.IsDeprecated)) + obj.Set(nil, "deprecationReason", ptrStringValue(f.DeprecationReason)) + obj.Set(nil, "__typename", astjson.StringValue(nil, f.TypeName)) + return obj +} + +func marshalInputValue(iv InputValue, typeMap map[string]*FullType, visited map[string]struct{}) *astjson.Value { + obj := astjson.ObjectValue(nil) + obj.Set(nil, "name", astjson.StringValue(nil, iv.Name)) + obj.Set(nil, "description", astjson.StringValue(nil, iv.Description)) + obj.Set(nil, "type", marshalTypeRef(iv.Type, typeMap, visited)) + obj.Set(nil, "defaultValue", ptrStringValue(iv.DefaultValue)) + obj.Set(nil, "isDeprecated", boolValue(iv.IsDeprecated)) + obj.Set(nil, "deprecationReason", ptrStringValue(iv.DeprecationReason)) + obj.Set(nil, "__typename", astjson.StringValue(nil, iv.TypeName)) + return obj +} + +func marshalEnumValue(ev EnumValue) *astjson.Value { + obj := astjson.ObjectValue(nil) + obj.Set(nil, "name", astjson.StringValue(nil, ev.Name)) + obj.Set(nil, "description", astjson.StringValue(nil, ev.Description)) + obj.Set(nil, "isDeprecated", boolValue(ev.IsDeprecated)) + obj.Set(nil, "deprecationReason", ptrStringValue(ev.DeprecationReason)) + obj.Set(nil, "__typename", astjson.StringValue(nil, ev.TypeName)) + return obj +} + +func marshalDirective(d Directive, typeMap map[string]*FullType, visited map[string]struct{}) *astjson.Value { + obj := astjson.ObjectValue(nil) + obj.Set(nil, "name", astjson.StringValue(nil, d.Name)) + obj.Set(nil, "description", astjson.StringValue(nil, d.Description)) + + locArr := astjson.ArrayValue(nil) + for i, loc := range d.Locations { + locArr.SetArrayItem(nil, i, astjson.StringValue(nil, loc)) + } + obj.Set(nil, "locations", locArr) + + obj.Set(nil, "args", marshalInputValueArray(d.Args, typeMap, visited)) + obj.Set(nil, "isRepeatable", boolValue(d.IsRepeatable)) + obj.Set(nil, "__typename", astjson.StringValue(nil, d.TypeName)) + return obj +} + +func marshalTypeRefArray(refs []TypeRef, typeMap map[string]*FullType, visited map[string]struct{}) *astjson.Value { + arr := astjson.ArrayValue(nil) + for i, tr := range refs { + arr.SetArrayItem(nil, i, marshalTypeRef(tr, typeMap, visited)) + } + return arr +} + +func marshalInputValueArray(ivs []InputValue, typeMap map[string]*FullType, visited map[string]struct{}) *astjson.Value { + arr := astjson.ArrayValue(nil) + for i, iv := range ivs { + arr.SetArrayItem(nil, i, marshalInputValue(iv, typeMap, visited)) + } + return arr +} + +func kindValue(k __TypeKind) *astjson.Value { + text, _ := k.MarshalText() + return astjson.StringValue(nil, string(text)) +} + +func boolValue(b bool) *astjson.Value { + if b { + return astjson.TrueValue(nil) + } + return astjson.FalseValue(nil) +} + +func ptrStringValue(s *string) *astjson.Value { + if s == nil { + return astjson.NullValue + } + return astjson.StringValue(nil, *s) +} diff --git a/v2/pkg/introspection/introspection.go b/v2/pkg/introspection/introspection.go index c799e640f6..27c962de53 100644 --- a/v2/pkg/introspection/introspection.go +++ b/v2/pkg/introspection/introspection.go @@ -12,14 +12,16 @@ type Data struct { } type Schema struct { - QueryType FullType `json:"queryType"` - MutationType *FullType `json:"mutationType"` - SubscriptionType *FullType `json:"subscriptionType"` - Types []*FullType `json:"types"` - Directives []Directive `json:"directives"` - TypeName string `json:"__typename"` - Description *string `json:"description,omitempty"` - fullTypeMap map[string]*FullType + QueryType FullType `json:"queryType"` + MutationType *FullType `json:"mutationType"` + SubscriptionType *FullType `json:"subscriptionType"` + Types []*FullType `json:"types"` + Directives []Directive `json:"directives"` + TypeName string `json:"__typename"` + Description *string `json:"description,omitempty"` + fullTypeMap map[string]*FullType + enrichedSchemaJSON []byte + enrichedTypeJSON map[string][]byte } func (s *Schema) AddType(t *FullType) { @@ -44,12 +46,25 @@ func (s *Schema) TypeNames() (query, mutation, subscription string) { return } +// EnrichedSchemaJSON returns the pre-built JSON for the full __schema introspection response. +// BuildJSON must be called first. +func (s *Schema) EnrichedSchemaJSON() []byte { + return s.enrichedSchemaJSON +} + +// EnrichedTypeJSON returns the pre-built JSON for a single __type introspection response. +// BuildJSON must be called first. +func (s *Schema) EnrichedTypeJSON(name string) []byte { + return s.enrichedTypeJSON[name] +} + func NewSchema() Schema { return Schema{ - Types: make([]*FullType, 0), - Directives: make([]Directive, 0), - TypeName: "__Schema", - fullTypeMap: make(map[string]*FullType), + Types: make([]*FullType, 0), + Directives: make([]Directive, 0), + TypeName: "__Schema", + fullTypeMap: make(map[string]*FullType), + enrichedTypeJSON: make(map[string][]byte), } } From f2b5757430c11adca2bbe05ebf972fa6b8764e44 Mon Sep 17 00:00:00 2001 From: Jens Neuse Date: Thu, 19 Feb 2026 10:31:28 +0100 Subject: [PATCH 2/4] test(introspection): add e2e test for nested enrichment and cycle prevention MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a complex nested introspection query exercising aliases, deep ofType.fields resolution, union possibleTypes with fields, and explicit cycle truncation (Review→User→reviews→Review shows fields:null). Co-Authored-By: Claude Opus 4.6 --- .../engine/federation_integration_test.go | 52 +++++++++++++++++++ .../introspection_nested_enriched.query | 46 ++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 execution/federationtesting/testdata/queries/introspection_nested_enriched.query diff --git a/execution/engine/federation_integration_test.go b/execution/engine/federation_integration_test.go index 85655064a1..fcb9620dea 100644 --- a/execution/engine/federation_integration_test.go +++ b/execution/engine/federation_integration_test.go @@ -517,6 +517,58 @@ func TestFederationIntegrationTest(t *testing.T) { expected := `{"data":{"__type":{"name":"User","kind":"OBJECT","fields":[{"name":"id","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","fields":null}}},{"name":"username","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","fields":null}}},{"name":"history","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"fields":null}}},{"name":"realName","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","fields":null}}},{"name":"reviews","type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Review","fields":[{"name":"body"},{"name":"author"},{"name":"product"},{"name":"attachments"},{"name":"comment"}]}}}]}}}` assert.Equal(t, compact(expected), string(resp)) }) + + // Complex nested introspection proving enrichment works end-to-end: + // - Aliases (review:, attachment:) + // - Deep ofType nesting: ofType.fields.type.ofType with full type resolution + // - Union possibleTypes with fields (Attachment → Question, Rating, Video) + // - Cycle prevention: User.reviews and Product.reviews both reference Review, + // which is already being serialized → "fields": null proves truncation + t.Run("introspection nested enriched types", func(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(cancel) + resp := gqlClient.Query(ctx, setup.GatewayServer.URL, testQueryPath("queries/introspection_nested_enriched.query"), nil, t) + expected := `{"data":{ + "review":{ + "kind":"OBJECT","name":"Review", + "fields":[ + {"name":"body","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","fields":null,"possibleTypes":[]}}}, + {"name":"author","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"User", + "fields":[ + {"name":"id","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","fields":null}}}, + {"name":"username","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","fields":null}}}, + {"name":"history","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"fields":null}}}, + {"name":"realName","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","fields":null}}}, + {"name":"reviews","type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Review","fields":null}}} + ], + "possibleTypes":[] + }}}, + {"name":"product","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"Product", + "fields":[ + {"name":"upc","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","fields":null}}}, + {"name":"name","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","fields":null}}}, + {"name":"price","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Int","fields":null}}}, + {"name":"inStock","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Int","fields":null}}}, + {"name":"reviews","type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Review","fields":null}}} + ], + "possibleTypes":[] + }}}, + {"name":"attachments","type":{"kind":"LIST","name":null,"ofType":{"kind":"UNION","name":"Attachment","fields":null,"possibleTypes":[{"kind":"OBJECT","name":"Question"},{"kind":"OBJECT","name":"Rating"},{"kind":"OBJECT","name":"Video"}]}}}, + {"name":"comment","type":{"kind":"INTERFACE","name":"Comment","ofType":null}} + ] + }, + "attachment":{ + "kind":"UNION","name":"Attachment", + "possibleTypes":[ + {"kind":"OBJECT","name":"Question","fields":[{"name":"upc"},{"name":"body"},{"name":"subject"}]}, + {"kind":"OBJECT","name":"Rating","fields":[{"name":"upc"},{"name":"body"},{"name":"score"}]}, + {"kind":"OBJECT","name":"Video","fields":[{"name":"upc"},{"name":"size"},{"name":"subject"}]} + ] + } + }}` + assert.Equal(t, compact(expected), string(resp)) + }) } func compact(input string) string { diff --git a/execution/federationtesting/testdata/queries/introspection_nested_enriched.query b/execution/federationtesting/testdata/queries/introspection_nested_enriched.query new file mode 100644 index 0000000000..b10d9d48d8 --- /dev/null +++ b/execution/federationtesting/testdata/queries/introspection_nested_enriched.query @@ -0,0 +1,46 @@ +{ + review: __type(name: "Review") { + kind + name + fields { + name + type { + kind + name + ofType { + kind + name + fields { + name + type { + kind + name + ofType { + kind + name + fields { + name + } + } + } + } + possibleTypes { + kind + name + } + } + } + } + } + attachment: __type(name: "Attachment") { + kind + name + possibleTypes { + kind + name + fields { + name + } + } + } +} From 67898039abc8d6f99ef76af2e24cf6c75843c939 Mon Sep 17 00:00:00 2001 From: Jens Neuse Date: Thu, 19 Feb 2026 10:38:49 +0100 Subject: [PATCH 3/4] refactor(introspection): defer visited cleanup and simplify kindValue Use defer for DFS visited-set cleanup to make cycle detection resilient to future early returns. Simplify kindValue to use String() directly. Co-Authored-By: Claude Opus 4.6 --- v2/pkg/introspection/enrich.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/v2/pkg/introspection/enrich.go b/v2/pkg/introspection/enrich.go index 24da061649..963db9f600 100644 --- a/v2/pkg/introspection/enrich.go +++ b/v2/pkg/introspection/enrich.go @@ -76,7 +76,10 @@ func marshalSchema(s *Schema, typeMap map[string]*FullType, visited map[string]s // marshalFullType serializes a FullType as a top-level JSON object. // Key order matches json.Marshal of the FullType struct. func marshalFullType(ft *FullType, typeMap map[string]*FullType, visited map[string]struct{}) *astjson.Value { + // Track DFS ancestry for cycle detection. Defer cleanup so sibling + // branches can independently expand this type. visited[ft.Name] = struct{}{} + defer func() { delete(visited, ft.Name) }() obj := astjson.ObjectValue(nil) obj.Set(nil, "kind", kindValue(ft.Kind)) @@ -87,7 +90,6 @@ func marshalFullType(ft *FullType, typeMap map[string]*FullType, visited map[str obj.Set(nil, "specifiedByURL", astjson.StringValue(nil, *ft.SpecifiedByURL)) } - delete(visited, ft.Name) return obj } @@ -126,12 +128,13 @@ func marshalTypeRef(tr TypeRef, typeMap map[string]*FullType, visited map[string } // Resolve: append full type data after the TypeRef keys. + // Defer cleanup so sibling branches can independently expand this type. visited[name] = struct{}{} + defer func() { delete(visited, name) }() appendFullTypeBody(obj, ft, typeMap, visited) if ft.SpecifiedByURL != nil { obj.Set(nil, "specifiedByURL", astjson.StringValue(nil, *ft.SpecifiedByURL)) } - delete(visited, name) return obj } @@ -232,8 +235,7 @@ func marshalInputValueArray(ivs []InputValue, typeMap map[string]*FullType, visi } func kindValue(k __TypeKind) *astjson.Value { - text, _ := k.MarshalText() - return astjson.StringValue(nil, string(text)) + return astjson.StringValue(nil, k.String()) } func boolValue(b bool) *astjson.Value { From dcc1795bc07137baca9b35da8252e2ab3ae2ebc3 Mon Sep 17 00:00:00 2001 From: Jens Neuse Date: Thu, 19 Feb 2026 10:56:57 +0100 Subject: [PATCH 4/4] bench(introspection): add benchmark for BuildJSON Co-Authored-By: Claude Opus 4.6 --- v2/pkg/introspection/enrich_test.go | 39 +++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 v2/pkg/introspection/enrich_test.go diff --git a/v2/pkg/introspection/enrich_test.go b/v2/pkg/introspection/enrich_test.go new file mode 100644 index 0000000000..4f3926883a --- /dev/null +++ b/v2/pkg/introspection/enrich_test.go @@ -0,0 +1,39 @@ +package introspection + +import ( + "os" + "testing" + + "github.com/wundergraph/graphql-go-tools/v2/pkg/astparser" + "github.com/wundergraph/graphql-go-tools/v2/pkg/asttransform" +) + +func BenchmarkBuildJSON(b *testing.B) { + starwarsSchema, err := os.ReadFile("./testdata/starwars.schema.graphql") + if err != nil { + b.Fatal(err) + } + + def, report := astparser.ParseGraphqlDocumentBytes(starwarsSchema) + if report.HasErrors() { + b.Fatal(report) + } + if err := asttransform.MergeDefinitionWithBaseSchema(&def); err != nil { + b.Fatal(err) + } + + gen := NewGenerator() + var data Data + gen.Generate(&def, &report, &data) + if report.HasErrors() { + b.Fatal(report) + } + + b.ReportAllocs() + b.ResetTimer() + for b.Loop() { + if err := data.Schema.BuildJSON(); err != nil { + b.Fatal(err) + } + } +}