Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ jobs:
- name: Run PHP CS Fixer
run: vendor/bin/php-cs-fixer check --diff

- name: Run Twig CS Fixer
run: vendor/bin/twig-cs-fixer lint

- name: Run PHPStan
run: vendor/bin/phpstan analyse

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
/vendor/
/.php-cs-fixer.cache
/.phpunit.cache/
/.twig-cs-fixer.cache
24 changes: 24 additions & 0 deletions .twig-cs-fixer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

use Ruudk\GraphQLCodeGenerator\Twig\GraphQLTokenParser;
use TwigCsFixer\Ruleset\Ruleset;
use TwigCsFixer\Standard\TwigCsFixer;
use TwigCsFixer\File\Finder;
use TwigCsFixer\Config\Config;

$ruleset = new Ruleset();

$ruleset->addStandard(new TwigCsFixer());

$finder = Finder::create()
->in('tests');

$config = new Config();
$config->allowNonFixableRules();
$config->setCacheFile(__DIR__ . '/.twig-cs-fixer.cache');
$config->setRuleset($ruleset);
$config->setFinder($finder);
$config->addTokenParser(new GraphQLTokenParser());

return $config;

5 changes: 4 additions & 1 deletion captainhook.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@
"action": "\\CaptainHook\\App\\Hook\\PHP\\Action\\Linting"
},
{
"action": "vendor/bin/php-cs-fixer check --diff"
"action": "vendor/bin/php-cs-fixer fix"
},
{
"action": "vendor/bin/twig-cs-fixer fix"
},
{
"action": "vendor/bin/phpstan"
Expand Down
3 changes: 3 additions & 0 deletions composer-dependency-analyser.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
declare(strict_types=1);

use ShipMonk\ComposerDependencyAnalyser\Config\Configuration;
use ShipMonk\ComposerDependencyAnalyser\Config\ErrorType;

$config = new Configuration();

$config->addPathToScan(__DIR__ . '/bin', isDev: false);

$config->ignoreErrorsOnPackage('twig/twig', [ErrorType::DEV_DEPENDENCY_IN_PROD]);

return $config;
8 changes: 7 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"type": "library",
"require": {
"php": "^8.4",
"composer-runtime-api": "^2.0",
"nikic/php-parser": "^5.6",
"phpstan/phpstan": "^2.1",
"ruudk/code-generator": "^0.4.3",
Expand Down Expand Up @@ -40,7 +41,12 @@
"symfony/dotenv": "^7.3",
"symfony/var-dumper": "^7.3",
"ticketswap/php-cs-fixer-config": "^1.0",
"ticketswap/phpstan-error-formatter": "^1.1"
"ticketswap/phpstan-error-formatter": "^1.1",
"twig/twig": "^3.21",
"vincentlanglet/twig-cs-fixer": "^3.9"
},
"suggest": {
"twig/twig": "For generating GraphQL fragments from Twig templates"
},
"autoload": {
"psr-4": {
Expand Down
161 changes: 159 additions & 2 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions src/Config/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* @param list<TypeInitializer\TypeInitializer> $typeInitializers
* @param null|object|(Closure(): object) $introspectionClient
* @param list<string> $inlineProcessingDirectories
* @param list<string> $twigProcessingDirectories
*/
private function __construct(
public Schema | string $schema,
Expand Down Expand Up @@ -48,6 +49,7 @@ private function __construct(
public bool $dumpEnumIsMethods = false,
public ?object $introspectionClient = null,
public array $inlineProcessingDirectories = [],
public array $twigProcessingDirectories = [],
public bool $formatOperationFiles = false,
) {}

Expand Down Expand Up @@ -187,6 +189,11 @@ public function withInlineProcessingDirectory(string $directory, string ...$dire
return $this->with('inlineProcessingDirectories', [...$this->inlineProcessingDirectories, $directory, ...$directories]);
}

public function withTwigProcessingDirectory(string $directory, string ...$directories) : self
{
return $this->with('twigProcessingDirectories', [...$this->twigProcessingDirectories, $directory, ...$directories]);
}

/**
* Replace with clone with when in PHP 8.5
*/
Expand Down
38 changes: 38 additions & 0 deletions src/Planner.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

namespace Ruudk\GraphQLCodeGenerator;

use Composer\InstalledVersions;
use Exception;
use GraphQL\Error\InvariantViolation;
use GraphQL\Language\AST\DocumentNode;
use GraphQL\Language\AST\FragmentDefinitionNode;
use GraphQL\Language\AST\NodeList;
use GraphQL\Language\AST\OperationDefinitionNode;
use GraphQL\Language\Parser;
Expand Down Expand Up @@ -76,6 +78,8 @@
use Ruudk\GraphQLCodeGenerator\Planner\SelectionSetPlanner;
use Ruudk\GraphQLCodeGenerator\Planner\Source\FileSource;
use Ruudk\GraphQLCodeGenerator\Planner\Source\InlineSource;
use Ruudk\GraphQLCodeGenerator\Twig\GraphQLExtension;
use Ruudk\GraphQLCodeGenerator\Twig\GraphQLNodeFinder;
use Ruudk\GraphQLCodeGenerator\Type\TypeHelper;
use Ruudk\GraphQLCodeGenerator\Validator\IndexByValidator;
use Ruudk\GraphQLCodeGenerator\Visitor\DefinedFragmentsVisitor;
Expand All @@ -89,6 +93,8 @@
use Symfony\Component\TypeInfo\Type as SymfonyType;
use Symfony\Component\TypeInfo\Type\BackedEnumType;
use Symfony\Component\TypeInfo\TypeIdentifier;
use Twig\Environment;
use Twig\Loader\ArrayLoader;
use Webmozart\Assert\Assert;
use Webmozart\Assert\InvalidArgumentException;

Expand Down Expand Up @@ -287,6 +293,8 @@ public function plan() : PlannerResult

Assert::notNull($definition->name, 'Expected operation to have a name');

$usedTypesCollector->analyze($document);

$operationType = $definition->operation;
$operationName = $definition->name->value;

Expand All @@ -312,6 +320,36 @@ public function plan() : PlannerResult
}
}

if ($this->config->twigProcessingDirectories !== []) {
Assert::true(InstalledVersions::isInstalled('twig/twig'), 'Twig is required to use twigProcessingDirectories');

$twig = new Environment(new ArrayLoader([]));
$twig->addExtension(new GraphQLExtension());
$nodeFinder = new GraphQLNodeFinder($twig);

$finder = Finder::create()
->files()
->in($this->config->inlineProcessingDirectories)
->name('*.twig')
->contains('{% graphql %}');

foreach ($finder as $file) {
foreach ($nodeFinder->find($file->getContents()) as $operation) {
$document = Parser::parse($operation);

Assert::minCount($document->definitions, 1);
Assert::allIsInstanceOf($document->definitions, FragmentDefinitionNode::class, 'Only fragment definitions are supported in Twig templates');

$usedTypesCollector->analyze($document);

$operations[$file->getPathname()][] = DocumentNodeWithSource::create(
$document,
new FileSource(Path::makeRelative($file->getPathname(), $this->config->projectDir)),
);
}
}
}

$usedTypes = $usedTypesCollector->usedTypes;

// Initialize enum and input types based on usage
Expand Down
19 changes: 19 additions & 0 deletions src/Twig/GraphQLExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace Ruudk\GraphQLCodeGenerator\Twig;

use Override;
use Twig\Extension\AbstractExtension;

final class GraphQLExtension extends AbstractExtension
{
#[Override]
public function getTokenParsers() : array
{
return [
new GraphQLTokenParser(),
];
}
}
Loading