From ffbb68b75719b50c9c94a0e90f5d701233bc6ec6 Mon Sep 17 00:00:00 2001 From: Andrii Sudiev Date: Fri, 27 Sep 2024 01:52:48 +0300 Subject: [PATCH] allow promise to be returned in methods --- src/QueryField.php | 25 ++++++++++++++-------- tests/Fixtures/Integration/Models/Blog.php | 13 +++++------ 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/QueryField.php b/src/QueryField.php index 0a63038b6..656cc99a5 100644 --- a/src/QueryField.php +++ b/src/QueryField.php @@ -74,15 +74,7 @@ public function __construct( $callResolver = function (...$args) use ($originalResolver, $source, $resolver) { $result = $resolver($source, ...$args); - try { - $this->assertReturnType($result); - } catch (TypeMismatchRuntimeException $e) { - $e->addInfo($this->name, $originalResolver->toString()); - - throw $e; - } - - return $result; + return $this->unwrapReturnType($result, $originalResolver); }; // GraphQL allows deferring resolving the field's value using promises, i.e. they call the resolve @@ -98,6 +90,21 @@ public function __construct( parent::__construct($config); } + private function unwrapReturnType(mixed $result, ResolverInterface $originalResolver): mixed + { + if ($result instanceof SyncPromise) { + return $result->then(fn ($resolvedValue) => $this->unwrapReturnType($resolvedValue, $originalResolver)); + } + try { + $this->assertReturnType($result); + } catch (TypeMismatchRuntimeException $e) { + $e->addInfo($this->name, $originalResolver->toString()); + + throw $e; + } + return $result; + } + /** * This method checks the returned value of the resolver to be sure it matches the documented return type. * We are sure the returned value is of the correct type... except if the return type is type-hinted as an array. diff --git a/tests/Fixtures/Integration/Models/Blog.php b/tests/Fixtures/Integration/Models/Blog.php index f3b593841..80812119f 100644 --- a/tests/Fixtures/Integration/Models/Blog.php +++ b/tests/Fixtures/Integration/Models/Blog.php @@ -4,6 +4,7 @@ namespace TheCodingMachine\GraphQLite\Fixtures\Integration\Models; +use GraphQL\Deferred; use TheCodingMachine\GraphQLite\Annotations\Field; use TheCodingMachine\GraphQLite\Annotations\Prefetch; use TheCodingMachine\GraphQLite\Annotations\Type; @@ -35,17 +36,13 @@ public function getPosts( return $prefetchedPosts[$this->id]; } - /** - * @param Blog[][] $prefetchedSubBlogs - * - * @return Blog[] - */ - #[Field] + /** @param Blog[][] $prefetchedSubBlogs */ + #[Field(outputType: '[Blog!]!')] public function getSubBlogs( #[Prefetch('prefetchSubBlogs')] array $prefetchedSubBlogs, - ): array { - return $prefetchedSubBlogs[$this->id]; + ): Deferred { + return new Deferred(fn () => $prefetchedSubBlogs[$this->id]); } /**