diff --git a/src/Codegen/Builders/CompositeBuilder.hack b/src/Codegen/Builders/CompositeBuilder.hack index d92ab8b..2f28dd5 100644 --- a/src/Codegen/Builders/CompositeBuilder.hack +++ b/src/Codegen/Builders/CompositeBuilder.hack @@ -19,11 +19,13 @@ use type Facebook\HackCodegen\{ * The annotated Hack type should be either a class, interface, or shape. */ abstract class CompositeBuilder extends OutputTypeBuilder<\Slack\GraphQL\__Private\CompositeType> { + use DirectivesBuilder; public function __construct( \Slack\GraphQL\__Private\CompositeType $type_info, string $hack_type, protected vec $fields, + protected dict> $directives, ) { parent::__construct($type_info, $hack_type); } @@ -31,6 +33,7 @@ abstract class CompositeBuilder extends OutputTypeBuilder<\Slack\GraphQL\__Priva public function build(HackCodegenFactory $cg): CodegenClass { return parent::build($cg) ->addMethod($this->generateGetFieldDefinition($cg)) + ->addMethod($this->generateGetDirectives($cg)) ->addConstant($this->generateFieldNamesConstant($cg, $this->getFieldNames())); } @@ -58,6 +61,18 @@ abstract class CompositeBuilder extends OutputTypeBuilder<\Slack\GraphQL\__Priva return $method; } + private function generateGetDirectives(HackCodegenFactory $cg): CodegenMethod { + $hb = hb($cg); + $hb->add('return '); + $hb = $this->buildDirectives($hb); + $hb->addLine(';'); + + return $cg->codegenMethod('getDirectives') + ->setPublic() + ->setReturnType('vec') + ->setBody($hb->getCode()); + } + final public function getFieldNames(): keyset { return Keyset\map($this->fields, $field ==> $field->getName()) |> Keyset\filter($$, $name ==> !Str\starts_with($name, '__')); diff --git a/src/Codegen/Builders/DirectivesBuilder.hack b/src/Codegen/Builders/DirectivesBuilder.hack new file mode 100644 index 0000000..01bc8c6 --- /dev/null +++ b/src/Codegen/Builders/DirectivesBuilder.hack @@ -0,0 +1,25 @@ + + + +namespace Slack\GraphQL\Codegen; + +use namespace HH\Lib\Str; +use type Facebook\HackCodegen\HackBuilder; + +trait DirectivesBuilder { + protected dict> $directives; + + protected function buildDirectives(HackBuilder $hb): HackBuilder { + if ($this->directives) { + $hb->addLine('vec[') + ->indent(); + foreach ($this->directives as $directive => $arguments) { + $hb->addLinef('new \%s(%s),', $directive, Str\join($arguments, ', ')); + } + $hb->unindent()->add(']'); + } else { + $hb->add('vec[]'); + } + return $hb; + } +} diff --git a/src/Codegen/Builders/Fields/FieldBuilder.hack b/src/Codegen/Builders/Fields/FieldBuilder.hack index 7a3ca5e..dfee822 100644 --- a/src/Codegen/Builders/Fields/FieldBuilder.hack +++ b/src/Codegen/Builders/Fields/FieldBuilder.hack @@ -10,10 +10,12 @@ use type Facebook\HackCodegen\{HackBuilder, HackBuilderValues}; * Base builder for constructing GraphQL fields. */ abstract class FieldBuilder { + use DirectivesBuilder; abstract const type TField as shape( 'name' => string, 'output_type' => shape('type' => string, ?'needs_await' => bool), + 'directives' => dict>, ... ); @@ -23,7 +25,11 @@ abstract class FieldBuilder { // Constructors - public function __construct(protected this::TField $data) {} + protected dict> $directives; + + public function __construct(protected this::TField $data) { + $this->directives = $data['directives']; + } /** * Construct a GraphQL field from a Hack method. @@ -31,6 +37,7 @@ abstract class FieldBuilder { public static function fromReflectionMethod( \Slack\GraphQL\Field $field, \ReflectionMethod $rm, + dict> $directives, bool $is_root_field = false, ): FieldBuilder { $data = shape( @@ -54,6 +61,7 @@ abstract class FieldBuilder { return $data; }, ), + 'directives' => $directives, ); if ($is_root_field) { @@ -75,14 +83,19 @@ abstract class FieldBuilder { 'name' => $name, 'output_type' => output_type(type_structure_to_type_alias($ts), false), 'is_optional' => Shapes::idx($ts, 'optional_shape_field') ?? false, + 'directives' => dict[], )); } /** * Construct a top-level GraphQL field. */ - public static function forRootField(\Slack\GraphQL\Field $field, \ReflectionMethod $rm): FieldBuilder { - return FieldBuilder::fromReflectionMethod($field, $rm, true); + public static function forRootField( + \Slack\GraphQL\Field $field, + \ReflectionMethod $rm, + dict> $directives, + ): FieldBuilder { + return FieldBuilder::fromReflectionMethod($field, $rm, $directives, true); } public static function introspectSchemaField(): FieldBuilder { @@ -126,6 +139,9 @@ abstract class FieldBuilder { $this->generateResolverBody($hb); $hb->addLine(','); + // Field directives + $hb = $this->buildDirectives($hb)->addLine(','); + // 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..9fbaa81 100644 --- a/src/Codegen/Builders/Fields/IntrospectionSchemaFieldBuilder.hack +++ b/src/Codegen/Builders/Fields/IntrospectionSchemaFieldBuilder.hack @@ -8,6 +8,7 @@ final class IntrospectSchemaFieldBuilder extends FieldBuilder { const type TField = shape( 'name' => string, 'output_type' => shape('type' => string, ?'needs_await' => bool), + 'directives' => dict>, ... ); @@ -15,6 +16,7 @@ final class IntrospectSchemaFieldBuilder extends FieldBuilder { parent::__construct(shape( 'name' => '__schema', 'output_type' => shape('type' => '__Schema::nullableOutput()'), + 'directives' => dict[], )); } diff --git a/src/Codegen/Builders/Fields/IntrospectionTypeFieldBuilder.hack b/src/Codegen/Builders/Fields/IntrospectionTypeFieldBuilder.hack index d10ac4c..dcf80be 100644 --- a/src/Codegen/Builders/Fields/IntrospectionTypeFieldBuilder.hack +++ b/src/Codegen/Builders/Fields/IntrospectionTypeFieldBuilder.hack @@ -15,6 +15,7 @@ final class IntrospectTypeFieldBuilder extends MethodFieldBuilder { 'parameters' => vec[ shape('name' => 'name', 'type' => 'HH\string', 'is_optional' => false), ], + 'directives' => dict[], )); } <<__Override>> diff --git a/src/Codegen/Builders/Fields/MethodFieldBuilder.hack b/src/Codegen/Builders/Fields/MethodFieldBuilder.hack index a0289cf..fb9f051 100644 --- a/src/Codegen/Builders/Fields/MethodFieldBuilder.hack +++ b/src/Codegen/Builders/Fields/MethodFieldBuilder.hack @@ -33,6 +33,7 @@ class MethodFieldBuilder extends FieldBuilder { 'method_name' => string, 'output_type' => shape('type' => string, ?'needs_await' => bool), 'parameters' => vec, + 'directives' => dict>, ?'root_field_for_type' => string, ?'is_static' => bool, ); diff --git a/src/Codegen/Builders/Fields/ShapeFieldBuilder.hack b/src/Codegen/Builders/Fields/ShapeFieldBuilder.hack index 6b1b37d..35b08e8 100644 --- a/src/Codegen/Builders/Fields/ShapeFieldBuilder.hack +++ b/src/Codegen/Builders/Fields/ShapeFieldBuilder.hack @@ -16,6 +16,7 @@ final class ShapeFieldBuilder extends FieldBuilder { 'name' => string, 'output_type' => shape('type' => string, ?'needs_await' => bool), 'is_optional' => bool, + 'directives' => dict>, ); <<__Override>> diff --git a/src/Codegen/Builders/InterfaceBuilder.hack b/src/Codegen/Builders/InterfaceBuilder.hack index 5becea0..1c84c7a 100644 --- a/src/Codegen/Builders/InterfaceBuilder.hack +++ b/src/Codegen/Builders/InterfaceBuilder.hack @@ -20,9 +20,10 @@ final class InterfaceBuilder extends CompositeBuilder { \Slack\GraphQL\__Private\CompositeType $type_info, string $hack_type, vec $fields, + dict> $directives, private dict $hack_class_to_graphql_object, ) { - parent::__construct($type_info, $hack_type, $fields); + parent::__construct($type_info, $hack_type, $fields, $directives); } <<__Override>> diff --git a/src/Codegen/Builders/ObjectBuilder.hack b/src/Codegen/Builders/ObjectBuilder.hack index c28c3ea..b8d3bef 100644 --- a/src/Codegen/Builders/ObjectBuilder.hack +++ b/src/Codegen/Builders/ObjectBuilder.hack @@ -20,9 +20,10 @@ class ObjectBuilder extends CompositeBuilder { \Slack\GraphQL\__Private\CompositeType $type_info, string $hack_type, vec $fields, + dict> $directives, private dict $hack_class_to_graphql_interface, ) { - parent::__construct($type_info, $hack_type, $fields); + parent::__construct($type_info, $hack_type, $fields, $directives); } <<__Override>> @@ -33,10 +34,10 @@ class ObjectBuilder extends CompositeBuilder { private function generateInterfacesConstant(HackCodegenFactory $cg): CodegenClassConstant { $interfaces = dict[]; - foreach ($this->hack_class_to_graphql_interface as $hack_class => $graphql_type) { - if (\is_subclass_of($this->hack_type, $hack_class)) { - $interfaces[$graphql_type] = Str\format('%s::class', $graphql_type); - } + foreach ( + get_interfaces($this->hack_type, $this->hack_class_to_graphql_interface) as $hack_class => $graphql_type + ) { + $interfaces[$graphql_type] = Str\format('%s::class', $graphql_type); } return $cg->codegenClassConstant('INTERFACES') @@ -58,11 +59,16 @@ class ObjectBuilder extends CompositeBuilder { $type_info, $type_alias->getName(), Vec\map_with_key($ts['fields'], ($name, $ts) ==> FieldBuilder::fromShapeField($name, $ts)), + dict[], // No directives (maybe we'll support them later) dict[], // Objects generated from shapes cannot implement interfaces ); } - public static function forConnection(string $name, string $edge_name): ObjectBuilder { + public static function forConnection( + string $name, + string $edge_name, + dict> $directives, + ): ObjectBuilder { // Remove namespace to generate a sane GQL name // This means that connections in different namespaces can collide with each other; // we could eventually fix that by merging the namespace and GQL name when @@ -81,14 +87,17 @@ class ObjectBuilder extends CompositeBuilder { 'needs_await' => true, ), 'parameters' => vec[], + 'directives' => dict[], )), new MethodFieldBuilder(shape( 'name' => 'pageInfo', 'method_name' => 'getPageInfo', 'output_type' => shape('type' => 'PageInfo::nullableOutput()', 'needs_await' => true), 'parameters' => vec[], + 'directives' => dict[], )), ], + $directives, dict[], // Connections do not implement any interfaces ); } @@ -105,14 +114,17 @@ class ObjectBuilder extends CompositeBuilder { 'method_name' => 'getNode', 'output_type' => shape('type' => $output_type.'::nullableOutput()'), 'parameters' => vec[], + 'directives' => dict[], )), new MethodFieldBuilder(shape( 'name' => 'cursor', 'method_name' => 'getCursor', 'output_type' => shape('type' => 'Types\StringType::nullableOutput()'), 'parameters' => vec[], + 'directives' => dict[], )), ], + dict[], // If we support custom edges, we'll want to support adding directives to them dict[], ); } diff --git a/src/Codegen/DirectivesFinder.hack b/src/Codegen/DirectivesFinder.hack new file mode 100644 index 0000000..4279274 --- /dev/null +++ b/src/Codegen/DirectivesFinder.hack @@ -0,0 +1,61 @@ + + + +namespace Slack\GraphQL\Codegen; + +use namespace HH\Lib\{C, Dict, Str, Vec}; + +final class DirectivesFinder { + public function __construct( + private shape( + ?'fields' => keyset>, + ?'objects' => keyset>, + ) $directives, + private dict $hack_class_to_graphql_interface, + ) {} + + public function findDirectivesForField(\ReflectionMethod $rm): dict> { + return self::findDirectives( + $this->directives['fields'] ?? keyset[], + $directive_type ==> $rm->getAttributeClass($directive_type), + ); + } + + public function findDirectivesForObject(\ReflectionClass $rc): dict> { + return vec[$rc->getName()] + |> Vec\concat( + $$, + get_interfaces($rc->getName(), $this->hack_class_to_graphql_interface) + |> Vec\keys($$), + ) + |> Vec\reverse($$) + |> Vec\map($$, $object_name ==> $this->findDirectivesForObjectName($object_name)) + |> Dict\merge(C\firstx($$), ...Vec\drop($$, 1)); + } + + <<__Memoize>> + private function findDirectivesForObjectName(string $object_name): dict> { + $rc = new \ReflectionClass($object_name); + return self::findDirectives( + $this->directives['objects'] ?? keyset[], + $directive_type ==> $rc->getAttributeClass($directive_type), + ); + } + + private static function findDirectives( + keyset> $custom_directive_types, + (function(classname): ?T) $getter, + ): dict> { + $directives = dict[]; + + foreach ($custom_directive_types as $directive_type) { + $directive = $getter($directive_type); + if ($directive is nonnull) { + $rc = new \ReflectionClass($directive); + $directives[$rc->getName()] = $directive->formatArgs(); + } + } + + return $directives; + } +} diff --git a/src/Codegen/FieldResolver.hack b/src/Codegen/FieldResolver.hack index c6b5ca1..4e567e9 100644 --- a/src/Codegen/FieldResolver.hack +++ b/src/Codegen/FieldResolver.hack @@ -14,7 +14,10 @@ final class FieldResolver { private dict $scanned_classes; private dict> $resolved_fields = dict[]; - public function __construct(vec $classes) { + public function __construct( + vec $classes, + private DirectivesFinder $directives_finder, + ) { $this->scanned_classes = Dict\from_values($classes, $class ==> $class->getName()); } @@ -69,7 +72,9 @@ final class FieldResolver { $graphql_field = $rm->getAttributeClass(\Slack\GraphQL\Field::class); if ($graphql_field is null) continue; - $fields[$graphql_field->getName()] = FieldBuilder::fromReflectionMethod($graphql_field, $rm); + $directives = $this->directives_finder->findDirectivesForField($rm); + + $fields[$graphql_field->getName()] = FieldBuilder::fromReflectionMethod($graphql_field, $rm, $directives); } return $fields; diff --git a/src/Codegen/Generator.hack b/src/Codegen/Generator.hack index cfb4764..288e5f4 100644 --- a/src/Codegen/Generator.hack +++ b/src/Codegen/Generator.hack @@ -31,6 +31,10 @@ final class Generator { 'output_directory' => string, 'namespace' => string, ?'codegen_config' => IHackCodegenConfig, + ?'custom_directives' => shape( + ?'fields' => keyset>, + ?'objects' => keyset>, + ), ); private function __construct(private MultiParser $parser, private self::TGeneratorConfig $config) { @@ -205,9 +209,6 @@ final class Generator { $classish_objects = $this->parser->getClassishObjects(); - $field_resolver = new FieldResolver($classish_objects); - $class_fields = $field_resolver->resolveFields(); - $hack_class_to_graphql_interface = dict[]; $hack_class_to_graphql_object = dict[]; foreach ($classish_objects as $class) { @@ -227,6 +228,14 @@ final class Generator { $hack_class_to_graphql_object = Dict\sort_by_key($hack_class_to_graphql_object); $hack_class_to_graphql_interface = Dict\sort_by_key($hack_class_to_graphql_interface); + $directive_finder = new DirectivesFinder( + $this->config['custom_directives'] ?? shape(), + $hack_class_to_graphql_interface, + ); + + $field_resolver = new FieldResolver($classish_objects, $directive_finder); + $class_fields = $field_resolver->resolveFields(); + $input_types = $this->parser->getTypes(); foreach ($input_types as $type) { $rt = new \ReflectionTypeAlias($type->getName()); @@ -248,7 +257,7 @@ final class Generator { "All connection types must have names ending with `Connection`. `%s` does not.", $class->getName(), ); - $objects = Vec\concat($objects, $this->getConnectionObjects($class)); + $objects = Vec\concat($objects, $this->getConnectionObjects($class, $directive_finder)); } elseif (!C\is_empty($class->getAttributes())) { $rc = new \ReflectionClass($class->getName()); $fields = $class_fields[$class->getName()]; @@ -264,6 +273,7 @@ final class Generator { $graphql_interface, $rc->getName(), $fields, + $directive_finder->findDirectivesForObject($rc), $hack_class_to_graphql_object, ); } else if ($graphql_object is nonnull) { @@ -271,6 +281,7 @@ final class Generator { $graphql_object, $rc->getName(), $fields, + $directive_finder->findDirectivesForObject($rc), $hack_class_to_graphql_interface, ); } @@ -285,7 +296,11 @@ final class Generator { $rm = new \ReflectionMethod($class->getName(), $method_name); $query_root_field = $rm->getAttributeClass(\Slack\GraphQL\QueryRootField::class); if ($query_root_field is nonnull) { - $query_fields[$query_root_field->getName()] = FieldBuilder::forRootField($query_root_field, $rm); + $query_fields[$query_root_field->getName()] = FieldBuilder::forRootField( + $query_root_field, + $rm, + $directive_finder->findDirectivesForField($rm), + ); continue; } @@ -297,6 +312,7 @@ final class Generator { $mutation_fields[$mutation_root_field->getName()] = FieldBuilder::forRootField( $mutation_root_field, $rm, + $directive_finder->findDirectivesForField($rm), ); } } @@ -314,6 +330,7 @@ final class Generator { new \Slack\GraphQL\ObjectType('Query', 'Query'), 'Slack\\GraphQL\\Root', vec(Dict\sort_by_key($query_fields)), + dict[], $hack_class_to_graphql_interface, ); @@ -322,6 +339,7 @@ final class Generator { new \Slack\GraphQL\ObjectType('Mutation', 'Mutation'), 'Slack\\GraphQL\\Root', vec(Dict\sort_by_key($mutation_fields)), + dict[], $hack_class_to_graphql_interface, ); } @@ -329,7 +347,10 @@ final class Generator { return Vec\sort_by($objects, $object ==> $object->getGraphQLType()); } - private function getConnectionObjects(DefinitionFinder\ScannedClassish $class): vec { + private function getConnectionObjects( + DefinitionFinder\ScannedClassish $class, + DirectivesFinder $df, + ): vec { $rc = new \ReflectionClass($class->getName()); $hack_type = $rc->getTypeConstants() |> C\find($$, $c ==> $c->getName() === 'TNode')?->getAssignedTypeText(); @@ -342,7 +363,11 @@ final class Generator { $rc->getName(), ); return vec[ - ObjectBuilder::forConnection($class->getName(), $type_info['gql_type'].'Edge'), + ObjectBuilder::forConnection( + $class->getName(), + $type_info['gql_type'].'Edge', + $df->findDirectivesForObject($rc), + ), ObjectBuilder::forEdge($type_info['gql_type'], $type_info['hack_type'], $type_info['output_type']), ]; } diff --git a/src/Codegen/Types.hack b/src/Codegen/Types.hack index c648a6e..3c9e6fe 100644 --- a/src/Codegen/Types.hack +++ b/src/Codegen/Types.hack @@ -3,7 +3,7 @@ namespace Slack\GraphQL\Codegen; -use namespace HH\Lib\{C, Str}; +use namespace HH\Lib\{C, Dict, Str}; use namespace Slack\GraphQL\Types; const dict> BUILTIN_TYPES = dict[ @@ -263,3 +263,13 @@ function get_node_type_info(string $hack_type): ?shape( 'output_type' => $output_type, ); } + +function get_interfaces( + string $hack_type, + dict $hack_class_to_graphql_interface, +): dict { + return Dict\filter_with_key( + $hack_class_to_graphql_interface, + ($interface, $_gql_type) ==> \is_subclass_of($hack_type, $interface), + ); +} diff --git a/src/Directive.hack b/src/Directive.hack new file mode 100644 index 0000000..eab0fd2 --- /dev/null +++ b/src/Directive.hack @@ -0,0 +1,45 @@ + + + +namespace Slack\GraphQL; + +/** + * A custom schema directive. + */ +interface Directive { + + /** + * Return the arguments necessary to reconstitute the directive by calling `new`. + * + * For example, if the directive has the following constructor: + * + * __construct(private float $x, private string $y) {} + * + * You'd implement `formatArgs()` as follows: + * + * return vec[Str\format("%f", $this->x), Str\format('"%s"', $this->y)]; + */ + public function formatArgs(): vec; +} + +/** + * A field-level directive. + */ +interface FieldDirective extends Directive, \HH\MethodAttribute { + + /** + * Hook which executes before resolving a field. + */ + public function beforeResolveField(mixed $object, string $field): Awaitable; +} + +/** + * An object-level directive. + */ +interface ObjectDirective extends Directive, \HH\ClassAttribute { + + /** + * Hook which executes before resolving an object. + */ + public function beforeResolveObject(string $object_name): Awaitable; +} diff --git a/src/FieldDefinition.hack b/src/FieldDefinition.hack index 4c965aa..1a8c6da 100644 --- a/src/FieldDefinition.hack +++ b/src/FieldDefinition.hack @@ -29,6 +29,7 @@ final class FieldDefinition implements IResolvableFiel dict, Variables, ): Awaitable) $resolver, + private vec $directives, ) {} public async function resolveAsync( @@ -38,6 +39,7 @@ final class FieldDefinition implements IResolvableFiel ): Awaitable> { $resolver = $this->resolver; try { + await $this->beforeResolve($parent); $value = await $resolver( $parent, // Validation guarantees all of the grouped field nodes have the same arguments, so it doesn't matter @@ -84,4 +86,15 @@ final class FieldDefinition implements IResolvableFiel public function getArgs(): vec { return vec($this->arguments); } + + private async function beforeResolve(TParent $parent): Awaitable { + foreach ($this->directives as $directive) { + await $directive->beforeResolveField($parent, $this->getName()); + } + + $unwrapped_type = $this->type->unwrapType(); + if ($unwrapped_type is Types\CompositeType) { + await $unwrapped_type->beforeResolveObject(); + } + } } diff --git a/src/Types/Output/CompositeType.hack b/src/Types/Output/CompositeType.hack index d24c991..6e62349 100644 --- a/src/Types/Output/CompositeType.hack +++ b/src/Types/Output/CompositeType.hack @@ -16,8 +16,16 @@ abstract class CompositeType extends NamedType { abstract public function getFieldDefinition(string $field_name): ?GraphQL\IFieldDefinition; + abstract public function getDirectives(): vec; + <<__Override>> final public function getFields(bool $includeDeprecated = false): vec { return Vec\map($this::FIELD_NAMES, $field_name ==> $this->getFieldDefinition($field_name) as nonnull); } + + final public async function beforeResolveObject(): Awaitable { + foreach ($this->getDirectives() as $directive) { + await $directive->beforeResolveObject($this::NAME); + } + } } diff --git a/tests/BaseTest.hack b/tests/BaseTest.hack new file mode 100644 index 0000000..cdff916 --- /dev/null +++ b/tests/BaseTest.hack @@ -0,0 +1,54 @@ + + + +use function Facebook\FBExpect\expect; +use namespace HH\Lib\C; +use namespace Slack\GraphQL; + +abstract class BaseTest extends \Facebook\HackTest\HackTest { + abstract const type TTestCases; + + abstract public static function getTestCases(): this::TTestCases; + + <<__Override>> + public static async function beforeFirstTestAsync(): Awaitable { + await self::runCodegenAsync(); + } + + <<__Memoize>> + private static async function runCodegenAsync(): Awaitable { + await GraphQL\Codegen\Generator::forPath( + __DIR__.'/Fixtures', + shape( + 'output_directory' => __DIR__.'/gen', + 'namespace' => 'Slack\GraphQL\Test\Generated', + 'custom_directives' => shape( + 'fields' => keyset[ + Directives\AnotherDirective::class, + Directives\HasRole::class, + Directives\LogSampled::class, + Directives\TestShapeDirective::class, + ], + 'objects' => keyset[ + Directives\AnotherDirective::class, + Directives\HasRole::class, + Directives\LogSampled::class, + ], + ), + ), + ); + } + + private function getResolver(GraphQL\Resolver::TOptions $options = shape()): GraphQL\Resolver { + return new GraphQL\Resolver(new \Slack\GraphQL\Test\Generated\Schema(), $options); + } + + public async function resolve( + string $query, + dict $variables = dict[], + GraphQL\Resolver::TOptions $options = shape(), + ): Awaitable { + $resolver = $this->getResolver($options); + return await $resolver->resolve($query, $variables); + } +} diff --git a/tests/DirectiveContext.hack b/tests/DirectiveContext.hack new file mode 100644 index 0000000..0bb8d44 --- /dev/null +++ b/tests/DirectiveContext.hack @@ -0,0 +1,50 @@ + +use namespace HH\Lib\C; + +final class DirectiveContext { + public static dict>> $field_resolutions = dict[]; + public static dict> $object_resolutions = dict[]; + + public static function reset(): void { + self::$field_resolutions = dict[]; + self::$object_resolutions = dict[]; + } + + public static function incrementResolveField( + \Slack\GraphQL\FieldDirective $directive, + mixed $object, + string $field, + ): void { + $directive_class = \get_class($directive); + if (!C\contains_key(self::$field_resolutions, $directive_class)) { + self::$field_resolutions[$directive_class] = dict[]; + } + + $object_class = \get_class($object); + if (!C\contains_key(self::$field_resolutions[$directive_class], $object_class)) { + self::$field_resolutions[$directive_class][$object_class] = dict[]; + } + + if (!C\contains_key(self::$field_resolutions[$directive_class][$object_class], $field)) { + self::$field_resolutions[$directive_class][$object_class][$field] = 0; + } + + self::$field_resolutions[$directive_class][$object_class][$field]++; + } + + public static function incrementResolveObject( + \Slack\GraphQL\ObjectDirective $directive, + string $object_name, + ): void { + $directive_class = \get_class($directive); + if (!C\contains_key(self::$object_resolutions, $directive_class)) { + self::$object_resolutions[$directive_class] = dict[]; + } + + if (!C\contains_key(self::$object_resolutions[$directive_class], $object_name)) { + self::$object_resolutions[$directive_class][$object_name] = 0; + } + + self::$object_resolutions[$directive_class][$object_name]++; + } +} diff --git a/tests/DirectiveTest.hack b/tests/DirectiveTest.hack new file mode 100644 index 0000000..86f7982 --- /dev/null +++ b/tests/DirectiveTest.hack @@ -0,0 +1,95 @@ + + + +use function Facebook\FBExpect\expect; +use namespace HH\Lib\C; +use namespace Slack\GraphQL; + +final class DirectiveTest extends BaseTest { + + const type TExpectedResponse = shape( + 'field_resolutions' => dict>>, + 'object_resolutions' => dict>, + ); + + const type TTestCases = dict, this::TExpectedResponse)>; + + public static function getTestCases(): this::TTestCases { + return dict[ + 'runs the expected number of directives in the expected order' => tuple( + 'query { + human(id: 2) { + favorite_color + } + }', + dict[], + shape( + 'object_resolutions' => dict[ + \Directives\AnotherDirective::class => dict[ + 'Human' => 1, + ], + \Directives\HasRole::class => dict[ + 'Human' => 1, + ], + \Directives\LogSampled::class => dict[ + 'Human' => 1, + ], + ], + 'field_resolutions' => dict[ + \Directives\AnotherDirective::class => dict[ + 'Human' => dict[ + 'favorite_color' => 1, + ], + ], + \Directives\HasRole::class => dict[ + 'Human' => dict[ + 'favorite_color' => 1, + ], + ], + \Directives\LogSampled::class => dict[ + 'Human' => dict[ + 'favorite_color' => 1, + ], + ], + \Directives\TestShapeDirective::class => dict[ + 'Human' => dict[ + 'favorite_color' => 1, + ], + ], + ], + ), + ), + 'runs directives for an interface' => tuple( + 'query { + viewer { + id + } + }', + dict[], + shape( + 'object_resolutions' => dict[ + \Directives\AnotherDirective::class => dict[ + 'User' => 1, + ], + ], + 'field_resolutions' => dict[], + ), + ), + ]; + } + + public async function beforeEachTestAsync(): Awaitable { + DirectiveContext::reset(); + } + + <<\Facebook\HackTest\DataProvider('getTestCases')>> + final public async function test( + string $query, + dict $variables, + this::TExpectedResponse $expected_response, + ): Awaitable { + await $this->resolve($query, $variables); + expect(DirectiveContext::$field_resolutions)->toEqual($expected_response['field_resolutions']); + expect(DirectiveContext::$object_resolutions)->toEqual($expected_response['object_resolutions']); + } +} diff --git a/tests/FixtureTest.hack b/tests/FixtureTest.hack index f959880..4b7c0dd 100644 --- a/tests/FixtureTest.hack +++ b/tests/FixtureTest.hack @@ -5,28 +5,10 @@ use function Facebook\FBExpect\expect; use namespace HH\Lib\C; use namespace Slack\GraphQL; -abstract class FixtureTest extends \Facebook\HackTest\HackTest { +abstract class FixtureTest extends BaseTest { const type TTestCases = dict, mixed)>; - abstract public static function getTestCases(): this::TTestCases; - - <<__Override>> - public static async function beforeFirstTestAsync(): Awaitable { - await self::runCodegenAsync(); - } - - <<__Memoize>> - private static async function runCodegenAsync(): Awaitable { - await GraphQL\Codegen\Generator::forPath( - __DIR__.'/Fixtures', - shape( - 'output_directory' => __DIR__.'/gen', - 'namespace' => 'Slack\GraphQL\Test\Generated', - ), - ); - } - <<\Facebook\HackTest\DataProvider('getTestCases')>> final public async function test( string $query, @@ -43,17 +25,4 @@ abstract class FixtureTest extends \Facebook\HackTest\HackTest { $out = await $this->resolve($query, $variables); expect($out)->toHaveSameShapeAs($expected_response); } - - private function getResolver(GraphQL\Resolver::TOptions $options = shape()): GraphQL\Resolver { - return new GraphQL\Resolver(new \Slack\GraphQL\Test\Generated\Schema(), $options); - } - - public async function resolve( - string $query, - dict $variables = dict[], - GraphQL\Resolver::TOptions $options = shape(), - ): Awaitable { - $resolver = $this->getResolver($options); - return await $resolver->resolve($query, $variables); - } } diff --git a/tests/Fixtures/Directives.hack b/tests/Fixtures/Directives.hack new file mode 100644 index 0000000..6b4e28f --- /dev/null +++ b/tests/Fixtures/Directives.hack @@ -0,0 +1,78 @@ + + + +namespace Directives; + +use namespace Slack\GraphQL; +use namespace HH\Lib\{C, Str, Vec}; + +abstract class RoleType {} +final class AdminRoleType extends RoleType {} +final class StaffRoleType extends RoleType {} + +final class HasRole implements \Slack\GraphQL\FieldDirective, \Slack\GraphQL\ObjectDirective { + public function __construct(private vec> $roles) {} + + public function formatArgs(): vec { + return vec[Str\format( + 'vec[%s]', + Vec\map($this->roles, $role ==> Str\format('\%s::class', $role)) |> Str\join($$, ', '), + )]; + } + + public async function beforeResolveField(mixed $object, string $field): Awaitable { + \DirectiveContext::incrementResolveField($this, $object, $field); + } + + public async function beforeResolveObject(string $object_name): Awaitable { + \DirectiveContext::incrementResolveObject($this, $object_name); + } +} + +final class LogSampled implements \Slack\GraphQL\FieldDirective, \Slack\GraphQL\ObjectDirective { + public function __construct(private float $frequency, private string $prefix) {} + + public function formatArgs(): vec { + return vec[ + Str\format('%f', $this->frequency), + Str\format('"%s"', $this->prefix), + ]; + } + + public async function beforeResolveField(mixed $object, string $field): Awaitable { + \DirectiveContext::incrementResolveField($this, $object, $field); + } + + public async function beforeResolveObject(string $object_name): Awaitable { + \DirectiveContext::incrementResolveObject($this, $object_name); + } +} + +final class TestShapeDirective implements \Slack\GraphQL\FieldDirective { + public function __construct(private shape('foo' => int, 'bar' => string) $args, private bool $extra) {} + + public function formatArgs(): vec { + return vec[ + Str\format('shape(\'foo\' => %d, \'bar\' => "%s")', $this->args['foo'], $this->args['bar']), + $this->extra ? 'true' : 'false', + ]; + } + + public async function beforeResolveField(mixed $object, string $field): Awaitable { + \DirectiveContext::incrementResolveField($this, $object, $field); + } +} + +final class AnotherDirective implements \Slack\GraphQL\FieldDirective, \Slack\GraphQL\ObjectDirective { + public function formatArgs(): vec { + return vec[]; + } + + public async function beforeResolveField(mixed $object, string $field): Awaitable { + \DirectiveContext::incrementResolveField($this, $object, $field); + } + + public async function beforeResolveObject(string $object_name): Awaitable { + \DirectiveContext::incrementResolveObject($this, $object_name); + } +} diff --git a/tests/Fixtures/Playground.hack b/tests/Fixtures/Playground.hack index 8a47e20..784efd6 100644 --- a/tests/Fixtures/Playground.hack +++ b/tests/Fixtures/Playground.hack @@ -2,7 +2,9 @@ use namespace Slack\GraphQL; -use namespace HH\Lib\{Math, Str, Vec}; +use type Directives\HasRole; +use type Directives\{TestShapeDirective}; +use namespace HH\Lib\{C, Math, Str, Vec}; <> type TCreateTeamInput = shape( @@ -31,7 +33,6 @@ final class TeamStore { if (self::$store is null) { self::$store = new self(); } - return self::$store; } @@ -46,7 +47,7 @@ final class TeamStore { } } -<> +<> interface User { <> public function getId(): int; @@ -94,9 +95,19 @@ enum FavoriteColor: int { BLUE = 2; } -<> +<< + GraphQL\ObjectType('Human', 'Human'), + HasRole(vec[Directives\AdminRoleType::class]), + Directives\LogSampled(0.0, 'bar'), +>> final class Human extends BaseUser { - <> + << + GraphQL\Field('favorite_color', 'Favorite color of the user'), + HasRole(vec[Directives\StaffRoleType::class]), + \Directives\LogSampled(33.3, 'foo'), + TestShapeDirective(shape('foo' => 1, 'bar' => 'abc'), true), + Directives\AnotherDirective, + >> public function getFavoriteColor(): FavoriteColor { return FavoriteColor::BLUE; } @@ -161,7 +172,7 @@ abstract final class UserQueryAttributes { return new \Human(shape('id' => $id, 'name' => 'User '.$id, 'team_id' => 1, 'is_active' => true)); } - <> + <> public static async function getBot(int $id): Awaitable<\Bot> { return new \Bot(shape('id' => $id, 'name' => 'User '.$id, 'team_id' => 1, 'is_active' => true)); } @@ -211,7 +222,10 @@ abstract final class UserMutationAttributes { return new \Human(shape('id' => $id, 'name' => 'User '.$id, 'team_id' => 1, 'is_active' => true)); } - <> + << + GraphQL\MutationRootField('createUser', 'Create a new user'), + \Directives\HasRole(vec[\Directives\StaffRoleType::class]), + >> public static async function createUser(TCreateUserInput $input): Awaitable<\User> { $team_input = $input['team'] ?? null; diff --git a/tests/Validation/BaseValidationTest.hack b/tests/Validation/BaseValidationTest.hack index d163f63..2fa8671 100644 --- a/tests/Validation/BaseValidationTest.hack +++ b/tests/Validation/BaseValidationTest.hack @@ -6,28 +6,12 @@ use namespace HH\Lib\Vec; use namespace Slack\GraphQL; use namespace Slack\GraphQL\Validation; -abstract class BaseValidationTest extends \Facebook\HackTest\HackTest { +abstract class BaseValidationTest extends BaseTest { const type TTestCases = dict)>; abstract const classname RULE; - <<__Override>> - public static async function beforeFirstTestAsync(): Awaitable { - await self::runCodegenAsync(); - } - - <<__Memoize>> - private static async function runCodegenAsync(): Awaitable { - await GraphQL\Codegen\Generator::forPath( - __DIR__.'/../Fixtures', - shape( - 'output_directory' => __DIR__.'/../gen', - 'namespace' => 'Slack\GraphQL\Test\Generated', - ), - ); - } - <<\Facebook\HackTest\DataProvider('getTestCases')>> final public async function test(string $query, vec $expected_errors): Awaitable { $source = new \Graphpinator\Source\StringSource($query); diff --git a/tests/gen/AlphabetConnection.hack b/tests/gen/AlphabetConnection.hack index 8f6b988..e83f126 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<<5f8b6c004891baeb9f3ebe6ccc928ed0>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -32,6 +32,7 @@ final class AlphabetConnection extends \Slack\GraphQL\Types\ObjectType { StringTypeEdge::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> await $parent->getEdges(), + vec[], ); case 'pageInfo': return new GraphQL\FieldDefinition( @@ -39,9 +40,14 @@ final class AlphabetConnection extends \Slack\GraphQL\Types\ObjectType { PageInfo::nullableOutput(), dict[], async ($parent, $args, $vars) ==> await $parent->getPageInfo(), + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/AnotherObjectShape.hack b/tests/gen/AnotherObjectShape.hack index 1f5b18f..3dea947 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<> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -31,9 +31,14 @@ final class AnotherObjectShape extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent['abc'], + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/Baz.hack b/tests/gen/Baz.hack index a471eb2..51ad76d 100644 --- a/tests/gen/Baz.hack +++ b/tests/gen/Baz.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<78317f3a7332839455ecbea5da091009>> + * @generated SignedSource<<28f4fb865ae1d6dc001cb3a5d9ea12d6>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -31,9 +31,14 @@ final class Baz extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getValue(), + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/Bot.hack b/tests/gen/Bot.hack index aee6b1a..d549005 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<<03be695df2735f4f7ae8ed28a01c23de>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -36,6 +36,7 @@ final class Bot extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getId(), + vec[], ); case 'is_active': return new GraphQL\FieldDefinition( @@ -43,6 +44,7 @@ final class Bot extends \Slack\GraphQL\Types\ObjectType { Types\BooleanType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->isActive(), + vec[], ); case 'name': return new GraphQL\FieldDefinition( @@ -50,6 +52,7 @@ final class Bot extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getName(), + vec[], ); case 'primary_function': return new GraphQL\FieldDefinition( @@ -57,6 +60,7 @@ final class Bot extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getPrimaryFunction(), + vec[], ); case 'team': return new GraphQL\FieldDefinition( @@ -64,9 +68,16 @@ final class Bot extends \Slack\GraphQL\Types\ObjectType { Team::nullableOutput(), dict[], async ($parent, $args, $vars) ==> await $parent->getTeam(), + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[ + new \Directives\AnotherDirective(), + ]; + } } diff --git a/tests/gen/Concrete.hack b/tests/gen/Concrete.hack index 05cbb58..65e3489 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<<09f97d331e6676408747e845f64c5356>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -35,6 +35,7 @@ final class Concrete extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->bar(), + vec[], ); case 'baz': return new GraphQL\FieldDefinition( @@ -42,6 +43,7 @@ final class Concrete extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->baz(), + vec[], ); case 'foo': return new GraphQL\FieldDefinition( @@ -49,9 +51,14 @@ final class Concrete extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->foo(), + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/ErrorTestObj.hack b/tests/gen/ErrorTestObj.hack index b2e43e0..06cecc8 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<> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -42,6 +42,7 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->bad_int_list_n_of_n(), + vec[], ); case 'bad_int_list_n_of_nn': return new GraphQL\FieldDefinition( @@ -49,6 +50,7 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->bad_int_list_n_of_nn(), + vec[], ); case 'bad_int_list_nn_of_nn': return new GraphQL\FieldDefinition( @@ -56,6 +58,7 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nonNullable()->nonNullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->bad_int_list_nn_of_nn(), + vec[], ); case 'hidden_exception': return new GraphQL\FieldDefinition( @@ -63,6 +66,7 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->hidden_exception(), + vec[], ); case 'nested': return new GraphQL\FieldDefinition( @@ -70,6 +74,7 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { ErrorTestObj::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->nested(), + vec[], ); case 'nested_list_n_of_n': return new GraphQL\FieldDefinition( @@ -77,6 +82,7 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { ErrorTestObj::nullableOutput()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->nested_list_n_of_n(), + vec[], ); case 'nested_list_n_of_nn': return new GraphQL\FieldDefinition( @@ -84,6 +90,7 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { ErrorTestObj::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->nested_list_n_of_nn(), + vec[], ); case 'nested_list_nn_of_nn': return new GraphQL\FieldDefinition( @@ -91,6 +98,7 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { ErrorTestObj::nonNullable()->nonNullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->nested_list_nn_of_nn(), + vec[], ); case 'nested_nn': return new GraphQL\FieldDefinition( @@ -98,6 +106,7 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { ErrorTestObj::nonNullable(), dict[], async ($parent, $args, $vars) ==> $parent->nested_nn(), + vec[], ); case 'no_error': return new GraphQL\FieldDefinition( @@ -105,6 +114,7 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->no_error(), + vec[], ); case 'non_nullable': return new GraphQL\FieldDefinition( @@ -112,6 +122,7 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nonNullable(), dict[], async ($parent, $args, $vars) ==> $parent->non_nullable(), + vec[], ); case 'user_facing_error': return new GraphQL\FieldDefinition( @@ -119,9 +130,14 @@ final class ErrorTestObj extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->user_facing_error(), + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/FooConnection.hack b/tests/gen/FooConnection.hack index 9168d92..c2378f9 100644 --- a/tests/gen/FooConnection.hack +++ b/tests/gen/FooConnection.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<> + * @generated SignedSource<<48c4764c438d48a28882faeec41c7594>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -32,6 +32,7 @@ final class FooConnection extends \Slack\GraphQL\Types\ObjectType { FooObjectEdge::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> await $parent->getEdges(), + vec[], ); case 'pageInfo': return new GraphQL\FieldDefinition( @@ -39,9 +40,14 @@ final class FooConnection extends \Slack\GraphQL\Types\ObjectType { PageInfo::nullableOutput(), dict[], async ($parent, $args, $vars) ==> await $parent->getPageInfo(), + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/FooInterface.hack b/tests/gen/FooInterface.hack index 99bc769..1ea297d 100644 --- a/tests/gen/FooInterface.hack +++ b/tests/gen/FooInterface.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; @@ -30,6 +30,10 @@ final class FooInterface extends \Slack\GraphQL\Types\InterfaceType { } } + public function getDirectives(): vec { + return vec[]; + } + public async function resolveAsync( this::THackType $value, vec<\Graphpinator\Parser\Field\IHasSelectionSet> $parent_nodes, diff --git a/tests/gen/FooObject.hack b/tests/gen/FooObject.hack index 05b68f8..83161fd 100644 --- a/tests/gen/FooObject.hack +++ b/tests/gen/FooObject.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; @@ -32,9 +32,14 @@ final class FooObject extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getValue(), + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/FooObjectEdge.hack b/tests/gen/FooObjectEdge.hack index 77021b2..ba2c281 100644 --- a/tests/gen/FooObjectEdge.hack +++ b/tests/gen/FooObjectEdge.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<96bd2ebd136797e7bb5774ad210a08b2>> + * @generated SignedSource<> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -32,6 +32,7 @@ final class FooObjectEdge extends \Slack\GraphQL\Types\ObjectType { FooObject::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getNode(), + vec[], ); case 'cursor': return new GraphQL\FieldDefinition( @@ -39,9 +40,14 @@ final class FooObjectEdge extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getCursor(), + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/Human.hack b/tests/gen/Human.hack index e2a2d27..0ac48cb 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<<7ea97f7c9dbc2d43a4cb74d7fd481c6f>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -38,6 +38,12 @@ final class Human extends \Slack\GraphQL\Types\ObjectType { FavoriteColor::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getFavoriteColor(), + vec[ + new \Directives\AnotherDirective(), + new \Directives\HasRole(vec[\Directives\StaffRoleType::class]), + new \Directives\LogSampled(33.300000, "foo"), + new \Directives\TestShapeDirective(shape('foo' => 1, 'bar' => "abc"), true), + ], ); case 'friends': return new GraphQL\FieldDefinition( @@ -71,6 +77,7 @@ final class Human extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableInput()->coerceOptionalNamedNode('first', $args, $vars, null), Types\IntType::nullableInput()->coerceOptionalNamedNode('last', $args, $vars, null), ), + vec[], ); case 'id': return new GraphQL\FieldDefinition( @@ -78,6 +85,7 @@ final class Human extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getId(), + vec[], ); case 'is_active': return new GraphQL\FieldDefinition( @@ -85,6 +93,7 @@ final class Human extends \Slack\GraphQL\Types\ObjectType { Types\BooleanType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->isActive(), + vec[], ); case 'name': return new GraphQL\FieldDefinition( @@ -92,6 +101,7 @@ final class Human extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getName(), + vec[], ); case 'named_friends': return new GraphQL\FieldDefinition( @@ -131,6 +141,7 @@ final class Human extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableInput()->coerceOptionalNamedNode('first', $args, $vars, null), Types\IntType::nullableInput()->coerceOptionalNamedNode('last', $args, $vars, null), ), + vec[], ); case 'team': return new GraphQL\FieldDefinition( @@ -138,9 +149,18 @@ final class Human extends \Slack\GraphQL\Types\ObjectType { Team::nullableOutput(), dict[], async ($parent, $args, $vars) ==> await $parent->getTeam(), + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[ + new \Directives\AnotherDirective(), + new \Directives\HasRole(vec[\Directives\AdminRoleType::class]), + new \Directives\LogSampled(0.000000, "bar"), + ]; + } } diff --git a/tests/gen/IIntrospectionInterfaceA.hack b/tests/gen/IIntrospectionInterfaceA.hack index c78038c..981079f 100644 --- a/tests/gen/IIntrospectionInterfaceA.hack +++ b/tests/gen/IIntrospectionInterfaceA.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<83c4ac9e30bde4ce823ffcb02f4260a4>> + * @generated SignedSource<<474eefa78f1e2d09600a88d534036421>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -33,6 +33,10 @@ final class IIntrospectionInterfaceA } } + public function getDirectives(): vec { + return vec[]; + } + public async function resolveAsync( this::THackType $value, vec<\Graphpinator\Parser\Field\IHasSelectionSet> $parent_nodes, diff --git a/tests/gen/IIntrospectionInterfaceB.hack b/tests/gen/IIntrospectionInterfaceB.hack index e02adbe..a16a827 100644 --- a/tests/gen/IIntrospectionInterfaceB.hack +++ b/tests/gen/IIntrospectionInterfaceB.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<12c9405d6c2b8a6c546a295fa510ad17>> + * @generated SignedSource<<2f12a89134a2d0e3c409bc6e8090774a>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -32,6 +32,10 @@ final class IIntrospectionInterfaceB } } + public function getDirectives(): vec { + return vec[]; + } + public async function resolveAsync( this::THackType $value, vec<\Graphpinator\Parser\Field\IHasSelectionSet> $parent_nodes, diff --git a/tests/gen/IIntrospectionInterfaceC.hack b/tests/gen/IIntrospectionInterfaceC.hack index d69c991..67d0b67 100644 --- a/tests/gen/IIntrospectionInterfaceC.hack +++ b/tests/gen/IIntrospectionInterfaceC.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<> + * @generated SignedSource<<86c4146f79457335723548bb2e9aaff6>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -31,6 +31,10 @@ final class IIntrospectionInterfaceC } } + public function getDirectives(): vec { + return vec[]; + } + public async function resolveAsync( this::THackType $value, vec<\Graphpinator\Parser\Field\IHasSelectionSet> $parent_nodes, diff --git a/tests/gen/ImplementInterfaceA.hack b/tests/gen/ImplementInterfaceA.hack index 13f0944..b57184c 100644 --- a/tests/gen/ImplementInterfaceA.hack +++ b/tests/gen/ImplementInterfaceA.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<53436dffd735452beaf52476eaf137fd>> + * @generated SignedSource<> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -29,4 +29,8 @@ final class ImplementInterfaceA extends \Slack\GraphQL\Types\ObjectType { return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/ImplementInterfaceB.hack b/tests/gen/ImplementInterfaceB.hack index c1875de..bf5e915 100644 --- a/tests/gen/ImplementInterfaceB.hack +++ b/tests/gen/ImplementInterfaceB.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<9e0b3a4ffca4c305b94da9212f5b4b6f>> + * @generated SignedSource<> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -30,4 +30,8 @@ final class ImplementInterfaceB extends \Slack\GraphQL\Types\ObjectType { return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/ImplementInterfaceC.hack b/tests/gen/ImplementInterfaceC.hack index 7beac92..b7e331b 100644 --- a/tests/gen/ImplementInterfaceC.hack +++ b/tests/gen/ImplementInterfaceC.hack @@ -4,7 +4,7 @@ * To re-generate this file run vendor/bin/hacktest * * - * @generated SignedSource<<11aa39f80b2881d293b3ecfb2c300565>> + * @generated SignedSource<> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -31,4 +31,8 @@ final class ImplementInterfaceC extends \Slack\GraphQL\Types\ObjectType { return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/InterfaceA.hack b/tests/gen/InterfaceA.hack index ba89bb8..dee8eb1 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,12 +32,17 @@ final class InterfaceA extends \Slack\GraphQL\Types\InterfaceType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->foo(), + vec[], ); default: return null; } } + public function getDirectives(): vec { + return vec[]; + } + public async function resolveAsync( this::THackType $value, vec<\Graphpinator\Parser\Field\IHasSelectionSet> $parent_nodes, diff --git a/tests/gen/InterfaceB.hack b/tests/gen/InterfaceB.hack index 483b134..51c59af 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<<23f46fe7d8463187b6682cfd68762302>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -33,6 +33,7 @@ final class InterfaceB extends \Slack\GraphQL\Types\InterfaceType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->bar(), + vec[], ); case 'foo': return new GraphQL\FieldDefinition( @@ -40,12 +41,17 @@ final class InterfaceB extends \Slack\GraphQL\Types\InterfaceType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->foo(), + vec[], ); default: return null; } } + public function getDirectives(): vec { + return vec[]; + } + public async function resolveAsync( this::THackType $value, vec<\Graphpinator\Parser\Field\IHasSelectionSet> $parent_nodes, diff --git a/tests/gen/IntrospectionTestObject.hack b/tests/gen/IntrospectionTestObject.hack index 7a1644b..b1f12a4 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<<45e41c9745331f6573116572a8ba8efc>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -37,6 +37,7 @@ final class IntrospectionTestObject extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->getDefaultListOfNonNullableInt(), + vec[], ); case 'default_list_of_nullable_int': return new GraphQL\FieldDefinition( @@ -44,6 +45,7 @@ final class IntrospectionTestObject extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->getDefaultListOfNullableInt(), + vec[], ); case 'default_nullable_string': return new GraphQL\FieldDefinition( @@ -51,6 +53,7 @@ final class IntrospectionTestObject extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getDefaultNullableString(), + vec[], ); case 'non_null_int': return new GraphQL\FieldDefinition( @@ -58,6 +61,7 @@ final class IntrospectionTestObject extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nonNullable(), dict[], async ($parent, $args, $vars) ==> $parent->getNonNullInt(), + vec[], ); case 'non_null_list_of_non_null': return new GraphQL\FieldDefinition( @@ -65,6 +69,7 @@ final class IntrospectionTestObject extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nonNullable()->nonNullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->getNonNullListOfNonNull(), + vec[], ); case 'non_null_string': return new GraphQL\FieldDefinition( @@ -72,6 +77,7 @@ final class IntrospectionTestObject extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nonNullable(), dict[], async ($parent, $args, $vars) ==> $parent->getNonNullString(), + vec[], ); case 'nullable_string': return new GraphQL\FieldDefinition( @@ -79,9 +85,14 @@ final class IntrospectionTestObject extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getNullableString(), + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/Mutation.hack b/tests/gen/Mutation.hack index 5a134de..e5c7977 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,9 @@ final class Mutation extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> await \UserMutationAttributes::createUser( CreateUserInput::nonNullable()->coerceNamedNode('input', $args, $vars), ), + vec[ + new \Directives\HasRole(vec[\Directives\StaffRoleType::class]), + ], ); case 'pokeUser': return new GraphQL\FieldDefinition( @@ -53,9 +56,14 @@ final class Mutation extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> await \UserMutationAttributes::pokeUser( Types\IntType::nonNullable()->coerceNamedNode('id', $args, $vars), ), + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/NestedOutputShape.hack b/tests/gen/NestedOutputShape.hack index 389f7c5..2d5cede 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<<0b7b74b98133923a0745b7bedee84638>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -31,9 +31,14 @@ final class NestedOutputShape extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent['vec_of_string'], + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/ObjectShape.hack b/tests/gen/ObjectShape.hack index 9b63d57..b54cc16 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<<6891ec753bf59d5345f3cdfff3f16249>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -33,6 +33,7 @@ final class ObjectShape extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['foo'], + vec[], ); case 'bar': return new GraphQL\FieldDefinition( @@ -40,6 +41,7 @@ final class ObjectShape extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['bar'] ?? null, + vec[], ); case 'baz': return new GraphQL\FieldDefinition( @@ -47,9 +49,14 @@ final class ObjectShape extends \Slack\GraphQL\Types\ObjectType { AnotherObjectShape::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['baz'], + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/OutputShape.hack b/tests/gen/OutputShape.hack index 10c4a20..d449ba8 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<<7e99f57dacb997591c72087d6edf3f08>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -33,6 +33,7 @@ final class OutputShape extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['string'], + vec[], ); case 'vec_of_int': return new GraphQL\FieldDefinition( @@ -40,6 +41,7 @@ final class OutputShape extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent['vec_of_int'], + vec[], ); case 'nested_shape': return new GraphQL\FieldDefinition( @@ -47,9 +49,14 @@ final class OutputShape extends \Slack\GraphQL\Types\ObjectType { NestedOutputShape::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['nested_shape'], + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/OutputTypeTestObj.hack b/tests/gen/OutputTypeTestObj.hack index aab4325..eb8067e 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<<09695374eb1e58934de4020b3263ef25>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -38,6 +38,7 @@ final class OutputTypeTestObj extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> await $parent->awaitable(), + vec[], ); case 'awaitable_nullable': return new GraphQL\FieldDefinition( @@ -45,6 +46,7 @@ final class OutputTypeTestObj extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> await $parent->awaitable_nullable(), + vec[], ); case 'awaitable_nullable_list': return new GraphQL\FieldDefinition( @@ -52,6 +54,7 @@ final class OutputTypeTestObj extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> await $parent->awaitable_nullable_list(), + vec[], ); case 'list': return new GraphQL\FieldDefinition( @@ -59,6 +62,7 @@ final class OutputTypeTestObj extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->list(), + vec[], ); case 'nested_lists': return new GraphQL\FieldDefinition( @@ -66,6 +70,7 @@ final class OutputTypeTestObj extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput()->nonNullableOutputListOf()->nullableOutputListOf()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->nested_lists(), + vec[], ); case 'nullable': return new GraphQL\FieldDefinition( @@ -73,6 +78,7 @@ final class OutputTypeTestObj extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->nullable(), + vec[], ); case 'output_shape': return new GraphQL\FieldDefinition( @@ -80,6 +86,7 @@ final class OutputTypeTestObj extends \Slack\GraphQL\Types\ObjectType { OutputShape::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->output_shape(), + vec[], ); case 'scalar': return new GraphQL\FieldDefinition( @@ -87,9 +94,14 @@ final class OutputTypeTestObj extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->scalar(), + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/PageInfo.hack b/tests/gen/PageInfo.hack index 93c39c7..8ee4d0b 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<<5bfc5f3b5335acce9fe7662d1508d4a7>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -34,6 +34,7 @@ final class PageInfo extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['startCursor'] ?? null, + vec[], ); case 'endCursor': return new GraphQL\FieldDefinition( @@ -41,6 +42,7 @@ final class PageInfo extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['endCursor'] ?? null, + vec[], ); case 'hasPreviousPage': return new GraphQL\FieldDefinition( @@ -48,6 +50,7 @@ final class PageInfo extends \Slack\GraphQL\Types\ObjectType { Types\BooleanType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['hasPreviousPage'] ?? null, + vec[], ); case 'hasNextPage': return new GraphQL\FieldDefinition( @@ -55,9 +58,14 @@ final class PageInfo extends \Slack\GraphQL\Types\ObjectType { Types\BooleanType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['hasNextPage'] ?? null, + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/Query.hack b/tests/gen/Query.hack index 894f2c0..b6b3a13 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<<1fe6f2b89af7fb1bc13a159233c38301>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -51,6 +51,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { __Schema::nullableOutput(), dict[], async ($parent, $args, $vars) ==> new Schema(), + vec[], ); case '__type': return new GraphQL\FieldDefinition( @@ -66,6 +67,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nonNullable()->coerceNamedNode('name', $args, $vars), ), + vec[], ); case 'allFooObjects': return new GraphQL\FieldDefinition( @@ -99,6 +101,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableInput()->coerceOptionalNamedNode('first', $args, $vars, null), Types\IntType::nullableInput()->coerceOptionalNamedNode('last', $args, $vars, null), ), + vec[], ); case 'alphabetConnection': return new GraphQL\FieldDefinition( @@ -132,6 +135,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableInput()->coerceOptionalNamedNode('first', $args, $vars, null), Types\IntType::nullableInput()->coerceOptionalNamedNode('last', $args, $vars, null), ), + vec[], ); case 'arg_test': return new GraphQL\FieldDefinition( @@ -157,6 +161,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableInput()->coerceNamedNode('nullable', $args, $vars), Types\IntType::nullableInput()->coerceOptionalNamedNode('optional', $args, $vars, 42), ), + vec[], ); case 'bot': return new GraphQL\FieldDefinition( @@ -171,6 +176,9 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> await \UserQueryAttributes::getBot( Types\IntType::nonNullable()->coerceNamedNode('id', $args, $vars), ), + vec[ + new \Directives\LogSampled(1.100000, "foo"), + ], ); case 'error_test': return new GraphQL\FieldDefinition( @@ -178,6 +186,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { ErrorTestObj::nullableOutput(), dict[], async ($parent, $args, $vars) ==> \ErrorTestObj::get(), + vec[], ); case 'error_test_nn': return new GraphQL\FieldDefinition( @@ -185,6 +194,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { ErrorTestObj::nonNullable(), dict[], async ($parent, $args, $vars) ==> \ErrorTestObj::getNonNullable(), + vec[], ); case 'getBaz': return new GraphQL\FieldDefinition( @@ -192,6 +202,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { Baz::nullableOutput(), dict[], async ($parent, $args, $vars) ==> \UserQueryAttributes::getBaz(), + vec[], ); case 'getConcrete': return new GraphQL\FieldDefinition( @@ -199,6 +210,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { Concrete::nullableOutput(), dict[], async ($parent, $args, $vars) ==> \Concrete::getConcrete(), + vec[], ); case 'getFoo': return new GraphQL\FieldDefinition( @@ -206,6 +218,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { FooObject::nullableOutput(), dict[], async ($parent, $args, $vars) ==> \UserQueryAttributes::getFoo(), + vec[], ); case 'getInterfaceA': return new GraphQL\FieldDefinition( @@ -213,6 +226,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { InterfaceA::nullableOutput(), dict[], async ($parent, $args, $vars) ==> \Concrete::getInterfaceA(), + vec[], ); case 'getInterfaceB': return new GraphQL\FieldDefinition( @@ -220,6 +234,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { InterfaceB::nullableOutput(), dict[], async ($parent, $args, $vars) ==> \Concrete::getInterfaceB(), + vec[], ); case 'getObjectShape': return new GraphQL\FieldDefinition( @@ -227,6 +242,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { ObjectShape::nullableOutput(), dict[], async ($parent, $args, $vars) ==> \ObjectTypeTestEntrypoint::getObjectShape(), + vec[], ); case 'human': return new GraphQL\FieldDefinition( @@ -241,6 +257,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> await \UserQueryAttributes::getHuman( Types\IntType::nonNullable()->coerceNamedNode('id', $args, $vars), ), + vec[], ); case 'introspection_test': return new GraphQL\FieldDefinition( @@ -248,6 +265,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { IntrospectionTestObject::nullableOutput(), dict[], async ($parent, $args, $vars) ==> \IntrospectionTestObject::get(), + vec[], ); case 'list_arg_test': return new GraphQL\FieldDefinition( @@ -262,6 +280,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> \ArgumentTestObj::listArgTest( Types\IntType::nonNullable()->nullableInputListOf()->nonNullableInputListOf()->nullableInputListOf()->coerceNamedNode('arg', $args, $vars), ), + vec[], ); case 'nested_list_sum': return new GraphQL\FieldDefinition( @@ -276,6 +295,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> \UserQueryAttributes::getNestedListSum( Types\IntType::nonNullable()->nonNullableInputListOf()->nonNullableInputListOf()->coerceNamedNode('numbers', $args, $vars), ), + vec[], ); case 'optional_field_test': return new GraphQL\FieldDefinition( @@ -290,6 +310,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> \UserQueryAttributes::optionalFieldTest( CreateUserInput::nonNullable()->coerceNamedNode('input', $args, $vars), ), + vec[], ); case 'output_type_test': return new GraphQL\FieldDefinition( @@ -297,6 +318,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { OutputTypeTestObj::nullableOutput(), dict[], async ($parent, $args, $vars) ==> \OutputTypeTestObj::get(), + vec[], ); case 'takes_favorite_color': return new GraphQL\FieldDefinition( @@ -311,6 +333,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> \UserQueryAttributes::takesFavoriteColor( FavoriteColor::nonNullable()->coerceNamedNode('favorite_color', $args, $vars), ), + vec[], ); case 'user': return new GraphQL\FieldDefinition( @@ -325,6 +348,7 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> await \UserQueryAttributes::getUser( Types\IntType::nonNullable()->coerceNamedNode('id', $args, $vars), ), + vec[], ); case 'viewer': return new GraphQL\FieldDefinition( @@ -332,9 +356,14 @@ final class Query extends \Slack\GraphQL\Types\ObjectType { User::nullableOutput(), dict[], async ($parent, $args, $vars) ==> await \UserQueryAttributes::getViewer(), + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/StringTypeEdge.hack b/tests/gen/StringTypeEdge.hack index 27333d5..6eb625b 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<<099876231b60f10f885505f29fd17d3e>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -32,6 +32,7 @@ final class StringTypeEdge extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getNode(), + vec[], ); case 'cursor': return new GraphQL\FieldDefinition( @@ -39,9 +40,14 @@ final class StringTypeEdge extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getCursor(), + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/Team.hack b/tests/gen/Team.hack index d541d9d..96e7ce6 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<<28b06e9d05212da52e2b0f1c80871c2b>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -41,6 +41,7 @@ final class Team extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> $parent->getDescription( Types\BooleanType::nonNullable()->coerceNamedNode('short', $args, $vars), ), + vec[], ); case 'id': return new GraphQL\FieldDefinition( @@ -48,6 +49,7 @@ final class Team extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getId(), + vec[], ); case 'name': return new GraphQL\FieldDefinition( @@ -55,6 +57,7 @@ final class Team extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getName(), + vec[], ); case 'num_users': return new GraphQL\FieldDefinition( @@ -62,9 +65,14 @@ final class Team extends \Slack\GraphQL\Types\ObjectType { Types\IntType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> await $parent->getNumUsers(), + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/User.hack b/tests/gen/User.hack index 77678fb..7081774 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<> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -36,6 +36,7 @@ final class User extends \Slack\GraphQL\Types\InterfaceType { Types\IntType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getId(), + vec[], ); case 'is_active': return new GraphQL\FieldDefinition( @@ -43,6 +44,7 @@ final class User extends \Slack\GraphQL\Types\InterfaceType { Types\BooleanType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->isActive(), + vec[], ); case 'name': return new GraphQL\FieldDefinition( @@ -50,6 +52,7 @@ final class User extends \Slack\GraphQL\Types\InterfaceType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getName(), + vec[], ); case 'team': return new GraphQL\FieldDefinition( @@ -57,12 +60,19 @@ final class User extends \Slack\GraphQL\Types\InterfaceType { Team::nullableOutput(), dict[], async ($parent, $args, $vars) ==> await $parent->getTeam(), + vec[], ); default: return null; } } + public function getDirectives(): vec { + return vec[ + new \Directives\AnotherDirective(), + ]; + } + public async function resolveAsync( this::THackType $value, vec<\Graphpinator\Parser\Field\IHasSelectionSet> $parent_nodes, diff --git a/tests/gen/UserConnection.hack b/tests/gen/UserConnection.hack index f43672f..83b2e83 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<> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -32,6 +32,7 @@ final class UserConnection extends \Slack\GraphQL\Types\ObjectType { UserEdge::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> await $parent->getEdges(), + vec[], ); case 'pageInfo': return new GraphQL\FieldDefinition( @@ -39,9 +40,14 @@ final class UserConnection extends \Slack\GraphQL\Types\ObjectType { PageInfo::nullableOutput(), dict[], async ($parent, $args, $vars) ==> await $parent->getPageInfo(), + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/UserEdge.hack b/tests/gen/UserEdge.hack index f19bb53..9cf5370 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<<5665608d7c5975f884ca8afb7893bdc5>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -32,6 +32,7 @@ final class UserEdge extends \Slack\GraphQL\Types\ObjectType { User::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getNode(), + vec[], ); case 'cursor': return new GraphQL\FieldDefinition( @@ -39,9 +40,14 @@ final class UserEdge extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getCursor(), + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/__Directive.hack b/tests/gen/__Directive.hack index 4853811..af99713 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<<8d1002ab1c1f4c808b79f8bf6b909a32>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -34,6 +34,7 @@ final class __Directive extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['name'], + vec[], ); case 'description': return new GraphQL\FieldDefinition( @@ -41,6 +42,7 @@ final class __Directive extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['description'], + vec[], ); case 'locations': return new GraphQL\FieldDefinition( @@ -48,6 +50,7 @@ final class __Directive extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent['locations'], + vec[], ); case 'args': return new GraphQL\FieldDefinition( @@ -55,9 +58,14 @@ final class __Directive extends \Slack\GraphQL\Types\ObjectType { __InputValue::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent['args'], + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/__EnumValue.hack b/tests/gen/__EnumValue.hack index 7c8dfd0..7de6c4a 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<> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -34,6 +34,7 @@ final class __EnumValue extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['name'], + vec[], ); case 'isDeprecated': return new GraphQL\FieldDefinition( @@ -41,6 +42,7 @@ final class __EnumValue extends \Slack\GraphQL\Types\ObjectType { Types\BooleanType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['isDeprecated'], + vec[], ); case 'description': return new GraphQL\FieldDefinition( @@ -48,6 +50,7 @@ final class __EnumValue extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['description'] ?? null, + vec[], ); case 'deprecationReason': return new GraphQL\FieldDefinition( @@ -55,9 +58,14 @@ final class __EnumValue extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['deprecationReason'] ?? null, + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/__Field.hack b/tests/gen/__Field.hack index dd48c35..b2888b5 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<<237fce4f25f9799eb3a313c7c981f5af>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -36,6 +36,7 @@ final class __Field extends \Slack\GraphQL\Types\ObjectType { __InputValue::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->getArgs(), + vec[], ); case 'deprecationReason': return new GraphQL\FieldDefinition( @@ -43,6 +44,7 @@ final class __Field extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getDeprecationReason(), + vec[], ); case 'description': return new GraphQL\FieldDefinition( @@ -50,6 +52,7 @@ final class __Field extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getDescription(), + vec[], ); case 'isDeprecated': return new GraphQL\FieldDefinition( @@ -57,6 +60,7 @@ final class __Field extends \Slack\GraphQL\Types\ObjectType { Types\BooleanType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->isDeprecated(), + vec[], ); case 'name': return new GraphQL\FieldDefinition( @@ -64,6 +68,7 @@ final class __Field extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getName(), + vec[], ); case 'type': return new GraphQL\FieldDefinition( @@ -71,9 +76,14 @@ final class __Field extends \Slack\GraphQL\Types\ObjectType { __Type::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getType(), + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/__InputValue.hack b/tests/gen/__InputValue.hack index 84df0d3..3ac30fa 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,7 @@ final class __InputValue extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['name'], + vec[], ); case 'description': return new GraphQL\FieldDefinition( @@ -41,6 +42,7 @@ final class __InputValue extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['description'] ?? null, + vec[], ); case 'type': return new GraphQL\FieldDefinition( @@ -48,6 +50,7 @@ final class __InputValue extends \Slack\GraphQL\Types\ObjectType { __Type::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['type'], + vec[], ); case 'defaultValue': return new GraphQL\FieldDefinition( @@ -55,9 +58,14 @@ final class __InputValue extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent['defaultValue'] ?? null, + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/__Schema.hack b/tests/gen/__Schema.hack index a254d4f..34dd14f 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<<7043578f96e44901000cd3cee9dcfb23>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -35,6 +35,7 @@ final class __Schema extends \Slack\GraphQL\Types\ObjectType { __Directive::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->getDirectives(), + vec[], ); case 'mutationType': return new GraphQL\FieldDefinition( @@ -42,6 +43,7 @@ final class __Schema extends \Slack\GraphQL\Types\ObjectType { __Type::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getIntrospectionMutationType(), + vec[], ); case 'queryType': return new GraphQL\FieldDefinition( @@ -49,6 +51,7 @@ final class __Schema extends \Slack\GraphQL\Types\ObjectType { __Type::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getIntrospectionQueryType(), + vec[], ); case 'subscriptionType': return new GraphQL\FieldDefinition( @@ -56,6 +59,7 @@ final class __Schema extends \Slack\GraphQL\Types\ObjectType { __Type::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getIntrospectionSubscriptionType(), + vec[], ); case 'types': return new GraphQL\FieldDefinition( @@ -63,9 +67,14 @@ final class __Schema extends \Slack\GraphQL\Types\ObjectType { __Type::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->getTypes(), + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } } diff --git a/tests/gen/__Type.hack b/tests/gen/__Type.hack index 05376fb..f37a013 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<<4b5c85309c11eb94cbd9e65361724b45>> */ namespace Slack\GraphQL\Test\Generated; use namespace Slack\GraphQL; @@ -39,6 +39,7 @@ final class __Type extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getIntrospectionDescription(), + vec[], ); case 'enumValues': return new GraphQL\FieldDefinition( @@ -54,6 +55,7 @@ final class __Type extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> $parent->getIntrospectionEnumValues( Types\BooleanType::nonNullable()->coerceOptionalNamedNode('includeDeprecated', $args, $vars, false), ), + vec[], ); case 'fields': return new GraphQL\FieldDefinition( @@ -69,6 +71,7 @@ final class __Type extends \Slack\GraphQL\Types\ObjectType { async ($parent, $args, $vars) ==> $parent->getIntrospectionFields( Types\BooleanType::nonNullable()->coerceOptionalNamedNode('includeDeprecated', $args, $vars, false), ), + vec[], ); case 'inputFields': return new GraphQL\FieldDefinition( @@ -76,6 +79,7 @@ final class __Type extends \Slack\GraphQL\Types\ObjectType { __InputValue::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->getIntrospectionInputFields(), + vec[], ); case 'interfaces': return new GraphQL\FieldDefinition( @@ -83,6 +87,7 @@ final class __Type extends \Slack\GraphQL\Types\ObjectType { __Type::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->getIntrospectionInterfaces(), + vec[], ); case 'kind': return new GraphQL\FieldDefinition( @@ -90,6 +95,7 @@ final class __Type extends \Slack\GraphQL\Types\ObjectType { __TypeKind::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getIntrospectionKind(), + vec[], ); case 'name': return new GraphQL\FieldDefinition( @@ -97,6 +103,7 @@ final class __Type extends \Slack\GraphQL\Types\ObjectType { Types\StringType::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getIntrospectionName(), + vec[], ); case 'ofType': return new GraphQL\FieldDefinition( @@ -104,6 +111,7 @@ final class __Type extends \Slack\GraphQL\Types\ObjectType { __Type::nullableOutput(), dict[], async ($parent, $args, $vars) ==> $parent->getIntrospectionOfType(), + vec[], ); case 'possibleTypes': return new GraphQL\FieldDefinition( @@ -111,9 +119,14 @@ final class __Type extends \Slack\GraphQL\Types\ObjectType { __Type::nonNullable()->nullableOutputListOf(), dict[], async ($parent, $args, $vars) ==> $parent->getIntrospectionPossibleTypes(), + vec[], ); default: return null; } } + + public function getDirectives(): vec { + return vec[]; + } }