forked from nuwave/lighthouse
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathASTManipulator.php
More file actions
107 lines (91 loc) · 3.56 KB
/
ASTManipulator.php
File metadata and controls
107 lines (91 loc) · 3.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<?php
namespace Nuwave\Lighthouse\Federation;
use GraphQL\Language\AST\ObjectTypeDefinitionNode;
use GraphQL\Language\Parser;
use Nuwave\Lighthouse\Events\ManipulateAST;
use Nuwave\Lighthouse\Exceptions\FederationException;
use Nuwave\Lighthouse\Schema\AST\DocumentAST;
use Nuwave\Lighthouse\Schema\RootType;
class ASTManipulator
{
public function handle(ManipulateAST $manipulateAST): void
{
$documentAST = $manipulateAST->documentAST;
$this->addScalars($documentAST);
$this->addEntityUnion($documentAST);
$this->addRootFields($documentAST);
$this->addServiceType($documentAST);
}
protected function addScalars(DocumentAST &$documentAST): void
{
$documentAST->setTypeDefinition(
Parser::scalarTypeDefinition(/** @lang GraphQL */ '
scalar _Any @scalar(class: "Nuwave\\\Lighthouse\\\Federation\\\Types\\\Any")
')
);
$documentAST->setTypeDefinition(
Parser::scalarTypeDefinition(/** @lang GraphQL */ '
scalar _FieldSet @scalar(class: "Nuwave\\\Lighthouse\\\Federation\\\Types\\\FieldSet")
')
);
}
/**
* Combine object types with `@key` into the _Entity union.
*
* @throws \Nuwave\Lighthouse\Exceptions\FederationException
*/
protected function addEntityUnion(DocumentAST &$documentAST): void
{
/** @var array<int, string> $entities */
$entities = [];
foreach ($documentAST->types as $type) {
if (! $type instanceof ObjectTypeDefinitionNode) {
continue;
}
/** @var \GraphQL\Language\AST\DirectiveNode $directive */
foreach ($type->directives as $directive) {
if ($directive->name->value === 'key') {
$entities[] = $type->name->value;
break;
}
}
}
if (count($entities) === 0) {
throw new FederationException('There must be at least one type using the @key directive when federation is enabled.');
}
$entitiesString = implode(' | ', $entities);
$documentAST->setTypeDefinition(
Parser::unionTypeDefinition(/** @lang GraphQL */ "
union _Entity = {$entitiesString}
")
);
}
protected function addRootFields(DocumentAST &$documentAST): void
{
// In federation it is fine for a schema to not have a user-defined root query type,
// since we add two federation related fields to it here.
if (! isset($documentAST->types[RootType::QUERY])) {
$documentAST->types[RootType::QUERY] = Parser::objectTypeDefinition(/** @lang GraphQL */ 'type Query');
}
/** @var \GraphQL\Language\AST\ObjectTypeDefinitionNode $queryType */
$queryType = $documentAST->types[RootType::QUERY];
$queryType->fields [] = Parser::fieldDefinition(/** @lang GraphQL */ '
_entities(
representations: [_Any!]!
): [_Entity]! @field(resolver: "Nuwave\\\Lighthouse\\\Federation\\\Resolvers\\\Entities")
');
$queryType->fields [] = Parser::fieldDefinition(/** @lang GraphQL */ '
_service: _Service! @field(resolver: "Nuwave\\\Lighthouse\\\Federation\\\Resolvers\\\Service")
');
}
protected function addServiceType(DocumentAST &$documentAST): void
{
$documentAST->setTypeDefinition(
Parser::objectTypeDefinition(/** @lang GraphQL */ '
type _Service {
sdl: String
}
')
);
}
}