-
-
Notifications
You must be signed in to change notification settings - Fork 468
Expand file tree
/
Copy pathIdeHelperCommand.php
More file actions
167 lines (128 loc) · 4.98 KB
/
IdeHelperCommand.php
File metadata and controls
167 lines (128 loc) · 4.98 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
155
156
157
158
159
160
161
162
163
164
165
166
167
<?php
namespace Nuwave\Lighthouse\Console;
use GraphQL\Language\AST\TypeDefinitionNode;
use GraphQL\Language\Parser;
use GraphQL\Type\Definition\Type;
use GraphQL\Utils\SchemaPrinter;
use Illuminate\Console\Command;
use Nuwave\Lighthouse\Schema\AST\ASTCache;
use Nuwave\Lighthouse\Schema\AST\ASTHelper;
use Nuwave\Lighthouse\Schema\DirectiveLocator;
use Nuwave\Lighthouse\Schema\SchemaBuilder;
use Nuwave\Lighthouse\Schema\Source\SchemaSourceProvider;
class IdeHelperCommand extends Command
{
public const OPENING_PHP_TAG = /** @lang GraphQL */ "<?php\n";
public const GENERATED_NOTICE = /** @lang GraphQL */ <<<'GRAPHQL'
# File generated by "php artisan lighthouse:ide-helper".
# Do not edit this file directly.
# This file should be ignored by git as it can be autogenerated.
GRAPHQL;
protected $name = 'lighthouse:ide-helper';
protected $description = 'Create IDE helper files to improve type checking and autocompletion.';
public function handle(): int
{
$this->laravel->call([$this, 'schemaDirectiveDefinitions']);
$this->laravel->call([$this, 'programmaticTypes']);
$this->laravel->call([$this, 'phpIdeHelper']);
$this->info("\nIt is recommended to add them to your .gitignore file.");
return 0;
}
/**
* Create and write schema directive definitions to a file.
*/
public function schemaDirectiveDefinitions(DirectiveLocator $directiveLocator): void
{
$schema = /** @lang GraphQL */ <<<'GRAPHQL'
"""
Placeholder type for various directives such as `@orderBy`.
Will be replaced by a generated type during schema manipulation.
"""
scalar _
GRAPHQL;
foreach ($directiveLocator->classes() as $directiveClass) {
$definition = $this->define($directiveClass);
$schema .= /** @lang GraphQL */ <<<GRAPHQL
# Directive class: {$directiveClass}
{$definition}
GRAPHQL;
}
$filePath = static::schemaDirectivesPath();
\Safe\file_put_contents($filePath, self::GENERATED_NOTICE . $schema);
$this->info("Wrote schema directive definitions to {$filePath}.");
}
/**
* @param class-string<\Nuwave\Lighthouse\Support\Contracts\Directive> $directiveClass
*
* @throws \Nuwave\Lighthouse\Exceptions\DefinitionException
*/
protected function define(string $directiveClass): string
{
$definition = $directiveClass::definition();
// Throws if the definition is invalid
ASTHelper::extractDirectiveDefinition($definition);
return trim($definition);
}
public static function schemaDirectivesPath(): string
{
return base_path() . '/schema-directives.graphql';
}
/**
* Users may register types programmatically, e.g. in service providers.
* In order to allow referencing those in the schema, it is useful to print
* those types to a helper schema, excluding types the user defined in the schema.
*/
public function programmaticTypes(SchemaSourceProvider $schemaSourceProvider, ASTCache $astCache, SchemaBuilder $schemaBuilder): void
{
$sourceSchema = Parser::parse($schemaSourceProvider->getSchemaString());
$sourceTypes = [];
foreach ($sourceSchema->definitions as $definition) {
if ($definition instanceof TypeDefinitionNode) {
$sourceTypes[$definition->name->value] = true;
}
}
$astCache->clear();
$allTypes = $schemaBuilder->schema()->getTypeMap();
$programmaticTypes = array_diff_key($allTypes, $sourceTypes);
$filePath = static::programmaticTypesPath();
if ([] === $programmaticTypes && file_exists($filePath)) {
\Safe\unlink($filePath);
return;
}
$schema = implode(
"\n\n",
array_map(
function (Type $type): string {
return SchemaPrinter::printType($type);
},
$programmaticTypes
)
);
\Safe\file_put_contents($filePath, self::GENERATED_NOTICE . $schema . "\n");
$this->info("Wrote definitions for programmatically registered types to {$filePath}.");
}
public static function programmaticTypesPath(): string
{
return base_path() . '/programmatic-types.graphql';
}
public function phpIdeHelper(): void
{
$filePath = static::phpIdeHelperPath();
$contents = \Safe\file_get_contents(__DIR__ . '/../../_ide_helper.php');
\Safe\file_put_contents($filePath, $this->withGeneratedNotice($contents));
$this->info("Wrote PHP definitions to {$filePath}.");
}
public static function phpIdeHelperPath(): string
{
return base_path() . '/_lighthouse_ide_helper.php';
}
protected function withGeneratedNotice(string $phpContents): string
{
return substr_replace(
$phpContents,
self::OPENING_PHP_TAG . self::GENERATED_NOTICE,
0,
strlen(self::OPENING_PHP_TAG)
);
}
}