protected function setNodeKey(NodeValue $nodeValue): void
    {
        if ($nodeValue->getCacheKey()) {
            return;
        }

        $fields = data_get($nodeValue->getTypeDefinition(), 'fields', []);
        $nodeKey = (new Collection($fields))->reduce(function (?string $key, FieldDefinitionNode $field): ?string {
            if ($key) {
                return $key;
            }

            $hasCacheKey = (new Collection($field->directives))
                ->contains(function (DirectiveNode $directive): bool {
                    return $directive->name->value === 'cacheKey';
                });

            return $hasCacheKey
                ? $field->name->value
                : $key;
        });

        if (! $nodeKey) {
            $nodeKey = (new Collection($fields))->reduce(function (?string $key, FieldDefinitionNode $field): ?string {
                if ($key) {
                    return $key;
                }

                $typeName = ASTHelper::getUnderlyingTypeName($field);

                return $typeName === 'ID'
                    ? $field->name->value
                    : $key;
            });
        }

        if (! $nodeKey && $nodeValue->getTypeDefinitionName() !== 'Query') {
            throw new DirectiveException(
                "No @cacheKey or ID field defined on {$nodeValue->getTypeDefinitionName()}"
            );
        }

        $nodeValue->setCacheKey($nodeKey);
    }