diff --git a/src/Codegen/Builders/Fields/ConnectionFieldBuilder.hack b/src/Codegen/Builders/Fields/ConnectionFieldBuilder.hack index c60023b..86a031a 100644 --- a/src/Codegen/Builders/Fields/ConnectionFieldBuilder.hack +++ b/src/Codegen/Builders/Fields/ConnectionFieldBuilder.hack @@ -32,7 +32,7 @@ final class ConnectionFieldBuilder extends MethodFieldBuilder { <<__Override>> protected function getArgumentDefinitions(): vec { - return Vec\concat($this->data['parameters'], $this->getConnectionParameters()); + return Vec\concat($this->data['parameters'] ?? vec[], $this->getConnectionParameters()); } /** diff --git a/src/Codegen/Builders/Fields/FieldBuilder.hack b/src/Codegen/Builders/Fields/FieldBuilder.hack index 7a3ca5e..2c907df 100644 --- a/src/Codegen/Builders/Fields/FieldBuilder.hack +++ b/src/Codegen/Builders/Fields/FieldBuilder.hack @@ -11,10 +11,16 @@ use type Facebook\HackCodegen\{HackBuilder, HackBuilderValues}; */ abstract class FieldBuilder { - abstract const type TField as shape( + const type TField = shape( 'name' => string, 'output_type' => shape('type' => string, ?'needs_await' => bool), - ... + ?'description' => string, + ?'deprecation_reason' => string, + ?'method_name' => string, + ?'parameters' => vec, + ?'root_field_for_type' => string, + ?'is_static' => bool, + ?'is_optional' => bool, ); public function getName(): string { @@ -35,6 +41,7 @@ abstract class FieldBuilder { ): FieldBuilder { $data = shape( 'name' => $field->getName(), + 'description' => $field->getDescription(), 'method_name' => $rm->getName(), 'output_type' => output_type( $rm->getReturnTypeText(), @@ -56,6 +63,11 @@ abstract class FieldBuilder { ), ); + $deprecated = $rm->getAttribute('__Deprecated'); + if ($deprecated) { + $data['deprecation_reason'] = C\firstx($deprecated) as string; + } + if ($is_root_field) { $data['root_field_for_type'] = $rm->getDeclaringClass()->getName(); } @@ -126,6 +138,22 @@ abstract class FieldBuilder { $this->generateResolverBody($hb); $hb->addLine(','); + // Field description + if ($this->data['description'] ?? '') { + $description_literal = \var_export($this->data['description'] ?? '', true); + $hb->addLinef('%s,', $description_literal); + } else { + // Fields built from shape members don't have descriptions as of yet + $hb->addLine('null,'); + } + + // Deprecation reason + if (Shapes::keyExists($this->data, 'deprecation_reason')) { + $hb->addLine(\var_export($this->data['deprecation_reason'], true).','); + } else { + $hb->addLine('null,'); + } + // End of new GraphQL\FieldDefinition( $hb->unindent()->addLine(');'); $hb->unindent(); diff --git a/src/Codegen/Builders/Fields/IntrospectionSchemaFieldBuilder.hack b/src/Codegen/Builders/Fields/IntrospectionSchemaFieldBuilder.hack index 9d93f49..9551db2 100644 --- a/src/Codegen/Builders/Fields/IntrospectionSchemaFieldBuilder.hack +++ b/src/Codegen/Builders/Fields/IntrospectionSchemaFieldBuilder.hack @@ -5,12 +5,6 @@ namespace Slack\GraphQL\Codegen; use type Facebook\HackCodegen\{HackBuilder}; final class IntrospectSchemaFieldBuilder extends FieldBuilder { - const type TField = shape( - 'name' => string, - 'output_type' => shape('type' => string, ?'needs_await' => bool), - ... - ); - public function __construct() { parent::__construct(shape( 'name' => '__schema', diff --git a/src/Codegen/Builders/Fields/MethodFieldBuilder.hack b/src/Codegen/Builders/Fields/MethodFieldBuilder.hack index a0289cf..b844d62 100644 --- a/src/Codegen/Builders/Fields/MethodFieldBuilder.hack +++ b/src/Codegen/Builders/Fields/MethodFieldBuilder.hack @@ -28,17 +28,11 @@ type Parameter = shape( * we can tell `MethodFieldBuilder` exactly what we want, and the runtime will successfully resolve the generic method. */ class MethodFieldBuilder extends FieldBuilder { - const type TField = shape( - 'name' => string, - 'method_name' => string, - 'output_type' => shape('type' => string, ?'needs_await' => bool), - 'parameters' => vec, - ?'root_field_for_type' => string, - ?'is_static' => bool, - ); - <<__Override>> protected function generateResolverBody(HackBuilder $hb): void { + if ($this->data['deprecation_reason'] ?? null) { + $hb->add('/* HH_FIXME[4128] Deprecated */ '); + } $type_info = $this->data['output_type']; $method_name = Shapes::at($this->data, 'method_name'); $hb->addf( @@ -54,9 +48,10 @@ class MethodFieldBuilder extends FieldBuilder { } protected function generateParametersInvocation(HackBuilder $hb): void { - if (!C\is_empty($this->data['parameters'])) { + $parameters = $this->data['parameters'] ?? vec[]; + if (!C\is_empty($parameters)) { $hb->newLine()->indent(); - foreach ($this->data['parameters'] as $param) { + foreach ($parameters as $param) { $arg = $this->getArgumentInvocationString($param); $hb->addLinef('%s,', $arg); } @@ -66,7 +61,7 @@ class MethodFieldBuilder extends FieldBuilder { <<__Override>> protected function getArgumentDefinitions(): vec { - return $this->data['parameters']; + return $this->data['parameters'] ?? vec[]; } protected function getMethodCallPrefix(): string { diff --git a/src/Codegen/Builders/Fields/ShapeFieldBuilder.hack b/src/Codegen/Builders/Fields/ShapeFieldBuilder.hack index 6b1b37d..0a84cea 100644 --- a/src/Codegen/Builders/Fields/ShapeFieldBuilder.hack +++ b/src/Codegen/Builders/Fields/ShapeFieldBuilder.hack @@ -12,12 +12,6 @@ use type Facebook\HackCodegen\{HackBuilder, HackBuilderValues}; * In general, call `FieldBuilder::fromShapeField` instead of instantiating this directly. */ final class ShapeFieldBuilder extends FieldBuilder { - const type TField = shape( - 'name' => string, - 'output_type' => shape('type' => string, ?'needs_await' => bool), - 'is_optional' => bool, - ); - <<__Override>> protected function getArgumentDefinitions(): vec { return vec[]; @@ -26,6 +20,6 @@ final class ShapeFieldBuilder extends FieldBuilder { <<__Override>> protected function generateResolverBody(HackBuilder $hb): void { $name_literal = \var_export($this->data['name'], true); - $hb->addf('$parent[%s]%s', $name_literal, $this->data['is_optional'] ? ' ?? null' : ''); + $hb->addf('$parent[%s]%s', $name_literal, Shapes::idx($this->data, 'is_optional', false) ? ' ?? null' : ''); } } diff --git a/src/Codegen/Builders/ObjectBuilder.hack b/src/Codegen/Builders/ObjectBuilder.hack index 413e662..28672bc 100644 --- a/src/Codegen/Builders/ObjectBuilder.hack +++ b/src/Codegen/Builders/ObjectBuilder.hack @@ -74,13 +74,11 @@ class ObjectBuilder extends CompositeBuilder { 'type' => $edge_name.'::nonNullable()->nullableOutputListOf()', 'needs_await' => true, ), - 'parameters' => vec[], )), new MethodFieldBuilder(shape( 'name' => 'pageInfo', 'method_name' => 'getPageInfo', 'output_type' => shape('type' => 'PageInfo::nullableOutput()', 'needs_await' => true), - 'parameters' => vec[], )), ], dict[], // Connections do not implement any interfaces @@ -98,13 +96,11 @@ class ObjectBuilder extends CompositeBuilder { 'name' => 'node', 'method_name' => 'getNode', 'output_type' => shape('type' => $output_type.'::nullableOutput()'), - 'parameters' => vec[], )), new MethodFieldBuilder(shape( 'name' => 'cursor', 'method_name' => 'getCursor', 'output_type' => shape('type' => 'Types\StringType::nullableOutput()'), - 'parameters' => vec[], )), ], dict[], diff --git a/src/Field.hack b/src/Field.hack index ec775af..dd12a03 100644 --- a/src/Field.hack +++ b/src/Field.hack @@ -9,6 +9,10 @@ class Field implements \HH\MethodAttribute { public function getName(): string { return $this->name; } + + public function getDescription(): string { + return $this->description; + } } /** @@ -30,6 +34,4 @@ class Field implements \HH\MethodAttribute { * * @see https://spec.graphql.org/draft/#sec-Handling-Field-Errors */ -final class KillsParentOnException implements \HH\MethodAttribute { - public function __construct() {} -} +final class KillsParentOnException implements \HH\MethodAttribute {} diff --git a/src/FieldDefinition.hack b/src/FieldDefinition.hack index 4c965aa..d9cc26e 100644 --- a/src/FieldDefinition.hack +++ b/src/FieldDefinition.hack @@ -29,6 +29,8 @@ final class FieldDefinition implements IResolvableFiel dict, Variables, ): Awaitable) $resolver, + private ?string $description, + private ?string $deprecation_reason = null, ) {} public async function resolveAsync( @@ -67,18 +69,15 @@ final class FieldDefinition implements IResolvableFiel } public function getDeprecationReason(): ?string { - // TODO - return null; + return $this->deprecation_reason; } public function isDeprecated(): bool { - // TODO - return false; + return $this->getDeprecationReason() is nonnull; } public function getDescription(): ?string { - // TODO - return null; + return $this->description; } public function getArgs(): vec { diff --git a/tests/Fixtures/IntrospectionTestObjects.hack b/tests/Fixtures/IntrospectionTestObjects.hack index b3ba52e..3cb2096 100644 --- a/tests/Fixtures/IntrospectionTestObjects.hack +++ b/tests/Fixtures/IntrospectionTestObjects.hack @@ -67,7 +67,7 @@ final class IntrospectionTestObject { return null; } - <> + <> public function getNonNullInt(): int { return 1; } @@ -87,4 +87,9 @@ final class IntrospectionTestObject { return vec[null]; } + <> + public function getDeprecated(): string { + return 'deprecated'; + } + } diff --git a/tests/IntrospectionTest.hack b/tests/IntrospectionTest.hack index 1a6aadc..ad5f85d 100644 --- a/tests/IntrospectionTest.hack +++ b/tests/IntrospectionTest.hack @@ -269,6 +269,7 @@ final class IntrospectionTest extends FixtureTest { name fields { name + description type { kind name @@ -285,6 +286,8 @@ final class IntrospectionTest extends FixtureTest { } } } + isDeprecated + deprecationReason } } }', @@ -295,6 +298,7 @@ final class IntrospectionTest extends FixtureTest { 'fields' => vec[ dict[ 'name' => 'default_list_of_non_nullable_int', + 'description' => 'Default list of non nullable int', 'type' => dict[ 'kind' => 'LIST', 'name' => null, @@ -308,9 +312,12 @@ final class IntrospectionTest extends FixtureTest { ], ], ], + 'isDeprecated' => false, + 'deprecationReason' => null, ], dict[ 'name' => 'default_list_of_nullable_int', + 'description' => 'Default list of nullable int', 'type' => dict[ 'kind' => 'LIST', 'name' => null, @@ -320,17 +327,34 @@ final class IntrospectionTest extends FixtureTest { 'ofType' => null, ], ], + 'isDeprecated' => false, + 'deprecationReason' => null, ], dict[ 'name' => 'default_nullable_string', + 'description' => 'Default nullable string', + 'type' => dict[ + 'kind' => 'SCALAR', + 'name' => 'String', + 'ofType' => null, + ], + 'isDeprecated' => false, + 'deprecationReason' => null, + ], + dict[ + 'name' => 'deprecated_field', + 'description' => 'Deprecated field', 'type' => dict[ 'kind' => 'SCALAR', 'name' => 'String', 'ofType' => null, ], + 'isDeprecated' => true, + 'deprecationReason' => 'Deprecated for testing', ], dict[ 'name' => 'non_null_int', + 'description' => 'Non nullable int', 'type' => dict[ 'kind' => 'NON_NULL', 'name' => null, @@ -340,9 +364,12 @@ final class IntrospectionTest extends FixtureTest { 'ofType' => null, ], ], + 'isDeprecated' => false, + 'deprecationReason' => null, ], dict[ 'name' => 'non_null_list_of_non_null', + 'description' => 'Non nullable list of non nullables', 'type' => dict[ 'kind' => 'NON_NULL', 'name' => null, @@ -359,9 +386,12 @@ final class IntrospectionTest extends FixtureTest { ], ], ], + 'isDeprecated' => false, + 'deprecationReason' => null, ], dict[ 'name' => 'non_null_string', + 'description' => 'Non nullable string', 'type' => dict[ 'kind' => 'NON_NULL', 'name' => null, @@ -371,14 +401,19 @@ final class IntrospectionTest extends FixtureTest { 'ofType' => null, ], ], + 'isDeprecated' => false, + 'deprecationReason' => null, ], dict[ 'name' => 'nullable_string', + 'description' => 'Nullable string', 'type' => dict[ 'kind' => 'SCALAR', 'name' => 'String', 'ofType' => null, ], + 'isDeprecated' => false, + 'deprecationReason' => null, ], ], ], diff --git a/tests/gen/AlphabetConnection.hack b/tests/gen/AlphabetConnection.hack index 8f6b988..a289b0c 100644 --- a/tests/gen/AlphabetConnection.hack +++ b/tests/gen/AlphabetConnection.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<62edee806dca502f5b400aefff59f52a>> + * @generated SignedSource<<28a23bb2fbfd1ea78d4867cfa9f92f20>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -32,6 +32,8 @@ final class AlphabetConnection extends \Slack\GraphQL\Types\ObjectType { StringTypeEdge::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> await $parent->getEdges(), + null, + null, ); case 'pageInfo': return new GraphQL\FieldDefinition( @@ -39,6 +41,8 @@ final class AlphabetConnection extends \Slack\GraphQL\Types\ObjectType { PageInfo::nullableOutput(), dict[], async ($parent, $args, $vars) ==> await $parent->getPageInfo(), + null, + null, ); default: return null; diff --git a/tests/gen/AnotherObjectShape.hack b/tests/gen/AnotherObjectShape.hack index 1f5b18f..52f127f 100644 --- a/tests/gen/AnotherObjectShape.hack +++ b/tests/gen/AnotherObjectShape.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<1df6595e51f53c069509e4a7216ba04f>> + * @generated SignedSource<<1563ad2b8703b4a0a402edf70519ea18>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -31,6 +31,8 @@ final class AnotherObjectShape extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent['abc'], + null, + null, ); default: return null; diff --git a/tests/gen/Bot.hack b/tests/gen/Bot.hack index aee6b1a..b747b1f 100644 --- a/tests/gen/Bot.hack +++ b/tests/gen/Bot.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<803c718476e0461c3e9d70a1db853f34>> + * @generated SignedSource<> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -36,6 +36,8 @@ final class Bot extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getId(), + 'ID of the user', + null, ); case 'is_active': return new GraphQL\FieldDefinition( @@ -43,6 +45,8 @@ final class Bot extends \Slack\GraphQL\Types\ObjectType { Types\BooleanType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->isActive(), + 'Whether the user is active', + null, ); case 'name': return new GraphQL\FieldDefinition( @@ -50,6 +54,8 @@ final class Bot extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getName(), + 'Name of the user', + null, ); case 'primary_function': return new GraphQL\FieldDefinition( @@ -57,6 +63,8 @@ final class Bot extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getPrimaryFunction(), + 'Intended use of the bot', + null, ); case 'team': return new GraphQL\FieldDefinition( @@ -64,6 +72,8 @@ final class Bot extends \Slack\GraphQL\Types\ObjectType { Team::nullableOutput(), dict[], async ($parent, $args, $vars) ==> await $parent->getTeam(), + 'Team the user belongs to', + null, ); default: return null; diff --git a/tests/gen/Concrete.hack b/tests/gen/Concrete.hack index 05cbb58..0d0454b 100644 --- a/tests/gen/Concrete.hack +++ b/tests/gen/Concrete.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<5e33a7e29516c49900df494dac33f7f5>> + * @generated SignedSource<> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -35,6 +35,8 @@ final class Concrete extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->bar(), + 'bar', + null, ); case 'baz': return new GraphQL\FieldDefinition( @@ -42,6 +44,8 @@ final class Concrete extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->baz(), + 'baz', + null, ); case 'foo': return new GraphQL\FieldDefinition( @@ -49,6 +53,8 @@ final class Concrete extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->foo(), + 'foo', + null, ); default: return null; diff --git a/tests/gen/ErrorTestObj.hack b/tests/gen/ErrorTestObj.hack index b2e43e0..e7ee1df 100644 --- a/tests/gen/ErrorTestObj.hack +++ b/tests/gen/ErrorTestObj.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<4938ded1db5fdd04f9875088d7f4978d>> + * @generated SignedSource<<0a268b891ecb99ff27ff68d02d8ed3f9>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -42,6 +42,8 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->bad_int_list_n_of_n(), + null, + null, ); case 'bad_int_list_n_of_nn': return new GraphQL\FieldDefinition( @@ -49,6 +51,8 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->bad_int_list_n_of_nn(), + 'Nullability of nested types is respected, which may result in killing the whole list (but no parents)', + null, ); case 'bad_int_list_nn_of_nn': return new GraphQL\FieldDefinition( @@ -56,6 +60,8 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nonNullable()->nonNullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->bad_int_list_nn_of_nn(), + null, + null, ); case 'hidden_exception': return new GraphQL\FieldDefinition( @@ -63,6 +69,8 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->hidden_exception(), + 'Arbitrary exceptions are hidden from clients, since they might contain sensitive data', + null, ); case 'nested': return new GraphQL\FieldDefinition( @@ -70,6 +78,8 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { ErrorTestObj::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->nested(), + null, + null, ); case 'nested_list_n_of_n': return new GraphQL\FieldDefinition( @@ -77,6 +87,8 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { ErrorTestObj::nullableOutput()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->nested_list_n_of_n(), + null, + null, ); case 'nested_list_n_of_nn': return new GraphQL\FieldDefinition( @@ -84,6 +96,8 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { ErrorTestObj::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->nested_list_n_of_nn(), + null, + null, ); case 'nested_list_nn_of_nn': return new GraphQL\FieldDefinition( @@ -91,6 +105,8 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { ErrorTestObj::nonNullable()->nonNullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->nested_list_nn_of_nn(), + null, + null, ); case 'nested_nn': return new GraphQL\FieldDefinition( @@ -98,6 +114,8 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { ErrorTestObj::nonNullable(), dict[], async ($parent, $args, $vars) ==> $parent->nested_nn(), + null, + null, ); case 'no_error': return new GraphQL\FieldDefinition( @@ -105,6 +123,8 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->no_error(), + null, + null, ); case 'non_nullable': return new GraphQL\FieldDefinition( @@ -112,6 +132,8 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nonNullable(), dict[], async ($parent, $args, $vars) ==> $parent->non_nullable(), + null, + null, ); case 'user_facing_error': return new GraphQL\FieldDefinition( @@ -119,6 +141,8 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->user_facing_error(), + null, + null, ); default: return null; diff --git a/tests/gen/Human.hack b/tests/gen/Human.hack index e2a2d27..b62e363 100644 --- a/tests/gen/Human.hack +++ b/tests/gen/Human.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<453bfb5200271c708353fecfc025619b>> + * @generated SignedSource<<6dcb233c0846538dfa0a620a12aee762>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -38,6 +38,8 @@ final class Human extends \Slack\GraphQL\Types\ObjectType { FavoriteColor::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getFavoriteColor(), + 'Favorite color of the user', + null, ); case 'friends': return new GraphQL\FieldDefinition( @@ -71,6 +73,8 @@ final class Human extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableInput()->coerceOptionalNamedNode('first', $args, $vars, null), Types\IntType::nullableInput()->coerceOptionalNamedNode('last', $args, $vars, null), ), + 'Friends', + null, ); case 'id': return new GraphQL\FieldDefinition( @@ -78,6 +82,8 @@ final class Human extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getId(), + 'ID of the user', + null, ); case 'is_active': return new GraphQL\FieldDefinition( @@ -85,6 +91,8 @@ final class Human extends \Slack\GraphQL\Types\ObjectType { Types\BooleanType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->isActive(), + 'Whether the user is active', + null, ); case 'name': return new GraphQL\FieldDefinition( @@ -92,6 +100,8 @@ final class Human extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getName(), + 'Name of the user', + null, ); case 'named_friends': return new GraphQL\FieldDefinition( @@ -131,6 +141,8 @@ final class Human extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableInput()->coerceOptionalNamedNode('first', $args, $vars, null), Types\IntType::nullableInput()->coerceOptionalNamedNode('last', $args, $vars, null), ), + 'Test that we can pass args to a field which returns a connection', + null, ); case 'team': return new GraphQL\FieldDefinition( @@ -138,6 +150,8 @@ final class Human extends \Slack\GraphQL\Types\ObjectType { Team::nullableOutput(), dict[], async ($parent, $args, $vars) ==> await $parent->getTeam(), + 'Team the user belongs to', + null, ); default: return null; diff --git a/tests/gen/InterfaceA.hack b/tests/gen/InterfaceA.hack index ba89bb8..9f57606 100644 --- a/tests/gen/InterfaceA.hack +++ b/tests/gen/InterfaceA.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<2692931475deaf2db40669c79479288f>> + * @generated SignedSource<> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -32,6 +32,8 @@ final class InterfaceA extends \Slack\GraphQL\Types\InterfaceType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->foo(), + 'foo', + null, ); default: return null; diff --git a/tests/gen/InterfaceB.hack b/tests/gen/InterfaceB.hack index 483b134..30a2738 100644 --- a/tests/gen/InterfaceB.hack +++ b/tests/gen/InterfaceB.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<> + * @generated SignedSource<<0ae35d65b1e919260db248fbaaab5018>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -33,6 +33,8 @@ final class InterfaceB extends \Slack\GraphQL\Types\InterfaceType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->bar(), + 'bar', + null, ); case 'foo': return new GraphQL\FieldDefinition( @@ -40,6 +42,8 @@ final class InterfaceB extends \Slack\GraphQL\Types\InterfaceType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->foo(), + 'foo', + null, ); default: return null; diff --git a/tests/gen/IntrospectionTestObject.hack b/tests/gen/IntrospectionTestObject.hack index 7a1644b..d0127e9 100644 --- a/tests/gen/IntrospectionTestObject.hack +++ b/tests/gen/IntrospectionTestObject.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<2ec633867a1874f20746329c497145ab>> + * @generated SignedSource<<93ec72ecc482e1cdffed6c2cee788a99>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -19,6 +19,7 @@ final class IntrospectionTestObject extends \Slack\GraphQL\Types\ObjectType { 'default_list_of_non_nullable_int', 'default_list_of_nullable_int', 'default_nullable_string', + 'deprecated_field', 'non_null_int', 'non_null_list_of_non_null', 'non_null_string', @@ -37,6 +38,8 @@ final class IntrospectionTestObject extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->getDefaultListOfNonNullableInt(), + 'Default list of non nullable int', + null, ); case 'default_list_of_nullable_int': return new GraphQL\FieldDefinition( @@ -44,6 +47,8 @@ final class IntrospectionTestObject extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->getDefaultListOfNullableInt(), + 'Default list of nullable int', + null, ); case 'default_nullable_string': return new GraphQL\FieldDefinition( @@ -51,6 +56,17 @@ final class IntrospectionTestObject extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getDefaultNullableString(), + 'Default nullable string', + null, + ); + case 'deprecated_field': + return new GraphQL\FieldDefinition( + 'deprecated_field', + Types\StringType::nullableOutput(), + dict[], + async ($parent, $args, $vars) ==> /* HH_FIXME[4128] Deprecated */ $parent->getDeprecated(), + 'Deprecated field', + 'Deprecated for testing', ); case 'non_null_int': return new GraphQL\FieldDefinition( @@ -58,6 +74,8 @@ final class IntrospectionTestObject extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nonNullable(), dict[], async ($parent, $args, $vars) ==> $parent->getNonNullInt(), + 'Non nullable int', + null, ); case 'non_null_list_of_non_null': return new GraphQL\FieldDefinition( @@ -65,6 +83,8 @@ final class IntrospectionTestObject extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nonNullable()->nonNullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->getNonNullListOfNonNull(), + 'Non nullable list of non nullables', + null, ); case 'non_null_string': return new GraphQL\FieldDefinition( @@ -72,6 +92,8 @@ final class IntrospectionTestObject extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nonNullable(), dict[], async ($parent, $args, $vars) ==> $parent->getNonNullString(), + 'Non nullable string', + null, ); case 'nullable_string': return new GraphQL\FieldDefinition( @@ -79,6 +101,8 @@ final class IntrospectionTestObject extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getNullableString(), + 'Nullable string', + null, ); default: return null; diff --git a/tests/gen/Mutation.hack b/tests/gen/Mutation.hack index 5a134de..fbe9b47 100644 --- a/tests/gen/Mutation.hack +++ b/tests/gen/Mutation.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<8effc458f88d700e19fc5f34452ec88f>> + * @generated SignedSource<> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -39,6 +39,8 @@ final class Mutation extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> await \UserMutationAttributes::createUser( CreateUserInput::nonNullable()->coerceNamedNode('input', $args, $vars), ), + 'Create a new user', + null, ); case 'pokeUser': return new GraphQL\FieldDefinition( @@ -53,6 +55,8 @@ final class Mutation extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> await \UserMutationAttributes::pokeUser( Types\IntType::nonNullable()->coerceNamedNode('id', $args, $vars), ), + 'Poke a user by ID', + null, ); default: return null; diff --git a/tests/gen/NestedOutputShape.hack b/tests/gen/NestedOutputShape.hack index 389f7c5..63f173f 100644 --- a/tests/gen/NestedOutputShape.hack +++ b/tests/gen/NestedOutputShape.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<5e9816ae88463151bbbadeb9b46700a7>> + * @generated SignedSource<> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -31,6 +31,8 @@ final class NestedOutputShape extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent['vec_of_string'], + null, + null, ); default: return null; diff --git a/tests/gen/ObjectShape.hack b/tests/gen/ObjectShape.hack index 9b63d57..b1ee2ed 100644 --- a/tests/gen/ObjectShape.hack +++ b/tests/gen/ObjectShape.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<4ee05a200f698afc8c2432c2a1b97359>> + * @generated SignedSource<<027a6e395bf5daeaf63e42a377209c62>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -33,6 +33,8 @@ final class ObjectShape extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['foo'], + null, + null, ); case 'bar': return new GraphQL\FieldDefinition( @@ -40,6 +42,8 @@ final class ObjectShape extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['bar'] ?? null, + null, + null, ); case 'baz': return new GraphQL\FieldDefinition( @@ -47,6 +51,8 @@ final class ObjectShape extends \Slack\GraphQL\Types\ObjectType { AnotherObjectShape::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['baz'], + null, + null, ); default: return null; diff --git a/tests/gen/OutputShape.hack b/tests/gen/OutputShape.hack index 10c4a20..c202587 100644 --- a/tests/gen/OutputShape.hack +++ b/tests/gen/OutputShape.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<> + * @generated SignedSource<<29784fefb527a1c0923f4913df884416>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -33,6 +33,8 @@ final class OutputShape extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['string'], + null, + null, ); case 'vec_of_int': return new GraphQL\FieldDefinition( @@ -40,6 +42,8 @@ final class OutputShape extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent['vec_of_int'], + null, + null, ); case 'nested_shape': return new GraphQL\FieldDefinition( @@ -47,6 +51,8 @@ final class OutputShape extends \Slack\GraphQL\Types\ObjectType { NestedOutputShape::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['nested_shape'], + null, + null, ); default: return null; diff --git a/tests/gen/OutputTypeTestObj.hack b/tests/gen/OutputTypeTestObj.hack index aab4325..c80183f 100644 --- a/tests/gen/OutputTypeTestObj.hack +++ b/tests/gen/OutputTypeTestObj.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<> + * @generated SignedSource<<7c66631690dca9d26e83298fd9af017a>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -38,6 +38,8 @@ final class OutputTypeTestObj extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> await $parent->awaitable(), + null, + null, ); case 'awaitable_nullable': return new GraphQL\FieldDefinition( @@ -45,6 +47,8 @@ final class OutputTypeTestObj extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> await $parent->awaitable_nullable(), + null, + null, ); case 'awaitable_nullable_list': return new GraphQL\FieldDefinition( @@ -52,6 +56,8 @@ final class OutputTypeTestObj extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> await $parent->awaitable_nullable_list(), + null, + null, ); case 'list': return new GraphQL\FieldDefinition( @@ -59,6 +65,8 @@ final class OutputTypeTestObj extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->list(), + null, + null, ); case 'nested_lists': return new GraphQL\FieldDefinition( @@ -66,6 +74,8 @@ final class OutputTypeTestObj extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput()->nonNullableOutputListOf()->nullableOutputListOf()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->nested_lists(), + 'Note that nested lists can be non-nullable', + null, ); case 'nullable': return new GraphQL\FieldDefinition( @@ -73,6 +83,8 @@ final class OutputTypeTestObj extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->nullable(), + null, + null, ); case 'output_shape': return new GraphQL\FieldDefinition( @@ -80,6 +92,8 @@ final class OutputTypeTestObj extends \Slack\GraphQL\Types\ObjectType { OutputShape::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->output_shape(), + null, + null, ); case 'scalar': return new GraphQL\FieldDefinition( @@ -87,6 +101,8 @@ final class OutputTypeTestObj extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->scalar(), + 'Note that the GraphQL field will be nullable by default, despite its non-nullable Hack type', + null, ); default: return null; diff --git a/tests/gen/PageInfo.hack b/tests/gen/PageInfo.hack index 93c39c7..e9788d7 100644 --- a/tests/gen/PageInfo.hack +++ b/tests/gen/PageInfo.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<> + * @generated SignedSource<<77dade56f824ad0618c83d99f2e67c83>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -34,6 +34,8 @@ final class PageInfo extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['startCursor'] ?? null, + null, + null, ); case 'endCursor': return new GraphQL\FieldDefinition( @@ -41,6 +43,8 @@ final class PageInfo extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['endCursor'] ?? null, + null, + null, ); case 'hasPreviousPage': return new GraphQL\FieldDefinition( @@ -48,6 +52,8 @@ final class PageInfo extends \Slack\GraphQL\Types\ObjectType { Types\BooleanType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['hasPreviousPage'] ?? null, + null, + null, ); case 'hasNextPage': return new GraphQL\FieldDefinition( @@ -55,6 +61,8 @@ final class PageInfo extends \Slack\GraphQL\Types\ObjectType { Types\BooleanType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['hasNextPage'] ?? null, + null, + null, ); default: return null; diff --git a/tests/gen/Query.hack b/tests/gen/Query.hack index 9da502b..ff72a69 100644 --- a/tests/gen/Query.hack +++ b/tests/gen/Query.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<> + * @generated SignedSource<<22d2455b45e30b3d6e20f3dc010d7761>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -48,6 +48,8 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { __Schema::nullableOutput(), dict[], async ($parent, $args, $vars) ==> new Schema(), + null, + null, ); case '__type': return new GraphQL\FieldDefinition( @@ -63,6 +65,8 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nonNullable()->coerceNamedNode('name', $args, $vars), ), + null, + null, ); case 'alphabetConnection': return new GraphQL\FieldDefinition( @@ -96,6 +100,8 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableInput()->coerceOptionalNamedNode('first', $args, $vars, null), Types\IntType::nullableInput()->coerceOptionalNamedNode('last', $args, $vars, null), ), + 'Test for list connection', + null, ); case 'arg_test': return new GraphQL\FieldDefinition( @@ -121,6 +127,8 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableInput()->coerceNamedNode('nullable', $args, $vars), Types\IntType::nullableInput()->coerceOptionalNamedNode('optional', $args, $vars, 42), ), + 'Root field for testing arguments', + null, ); case 'bot': return new GraphQL\FieldDefinition( @@ -135,6 +143,8 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> await \UserQueryAttributes::getBot( Types\IntType::nonNullable()->coerceNamedNode('id', $args, $vars), ), + 'Fetch a bot by ID', + null, ); case 'error_test': return new GraphQL\FieldDefinition( @@ -142,6 +152,8 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { ErrorTestObj::nullableOutput(), dict[], async ($parent, $args, $vars) ==> \ErrorTestObj::get(), + 'Root field to get an instance', + null, ); case 'error_test_nn': return new GraphQL\FieldDefinition( @@ -149,6 +161,8 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { ErrorTestObj::nonNullable(), dict[], async ($parent, $args, $vars) ==> \ErrorTestObj::getNonNullable(), + 'A non-nullable root field to get an instance', + null, ); case 'getConcrete': return new GraphQL\FieldDefinition( @@ -156,6 +170,8 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { Concrete::nullableOutput(), dict[], async ($parent, $args, $vars) ==> \Concrete::getConcrete(), + 'Root field to get an instance of Concrete', + null, ); case 'getInterfaceA': return new GraphQL\FieldDefinition( @@ -163,6 +179,8 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { InterfaceA::nullableOutput(), dict[], async ($parent, $args, $vars) ==> \Concrete::getInterfaceA(), + 'Root field to get an instance of InterfaceA', + null, ); case 'getInterfaceB': return new GraphQL\FieldDefinition( @@ -170,6 +188,8 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { InterfaceB::nullableOutput(), dict[], async ($parent, $args, $vars) ==> \Concrete::getInterfaceB(), + 'Root field to get an instance of InterfaceB', + null, ); case 'getObjectShape': return new GraphQL\FieldDefinition( @@ -177,6 +197,8 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { ObjectShape::nullableOutput(), dict[], async ($parent, $args, $vars) ==> \ObjectTypeTestEntrypoint::getObjectShape(), + 'fetch an object shape', + null, ); case 'human': return new GraphQL\FieldDefinition( @@ -191,6 +213,8 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> await \UserQueryAttributes::getHuman( Types\IntType::nonNullable()->coerceNamedNode('id', $args, $vars), ), + 'Fetch a user by ID', + null, ); case 'introspection_test': return new GraphQL\FieldDefinition( @@ -198,6 +222,8 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { IntrospectionTestObject::nullableOutput(), dict[], async ($parent, $args, $vars) ==> \IntrospectionTestObject::get(), + 'Root field to get an instance', + null, ); case 'list_arg_test': return new GraphQL\FieldDefinition( @@ -212,6 +238,8 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> \ArgumentTestObj::listArgTest( Types\IntType::nonNullable()->nullableInputListOf()->nonNullableInputListOf()->nullableInputListOf()->coerceNamedNode('arg', $args, $vars), ), + 'Root field for testing list arguments', + null, ); case 'nested_list_sum': return new GraphQL\FieldDefinition( @@ -226,6 +254,8 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> \UserQueryAttributes::getNestedListSum( Types\IntType::nonNullable()->nonNullableInputListOf()->nonNullableInputListOf()->coerceNamedNode('numbers', $args, $vars), ), + 'Test for nested list arguments', + null, ); case 'optional_field_test': return new GraphQL\FieldDefinition( @@ -240,6 +270,8 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> \UserQueryAttributes::optionalFieldTest( CreateUserInput::nonNullable()->coerceNamedNode('input', $args, $vars), ), + 'Test for an optional input object field', + null, ); case 'output_type_test': return new GraphQL\FieldDefinition( @@ -247,6 +279,8 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { OutputTypeTestObj::nullableOutput(), dict[], async ($parent, $args, $vars) ==> \OutputTypeTestObj::get(), + 'Root field to get an instance', + null, ); case 'takes_favorite_color': return new GraphQL\FieldDefinition( @@ -261,6 +295,8 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> \UserQueryAttributes::takesFavoriteColor( FavoriteColor::nonNullable()->coerceNamedNode('favorite_color', $args, $vars), ), + 'Test for enum arguments', + null, ); case 'user': return new GraphQL\FieldDefinition( @@ -275,6 +311,8 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> await \UserQueryAttributes::getUser( Types\IntType::nonNullable()->coerceNamedNode('id', $args, $vars), ), + 'Fetch a user by ID', + null, ); case 'viewer': return new GraphQL\FieldDefinition( @@ -282,6 +320,8 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { User::nullableOutput(), dict[], async ($parent, $args, $vars) ==> await \UserQueryAttributes::getViewer(), + 'Authenticated viewer', + null, ); default: return null; diff --git a/tests/gen/StringTypeEdge.hack b/tests/gen/StringTypeEdge.hack index 27333d5..e239d95 100644 --- a/tests/gen/StringTypeEdge.hack +++ b/tests/gen/StringTypeEdge.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<9edbef9197acde53464ef3e6c06253e3>> + * @generated SignedSource<> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -32,6 +32,8 @@ final class StringTypeEdge extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getNode(), + null, + null, ); case 'cursor': return new GraphQL\FieldDefinition( @@ -39,6 +41,8 @@ final class StringTypeEdge extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getCursor(), + null, + null, ); default: return null; diff --git a/tests/gen/Team.hack b/tests/gen/Team.hack index d541d9d..e219522 100644 --- a/tests/gen/Team.hack +++ b/tests/gen/Team.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<42f8451c72c0c7713661e2da057f8902>> + * @generated SignedSource<<4101af3b5a52deed789cbd661b9a8b0d>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -41,6 +41,8 @@ final class Team extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> $parent->getDescription( Types\BooleanType::nonNullable()->coerceNamedNode('short', $args, $vars), ), + 'Description of the team', + null, ); case 'id': return new GraphQL\FieldDefinition( @@ -48,6 +50,8 @@ final class Team extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getId(), + 'ID of the team', + null, ); case 'name': return new GraphQL\FieldDefinition( @@ -55,6 +59,8 @@ final class Team extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getName(), + 'Name of the team', + null, ); case 'num_users': return new GraphQL\FieldDefinition( @@ -62,6 +68,8 @@ final class Team extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> await $parent->getNumUsers(), + 'Number of users on the team', + null, ); default: return null; diff --git a/tests/gen/User.hack b/tests/gen/User.hack index 77678fb..2d21adb 100644 --- a/tests/gen/User.hack +++ b/tests/gen/User.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<481a5396998f1863b06a6992d837fe3b>> + * @generated SignedSource<<3f80380271d776f8efd8825d50e067d7>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -36,6 +36,8 @@ final class User extends \Slack\GraphQL\Types\InterfaceType { Types\IntType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getId(), + 'ID of the user', + null, ); case 'is_active': return new GraphQL\FieldDefinition( @@ -43,6 +45,8 @@ final class User extends \Slack\GraphQL\Types\InterfaceType { Types\BooleanType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->isActive(), + 'Whether the user is active', + null, ); case 'name': return new GraphQL\FieldDefinition( @@ -50,6 +54,8 @@ final class User extends \Slack\GraphQL\Types\InterfaceType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getName(), + 'Name of the user', + null, ); case 'team': return new GraphQL\FieldDefinition( @@ -57,6 +63,8 @@ final class User extends \Slack\GraphQL\Types\InterfaceType { Team::nullableOutput(), dict[], async ($parent, $args, $vars) ==> await $parent->getTeam(), + 'Team the user belongs to', + null, ); default: return null; diff --git a/tests/gen/UserConnection.hack b/tests/gen/UserConnection.hack index f43672f..93c94c4 100644 --- a/tests/gen/UserConnection.hack +++ b/tests/gen/UserConnection.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<10f75bca86cba0f89742c4b2faf55f99>> + * @generated SignedSource<<54bd192726634acf19f8a1b2080e2b3b>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -32,6 +32,8 @@ final class UserConnection extends \Slack\GraphQL\Types\ObjectType { UserEdge::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> await $parent->getEdges(), + null, + null, ); case 'pageInfo': return new GraphQL\FieldDefinition( @@ -39,6 +41,8 @@ final class UserConnection extends \Slack\GraphQL\Types\ObjectType { PageInfo::nullableOutput(), dict[], async ($parent, $args, $vars) ==> await $parent->getPageInfo(), + null, + null, ); default: return null; diff --git a/tests/gen/UserEdge.hack b/tests/gen/UserEdge.hack index f19bb53..689f26c 100644 --- a/tests/gen/UserEdge.hack +++ b/tests/gen/UserEdge.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<10bd530f34fa766a0c89a1f81e8f8ad3>> + * @generated SignedSource<<9925c3d082ffd4d43aa08bc530735963>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -32,6 +32,8 @@ final class UserEdge extends \Slack\GraphQL\Types\ObjectType { User::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getNode(), + null, + null, ); case 'cursor': return new GraphQL\FieldDefinition( @@ -39,6 +41,8 @@ final class UserEdge extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getCursor(), + null, + null, ); default: return null; diff --git a/tests/gen/__Directive.hack b/tests/gen/__Directive.hack index 4853811..7f4713a 100644 --- a/tests/gen/__Directive.hack +++ b/tests/gen/__Directive.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<> + * @generated SignedSource<<796f38c47585b4bd8216598885e63d20>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -34,6 +34,8 @@ final class __Directive extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['name'], + null, + null, ); case 'description': return new GraphQL\FieldDefinition( @@ -41,6 +43,8 @@ final class __Directive extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['description'], + null, + null, ); case 'locations': return new GraphQL\FieldDefinition( @@ -48,6 +52,8 @@ final class __Directive extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent['locations'], + null, + null, ); case 'args': return new GraphQL\FieldDefinition( @@ -55,6 +61,8 @@ final class __Directive extends \Slack\GraphQL\Types\ObjectType { __InputValue::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent['args'], + null, + null, ); default: return null; diff --git a/tests/gen/__EnumValue.hack b/tests/gen/__EnumValue.hack index 7c8dfd0..1fd8101 100644 --- a/tests/gen/__EnumValue.hack +++ b/tests/gen/__EnumValue.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<2a376d1323cd8b83e6af8c63aa02034c>> + * @generated SignedSource<<79cc4c1ea40dd63c7dfe85f7089e9fb2>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -34,6 +34,8 @@ final class __EnumValue extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['name'], + null, + null, ); case 'isDeprecated': return new GraphQL\FieldDefinition( @@ -41,6 +43,8 @@ final class __EnumValue extends \Slack\GraphQL\Types\ObjectType { Types\BooleanType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['isDeprecated'], + null, + null, ); case 'description': return new GraphQL\FieldDefinition( @@ -48,6 +52,8 @@ final class __EnumValue extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['description'] ?? null, + null, + null, ); case 'deprecationReason': return new GraphQL\FieldDefinition( @@ -55,6 +61,8 @@ final class __EnumValue extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['deprecationReason'] ?? null, + null, + null, ); default: return null; diff --git a/tests/gen/__Field.hack b/tests/gen/__Field.hack index dd48c35..1a46e46 100644 --- a/tests/gen/__Field.hack +++ b/tests/gen/__Field.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<1d6ae474d70729d9c6200f3336b331be>> + * @generated SignedSource<<10c691da2cbe51607ac826b0daa0aa1e>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -36,6 +36,8 @@ final class __Field extends \Slack\GraphQL\Types\ObjectType { __InputValue::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->getArgs(), + 'Args of the field', + null, ); case 'deprecationReason': return new GraphQL\FieldDefinition( @@ -43,6 +45,8 @@ final class __Field extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getDeprecationReason(), + 'Reason the field was deprecated', + null, ); case 'description': return new GraphQL\FieldDefinition( @@ -50,6 +54,8 @@ final class __Field extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getDescription(), + 'Description of the field', + null, ); case 'isDeprecated': return new GraphQL\FieldDefinition( @@ -57,6 +63,8 @@ final class __Field extends \Slack\GraphQL\Types\ObjectType { Types\BooleanType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->isDeprecated(), + 'Boolean for whether or not the field is deprecated', + null, ); case 'name': return new GraphQL\FieldDefinition( @@ -64,6 +72,8 @@ final class __Field extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getName(), + 'Name of the field', + null, ); case 'type': return new GraphQL\FieldDefinition( @@ -71,6 +81,8 @@ final class __Field extends \Slack\GraphQL\Types\ObjectType { __Type::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getType(), + 'Type of the field', + null, ); default: return null; diff --git a/tests/gen/__InputValue.hack b/tests/gen/__InputValue.hack index 84df0d3..89ef46c 100644 --- a/tests/gen/__InputValue.hack +++ b/tests/gen/__InputValue.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<> + * @generated SignedSource<> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -34,6 +34,8 @@ final class __InputValue extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['name'], + null, + null, ); case 'description': return new GraphQL\FieldDefinition( @@ -41,6 +43,8 @@ final class __InputValue extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['description'] ?? null, + null, + null, ); case 'type': return new GraphQL\FieldDefinition( @@ -48,6 +52,8 @@ final class __InputValue extends \Slack\GraphQL\Types\ObjectType { __Type::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['type'], + null, + null, ); case 'defaultValue': return new GraphQL\FieldDefinition( @@ -55,6 +61,8 @@ final class __InputValue extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['defaultValue'] ?? null, + null, + null, ); default: return null; diff --git a/tests/gen/__Schema.hack b/tests/gen/__Schema.hack index a254d4f..9c8073e 100644 --- a/tests/gen/__Schema.hack +++ b/tests/gen/__Schema.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<> + * @generated SignedSource<> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -35,6 +35,8 @@ final class __Schema extends \Slack\GraphQL\Types\ObjectType { __Directive::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->getDirectives(), + 'Directives supported by the schema', + null, ); case 'mutationType': return new GraphQL\FieldDefinition( @@ -42,6 +44,8 @@ final class __Schema extends \Slack\GraphQL\Types\ObjectType { __Type::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getIntrospectionMutationType(), + 'Mutation root type', + null, ); case 'queryType': return new GraphQL\FieldDefinition( @@ -49,6 +53,8 @@ final class __Schema extends \Slack\GraphQL\Types\ObjectType { __Type::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getIntrospectionQueryType(), + 'Query root type', + null, ); case 'subscriptionType': return new GraphQL\FieldDefinition( @@ -56,6 +62,8 @@ final class __Schema extends \Slack\GraphQL\Types\ObjectType { __Type::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getIntrospectionSubscriptionType(), + 'Subscription root type', + null, ); case 'types': return new GraphQL\FieldDefinition( @@ -63,6 +71,8 @@ final class __Schema extends \Slack\GraphQL\Types\ObjectType { __Type::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->getTypes(), + 'Types contained within the schema', + null, ); default: return null; diff --git a/tests/gen/__Type.hack b/tests/gen/__Type.hack index 05376fb..fb5c756 100644 --- a/tests/gen/__Type.hack +++ b/tests/gen/__Type.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<46725fb0d0175c7f30579a28e030cf3b>> + * @generated SignedSource<<7cbd90ef4f45cdf1581e52cb4bde2388>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -39,6 +39,8 @@ final class __Type extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getIntrospectionDescription(), + 'Description of the type', + null, ); case 'enumValues': return new GraphQL\FieldDefinition( @@ -54,6 +56,8 @@ final class __Type extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> $parent->getIntrospectionEnumValues( Types\BooleanType::nonNullable()->coerceOptionalNamedNode('includeDeprecated', $args, $vars, false), ), + 'Enum values, only applies to ENUM', + null, ); case 'fields': return new GraphQL\FieldDefinition( @@ -69,6 +73,8 @@ final class __Type extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> $parent->getIntrospectionFields( Types\BooleanType::nonNullable()->coerceOptionalNamedNode('includeDeprecated', $args, $vars, false), ), + 'Fields of the type, only applies to OBJECT and INTERFACE', + null, ); case 'inputFields': return new GraphQL\FieldDefinition( @@ -76,6 +82,8 @@ final class __Type extends \Slack\GraphQL\Types\ObjectType { __InputValue::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->getIntrospectionInputFields(), + 'Input fields, only applies to INPUT_OBJECT', + null, ); case 'interfaces': return new GraphQL\FieldDefinition( @@ -83,6 +91,8 @@ final class __Type extends \Slack\GraphQL\Types\ObjectType { __Type::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->getIntrospectionInterfaces(), + 'Interfaces the object implements, only applies to OBJECT', + null, ); case 'kind': return new GraphQL\FieldDefinition( @@ -90,6 +100,8 @@ final class __Type extends \Slack\GraphQL\Types\ObjectType { __TypeKind::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getIntrospectionKind(), + 'Kind of the type', + null, ); case 'name': return new GraphQL\FieldDefinition( @@ -97,6 +109,8 @@ final class __Type extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getIntrospectionName(), + 'Name of the type', + null, ); case 'ofType': return new GraphQL\FieldDefinition( @@ -104,6 +118,8 @@ final class __Type extends \Slack\GraphQL\Types\ObjectType { __Type::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getIntrospectionOfType(), + 'Underlying wrapped type, only applies to NON_NULL and LIST', + null, ); case 'possibleTypes': return new GraphQL\FieldDefinition( @@ -111,6 +127,8 @@ final class __Type extends \Slack\GraphQL\Types\ObjectType { __Type::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->getIntrospectionPossibleTypes(), + 'Possible types that implement this interface, only applies to INTERFACE', + null, ); default: return null; diff --git a/tests/schema.json b/tests/schema.json index b1f1807..c155945 100644 --- a/tests/schema.json +++ b/tests/schema.json @@ -1091,6 +1091,17 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "deprecated_field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": true, + "deprecationReason": "Deprecated for testing" + }, { "name": "non_null_int", "args": [],