forked from nuwave/lighthouse
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFederationPrinter.php
More file actions
130 lines (112 loc) · 4.42 KB
/
FederationPrinter.php
File metadata and controls
130 lines (112 loc) · 4.42 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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<?php
namespace Nuwave\Lighthouse\Federation;
use GraphQL\Language\AST\DirectiveNode;
use GraphQL\Language\AST\FieldDefinitionNode;
use GraphQL\Language\AST\ObjectTypeDefinitionNode;
use GraphQL\Type\Definition\Directive;
use GraphQL\Type\Definition\EnumValueDefinition;
use GraphQL\Type\Definition\FieldArgument;
use GraphQL\Type\Definition\FieldDefinition;
use GraphQL\Type\Definition\InputObjectField;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Schema;
use GraphQL\Type\SchemaConfig;
use GraphQL\Utils\Utils;
use Illuminate\Support\Arr;
use Nuwave\Lighthouse\Federation\Directives\ExtendsDirective;
use Nuwave\Lighthouse\Federation\Directives\ExternalDirective;
use Nuwave\Lighthouse\Federation\Directives\KeyDirective;
use Nuwave\Lighthouse\Federation\Directives\ProvidesDirective;
use Nuwave\Lighthouse\Federation\Directives\RequiresDirective;
use Nuwave\Lighthouse\Schema\RootType;
class FederationPrinter
{
const FEDERATION_TYPES = [
'_Any',
'_Entity',
'_FieldSet',
'_Service',
];
const FEDERATION_FIELDS = [
'_service',
'_entities',
];
const FEDERATION_DIRECTIVES = [
ExtendsDirective::NAME,
ExternalDirective::NAME,
KeyDirective::NAME,
ProvidesDirective::NAME,
RequiresDirective::NAME,
];
public static function print(Schema $schema): string
{
$config = SchemaConfig::create();
$types = $schema->getTypeMap();
foreach (self::FEDERATION_TYPES as $type) {
unset($types[$type]);
}
/** @var \GraphQL\Type\Definition\ObjectType $originalQueryType */
$originalQueryType = Arr::pull($types, RootType::QUERY);
$queryFieldsWithoutFederation = array_filter(
$originalQueryType->getFields(),
static function (FieldDefinition $field): bool {
return ! in_array($field->name, static::FEDERATION_FIELDS);
}
);
$newQueryType = count($queryFieldsWithoutFederation) > 0
? new ObjectType([
'name' => RootType::QUERY,
'fields' => $queryFieldsWithoutFederation,
'interfaces' => $originalQueryType->getInterfaces(),
])
: null;
$config->setQuery($newQueryType);
$config->setMutation(Arr::pull($types, RootType::MUTATION));
$config->setSubscription(Arr::pull($types, RootType::SUBSCRIPTION));
$config->setTypes($types);
$config->setDirectives(array_filter(
$schema->getDirectives(),
static function (Directive $directive): bool {
return ! in_array($directive->name, static::FEDERATION_DIRECTIVES);
}
));
$printDirectives = static function ($definition): string {
/** @var Type|EnumValueDefinition|FieldArgument|FieldDefinition|InputObjectField $definition */
$astNode = $definition->astNode;
if ($astNode === null) {
return '';
}
if ($astNode instanceof ObjectTypeDefinitionNode) {
return SchemaPrinter::printDirectives(
Utils::filter(
$astNode->directives,
static function (DirectiveNode $directive): bool {
$name = $directive->name->value;
return $name === KeyDirective::NAME
|| $name === ExtendsDirective::NAME;
}
)
);
} elseif ($astNode instanceof FieldDefinitionNode) {
return SchemaPrinter::printDirectives(
Utils::filter(
$astNode->directives,
static function (DirectiveNode $directive): bool {
$name = $directive->name->value;
return $name === ProvidesDirective::NAME
|| $name === RequiresDirective::NAME
|| $name === ExternalDirective::NAME;
}
)
);
}
return '';
};
return SchemaPrinter::doPrint(
new Schema($config),
// @phpstan-ignore-next-line We extended the SchemaPrinter to allow for this option
['printDirectives' => $printDirectives]
);
}
}