From 9d1e54fc6e5513ebfbcffb8880df4f01273ad2ee Mon Sep 17 00:00:00 2001 From: Benedikt Franke Date: Sun, 1 Dec 2024 16:16:48 +0100 Subject: [PATCH 1/3] Expose query complexity score in BuildExtensionsResponse https://github.com/nuwave/lighthouse/discussions/2634 --- docs/master/api-reference/events.md | 24 +++++++++++-------- src/Events/BuildExtensionsResponse.php | 2 ++ src/Execution/ExtensionsResponse.php | 12 +++------- src/GraphQL.php | 14 +++++++---- .../Directives/ComplexityDirectiveTest.php | 15 ++++++++++++ 5 files changed, 44 insertions(+), 23 deletions(-) diff --git a/docs/master/api-reference/events.md b/docs/master/api-reference/events.md index 4e2923a8d2..64164a9085 100644 --- a/docs/master/api-reference/events.md +++ b/docs/master/api-reference/events.md @@ -175,31 +175,35 @@ class StartExecution ### BuildExtensionsResponse ```php +use GraphQL\Executor\ExecutionResult; + /** * Fires after a query was resolved. * * Listeners may return a @see \Nuwave\Lighthouse\Execution\ExtensionsResponse * to include in the response. */ -class BuildExtensionsResponse {} +class BuildExtensionsResponse +{ + public function __construct( + /** The result of resolving a single operation. */ + public ExecutionResult $result, + /** The calculated query complexity score of the operation, only available if the validation rule is enabled. */ + public ?int $queryComplexity, + ) {} +} ``` ```php namespace Nuwave\Lighthouse\Execution; -/** - * May be returned from listeners of @see \Nuwave\Lighthouse\Events\BuildExtensionsResponse. - */ +/** May be returned from listeners of @see \Nuwave\Lighthouse\Events\BuildExtensionsResponse. */ class ExtensionsResponse { public function __construct( - /** - * Will be used as the key in the response map. - */ + /** Will be used as the key in the response map. */ public string $key, - /** - * JSON-encodable content of the extension. - */ + /** JSON-encodable content of the extension. */ public mixed $content, ) {} } diff --git a/src/Events/BuildExtensionsResponse.php b/src/Events/BuildExtensionsResponse.php index d3594d6a0a..2c1a9216f8 100644 --- a/src/Events/BuildExtensionsResponse.php +++ b/src/Events/BuildExtensionsResponse.php @@ -15,5 +15,7 @@ class BuildExtensionsResponse public function __construct( /** The result of resolving a single operation. */ public ExecutionResult $result, + /** The calculated query complexity score of the operation, only available if the validation rule is enabled. */ + public ?int $queryComplexity, ) {} } diff --git a/src/Execution/ExtensionsResponse.php b/src/Execution/ExtensionsResponse.php index 79fa74462c..50d60f0798 100644 --- a/src/Execution/ExtensionsResponse.php +++ b/src/Execution/ExtensionsResponse.php @@ -2,19 +2,13 @@ namespace Nuwave\Lighthouse\Execution; -/** - * May be returned from listeners of @see \Nuwave\Lighthouse\Events\BuildExtensionsResponse. - */ +/** May be returned from listeners of @see \Nuwave\Lighthouse\Events\BuildExtensionsResponse. */ class ExtensionsResponse { public function __construct( - /** - * Will be used as the key in the response map. - */ + /** Will be used as the key in the response map. */ public string $key, - /** - * JSON-encodable content of the extension. - */ + /** JSON-encodable content of the extension. */ public mixed $content, ) {} } diff --git a/src/GraphQL.php b/src/GraphQL.php index 36e71f3e02..66feba7880 100644 --- a/src/GraphQL.php +++ b/src/GraphQL.php @@ -135,14 +135,16 @@ public function executeParsedQueryRaw( ); if ($this->providesValidationRules instanceof CacheableValidationRulesProvider) { - $validationRules = $this->providesValidationRules->cacheableValidationRules(); + $cacheableValidationRules = $this->providesValidationRules->cacheableValidationRules(); - $errors = $this->validateCacheableRules($validationRules, $schema, $this->schemaBuilder->schemaHash(), $query, $queryHash); + $errors = $this->validateCacheableRules($cacheableValidationRules, $schema, $this->schemaBuilder->schemaHash(), $query, $queryHash); if ($errors !== []) { return new ExecutionResult(null, $errors); } } + $validationRules = $this->providesValidationRules->validationRules(); + $result = GraphQLBase::executeQuery( $schema, $query, @@ -151,12 +153,16 @@ public function executeParsedQueryRaw( $variables, $operationName, null, - $this->providesValidationRules->validationRules(), + $validationRules, ); + $queryComplexityRule = $validationRules[QueryComplexity::class] ?? null; + assert($queryComplexityRule instanceof QueryComplexity || $queryComplexityRule === null); + $queryComplexity = $queryComplexityRule?->getQueryComplexity(); + /** @var array<\Nuwave\Lighthouse\Execution\ExtensionsResponse|null> $extensionsResponses */ $extensionsResponses = (array) $this->eventDispatcher->dispatch( - new BuildExtensionsResponse($result), + new BuildExtensionsResponse($result, $queryComplexity), ); foreach ($extensionsResponses as $extensionsResponse) { diff --git a/tests/Unit/Schema/Directives/ComplexityDirectiveTest.php b/tests/Unit/Schema/Directives/ComplexityDirectiveTest.php index 5ccee1d121..22719f000a 100644 --- a/tests/Unit/Schema/Directives/ComplexityDirectiveTest.php +++ b/tests/Unit/Schema/Directives/ComplexityDirectiveTest.php @@ -4,6 +4,8 @@ use GraphQL\Validator\Rules\QueryComplexity; use Illuminate\Contracts\Config\Repository as ConfigRepository; +use Illuminate\Contracts\Events\Dispatcher as EventsDispatcher; +use Nuwave\Lighthouse\Events\BuildExtensionsResponse; use Tests\TestCase; use Tests\Utils\Queries\Foo; @@ -13,6 +15,14 @@ final class ComplexityDirectiveTest extends TestCase public function testDefaultComplexity(): void { + $eventsDispatcher = $this->app->make(EventsDispatcher::class); + + /** @var array $events */ + $events = []; + $eventsDispatcher->listen(BuildExtensionsResponse::class, static function (BuildExtensionsResponse $event) use (&$events): void { + $events[] = $event; + }); + $max = 1; $this->setMaxQueryComplexity($max); @@ -33,6 +43,11 @@ public function testDefaultComplexity(): void } } ')->assertGraphQLErrorMessage(QueryComplexity::maxQueryComplexityErrorMessage($max, 2)); + + $this->assertCount(1, $events); + + $event = $events[0]; + $this->assertSame(2, $event->queryComplexity); } public function testKnowsPagination(): void From 85bd42f0e4380c7626dc16e93a43c0554ae603a3 Mon Sep 17 00:00:00 2001 From: Benedikt Franke Date: Sun, 1 Dec 2024 16:17:49 +0100 Subject: [PATCH 2/3] release --- CHANGELOG.md | 6 ++++++ docs/6/api-reference/events.md | 24 ++++++++++++++---------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5bd5fa17f..a8a64f4ed4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ You can find and compare releases at the [GitHub release page](https://github.co ## Unreleased +## v6.46.0 + +### Added + +- Expose query complexity score in lifecycle event `BuildExtensionsResponse` https://github.com/nuwave/lighthouse/pull/2637 + ## v6.45.1 ### Fixed diff --git a/docs/6/api-reference/events.md b/docs/6/api-reference/events.md index 4e2923a8d2..64164a9085 100644 --- a/docs/6/api-reference/events.md +++ b/docs/6/api-reference/events.md @@ -175,31 +175,35 @@ class StartExecution ### BuildExtensionsResponse ```php +use GraphQL\Executor\ExecutionResult; + /** * Fires after a query was resolved. * * Listeners may return a @see \Nuwave\Lighthouse\Execution\ExtensionsResponse * to include in the response. */ -class BuildExtensionsResponse {} +class BuildExtensionsResponse +{ + public function __construct( + /** The result of resolving a single operation. */ + public ExecutionResult $result, + /** The calculated query complexity score of the operation, only available if the validation rule is enabled. */ + public ?int $queryComplexity, + ) {} +} ``` ```php namespace Nuwave\Lighthouse\Execution; -/** - * May be returned from listeners of @see \Nuwave\Lighthouse\Events\BuildExtensionsResponse. - */ +/** May be returned from listeners of @see \Nuwave\Lighthouse\Events\BuildExtensionsResponse. */ class ExtensionsResponse { public function __construct( - /** - * Will be used as the key in the response map. - */ + /** Will be used as the key in the response map. */ public string $key, - /** - * JSON-encodable content of the extension. - */ + /** JSON-encodable content of the extension. */ public mixed $content, ) {} } From e1178c78b733048e789db790687b923a0a8af3ff Mon Sep 17 00:00:00 2001 From: Benedikt Franke Date: Sun, 1 Dec 2024 16:21:59 +0100 Subject: [PATCH 3/3] fix ci for lower deps --- src/GraphQL.php | 7 +++++-- tests/Unit/Schema/Directives/ComplexityDirectiveTest.php | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/GraphQL.php b/src/GraphQL.php index 66feba7880..10edfd30c1 100644 --- a/src/GraphQL.php +++ b/src/GraphQL.php @@ -157,8 +157,11 @@ public function executeParsedQueryRaw( ); $queryComplexityRule = $validationRules[QueryComplexity::class] ?? null; - assert($queryComplexityRule instanceof QueryComplexity || $queryComplexityRule === null); - $queryComplexity = $queryComplexityRule?->getQueryComplexity(); + $queryComplexity = $queryComplexityRule instanceof QueryComplexity + // TODO remove this check when updating the required version of webonyx/graphql-php + && method_exists($queryComplexityRule, 'getQueryComplexity') + ? $queryComplexityRule->getQueryComplexity() + : null; /** @var array<\Nuwave\Lighthouse\Execution\ExtensionsResponse|null> $extensionsResponses */ $extensionsResponses = (array) $this->eventDispatcher->dispatch( diff --git a/tests/Unit/Schema/Directives/ComplexityDirectiveTest.php b/tests/Unit/Schema/Directives/ComplexityDirectiveTest.php index 22719f000a..418349a44d 100644 --- a/tests/Unit/Schema/Directives/ComplexityDirectiveTest.php +++ b/tests/Unit/Schema/Directives/ComplexityDirectiveTest.php @@ -46,8 +46,11 @@ public function testDefaultComplexity(): void $this->assertCount(1, $events); - $event = $events[0]; - $this->assertSame(2, $event->queryComplexity); + // TODO remove this check when updating the required version of webonyx/graphql-php + if (method_exists(QueryComplexity::class, 'getQueryComplexity')) { + $event = $events[0]; + $this->assertSame(2, $event->queryComplexity); + } } public function testKnowsPagination(): void