-
Notifications
You must be signed in to change notification settings - Fork 225
Expand file tree
/
Copy pathGraphQLDumpSchemaCommand.php
More file actions
154 lines (129 loc) · 4.96 KB
/
GraphQLDumpSchemaCommand.php
File metadata and controls
154 lines (129 loc) · 4.96 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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<?php
declare(strict_types=1);
namespace Overblog\GraphQLBundle\Command;
use GraphQL\Type\Introspection;
use GraphQL\Utils\SchemaPrinter;
use InvalidArgumentException;
use Overblog\GraphQLBundle\Request\Executor as RequestExecutor;
use Overblog\GraphQLBundle\Resolver\TypeResolver;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use function file_put_contents;
use function json_encode;
use function realpath;
use function sprintf;
use function strtolower;
use const JSON_PRETTY_PRINT;
final class GraphQLDumpSchemaCommand extends Command
{
private RequestExecutor $requestExecutor;
private string $baseExportPath;
public function __construct(string $baseExportPath, RequestExecutor $requestExecutor, TypeResolver $typeResolver)
{
parent::__construct();
$this->baseExportPath = $baseExportPath;
$this->requestExecutor = $requestExecutor;
// Disable exception when an unresolvable types is encountered. Schema dump will try to access the Query, Mutation and Subscription types and will fail if they are not defined.
$typeResolver->setIgnoreUnresolvableException(true);
}
public function getRequestExecutor(): RequestExecutor
{
return $this->requestExecutor;
}
protected function configure(): void
{
$this
->setName('graphql:dump-schema')
->setAliases(['graph:dump-schema'])
->setDescription('Dumps GraphQL schema')
->addOption(
'file',
null,
InputOption::VALUE_OPTIONAL,
'Path to generate schema file.'
)
->addOption(
'schema',
null,
InputOption::VALUE_OPTIONAL,
'The schema name to generate.'
)
->addOption(
'format',
null,
InputOption::VALUE_OPTIONAL,
'The schema format to generate ("graphql" or "json").',
'json'
)
->addOption(
'modern',
null,
InputOption::VALUE_NONE,
'Enabled modern json format: { "data": { "__schema": {...} } }.'
)
->addOption(
'classic',
null,
InputOption::VALUE_NONE,
'Enabled classic json format: { "__schema": {...} }.'
)
->addOption(
'with-descriptions',
null,
InputOption::VALUE_NONE,
'Dump schema including descriptions.'
)
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$file = $this->createFile($input);
$io->success(sprintf('GraphQL schema "%s" was successfully dumped.', realpath($file)));
return 0;
}
private function createFile(InputInterface $input): string
{
$format = strtolower($input->getOption('format'));
/** @var string|null $schemaName */
$schemaName = $input->getOption('schema');
/** @var bool $includeDescription */
$includeDescription = $input->getOption('with-descriptions');
/** @var string $file */
$file = $input->getOption('file') ?: $this->baseExportPath.sprintf('/schema%s.%s', $schemaName ? '.'.$schemaName : '', $format);
switch ($format) {
case 'json':
$request = [
'query' => Introspection::getIntrospectionQuery(['descriptions' => $includeDescription]),
'variables' => [],
'operationName' => null,
];
$modern = $this->useModernJsonFormat($input);
$result = $this->getRequestExecutor()
->execute($schemaName, $request)
->toArray();
$content = json_encode($modern ? $result : ($result['data'] ?? null), JSON_PRETTY_PRINT);
break;
case 'graphql':
$content = SchemaPrinter::doPrint($this->getRequestExecutor()->getSchema($schemaName));
break;
default:
throw new InvalidArgumentException(sprintf('Unknown format %s.', json_encode($format)));
}
file_put_contents($file, $content);
// @phpstan-ignore-next-line
return $file;
}
private function useModernJsonFormat(InputInterface $input): bool
{
$modern = $input->getOption('modern');
$classic = $input->getOption('classic');
if ($modern && $classic) {
throw new InvalidArgumentException('"modern" and "classic" options should not be used together.');
}
return true === $modern;
}
}