diff --git a/src/Utils/SchemaPrinter.php b/src/Utils/SchemaPrinter.php index 91099d4..9c27b50 100644 --- a/src/Utils/SchemaPrinter.php +++ b/src/Utils/SchemaPrinter.php @@ -3,6 +3,7 @@ namespace GraphQL\Utils; use GraphQL\Language\Printer; use GraphQL\Schema; +use GraphQL\Type\Definition\CompositeType; use GraphQL\Type\Definition\EnumType; use GraphQL\Type\Definition\InputObjectType; use GraphQL\Type\Definition\InterfaceType; @@ -203,7 +204,7 @@ class SchemaPrinter private static function printInputObject(InputObjectType $type) { - $fields = array_values($type->getFields()); + $fields = self::sortFields($type->getFields()); return self::printDescription($type) . "input {$type->name} {\n" . implode("\n", array_map(function($f, $i) { @@ -214,7 +215,7 @@ class SchemaPrinter private static function printFields($type) { - $fields = array_values($type->getFields()); + $fields = self::sortFields($type->getFields()); return implode("\n", array_map(function($f, $i) { return self::printDescription($f, ' ', !$i) . ' ' . $f->name . self::printArgs($f->args, ' ') . ': ' . @@ -301,4 +302,10 @@ class SchemaPrinter return trim($part); }, $parts); } + + private static function sortFields(array $fields) + { + ksort($fields); + return array_values($fields); + } } \ No newline at end of file diff --git a/tests/Utils/BuildSchemaTest.php b/tests/Utils/BuildSchemaTest.php index 65e5fe5..8d09261 100644 --- a/tests/Utils/BuildSchemaTest.php +++ b/tests/Utils/BuildSchemaTest.php @@ -71,11 +71,11 @@ schema { } type HelloScalars { - str: String - int: Int + bool: Boolean float: Float id: ID - bool: Boolean + int: Int + str: String } '; $output = $this->cycleOutput($body); @@ -194,11 +194,11 @@ schema { } type HelloScalars { - nonNullStr: String! - listOfStrs: [String] listOfNonNullStrs: [String!] - nonNullListOfStrs: [String]! + listOfStrs: [String] nonNullListOfNonNullStrs: [String!]! + nonNullListOfStrs: [String]! + nonNullStr: String! } '; $output = $this->cycleOutput($body); @@ -216,8 +216,8 @@ schema { } type Recurse { - str: String recurse: Recurse + str: String } '; $output = $this->cycleOutput($body); @@ -259,10 +259,10 @@ schema { } type Hello { - str(int: Int): String + booleanToStr(bool: Boolean): String floatToStr(float: Float): String idToStr(id: ID): String - booleanToStr(bool: Boolean): String + str(int: Int): String strToStr(bool: String): String } '; @@ -479,9 +479,9 @@ schema { } type HelloScalars { - str: String - int: Int bool: Boolean + int: Int + str: String } type Mutation { @@ -504,9 +504,9 @@ schema { } type HelloScalars { - str: String - int: Int bool: Boolean + int: Int + str: String } type Subscription { @@ -572,9 +572,9 @@ enum MyEnum { } type Query { + enum: MyEnum field1: String @deprecated field2: Int @deprecated(reason: "Because I said so") - enum: MyEnum } '; $output = $this->cycleOutput($body); diff --git a/tests/Utils/SchemaPrinterTest.php b/tests/Utils/SchemaPrinterTest.php index 49314f0..55fec16 100644 --- a/tests/Utils/SchemaPrinterTest.php +++ b/tests/Utils/SchemaPrinterTest.php @@ -445,8 +445,8 @@ interface Baaz { } type Bar implements Foo, Baaz { - str: String int: Int + str: String } interface Foo { @@ -512,8 +512,8 @@ type Foo { union MultipleUnion = Foo | Bar type Root { - single: SingleUnion multiple: MultipleUnion + single: SingleUnion } union SingleUnion = Foo @@ -677,13 +677,13 @@ directive @deprecated( # skipping a field. Directives provide this by describing additional information # to the executor. type __Directive { - name: String! + args: [__InputValue!]! description: String locations: [__DirectiveLocation!]! - args: [__InputValue!]! - onOperation: Boolean! @deprecated(reason: "Use `locations`.") - onFragment: Boolean! @deprecated(reason: "Use `locations`.") + name: String! onField: Boolean! @deprecated(reason: "Use `locations`.") + onFragment: Boolean! @deprecated(reason: "Use `locations`.") + onOperation: Boolean! @deprecated(reason: "Use `locations`.") } # A Directive can be adjacent to many parts of the GraphQL language, a @@ -748,53 +748,52 @@ enum __DirectiveLocation { # placeholder for a string or numeric value. However an Enum value is returned in # a JSON response as a string. type __EnumValue { - name: String! + deprecationReason: String description: String isDeprecated: Boolean! - deprecationReason: String + name: String! } # Object and Interface types are described by a list of Fields, each of which has # a name, potentially a list of arguments, and a return type. type __Field { - name: String! - description: String args: [__InputValue!]! - type: __Type! - isDeprecated: Boolean! deprecationReason: String + description: String + isDeprecated: Boolean! + name: String! + type: __Type! } # Arguments provided to Fields or Directives and the input fields of an # InputObject are represented as Input Values which describe their type and # optionally a default value. type __InputValue { - name: String! - description: String - type: __Type! - # A GraphQL-formatted string representing the default value for this input value. defaultValue: String + description: String + name: String! + type: __Type! } # A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all # available types and directives on the server, as well as the entry points for # query, mutation, and subscription operations. type __Schema { - # A list of all types supported by this server. - types: [__Type!]! - - # The type that query operations will be rooted at. - queryType: __Type! + # A list of all directives supported by this server. + directives: [__Directive!]! # If this server supports mutation, the type that mutation operations will be rooted at. mutationType: __Type + # The type that query operations will be rooted at. + queryType: __Type! + # If this server support subscription, the type that subscription operations will be rooted at. subscriptionType: __Type - # A list of all directives supported by this server. - directives: [__Directive!]! + # A list of all types supported by this server. + types: [__Type!]! } # The fundamental unit of any GraphQL Schema is the type. There are many kinds of @@ -806,15 +805,15 @@ type __Schema { # they describe. Abstract types, Union and Interface, provide the Object types # possible at runtime. List and NonNull types compose other types. type __Type { + description: String + enumValues(includeDeprecated: Boolean = false): [__EnumValue!] + fields(includeDeprecated: Boolean = false): [__Field!] + inputFields: [__InputValue!] + interfaces: [__Type!] kind: __TypeKind! name: String - description: String - fields(includeDeprecated: Boolean = false): [__Field!] - interfaces: [__Type!] - possibleTypes: [__Type!] - enumValues(includeDeprecated: Boolean = false): [__EnumValue!] - inputFields: [__InputValue!] ofType: __Type + possibleTypes: [__Type!] } # An enum describing what kind of type a given `__Type` is.