x-graphql / schema-gateway
Merging all sub schemas into one and add relationships for them
Installs: 9 962
Dependents: 0
Suggesters: 0
Security: 0
Stars: 2
Watchers: 0
Forks: 0
Open Issues: 0
Requires
- php: >=8.2
- webonyx/graphql-php: ^15.9
- x-graphql/delegate-execution: ^0.9.0
- x-graphql/schema-cache: ^0.1.0
- x-graphql/utils: >=0.2.0
Requires (Dev)
- guzzlehttp/promises: ^2.0
- nyholm/psr7: ^1.8
- phpunit/phpunit: ^11.0
- symfony/cache: ^6.3 || ^7.0
- symfony/http-client: ^6.3 || ^7.0
- symplify/easy-coding-standard: ^12.1
- x-graphql/http-schema: ^0.8.0
README
Image source: GraphQL Stitching
Getting started
Install this package via Composer
composer require x-graphql/schema-gateway
Add http-schema
package for creating and executing GraphQL schema over HTTP:
composer require x-graphql/http-schema
Usages
<?php require __DIR__ . '/vendor/autoload.php'; use GraphQL\GraphQL; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\Type; use GraphQL\Utils\SchemaPrinter; use GraphQL\Type\Schema; use XGraphQL\HttpSchema\HttpDelegator; use XGraphQL\HttpSchema\HttpSchemaFactory; use XGraphQL\SchemaGateway\MandatorySelectionSetProviderInterface; use XGraphQL\SchemaGateway\Relation; use XGraphQL\SchemaGateway\RelationArgumentResolverInterface; use XGraphQL\SchemaGateway\RelationOperation; use XGraphQL\SchemaGateway\SchemaGatewayFactory; use XGraphQL\SchemaGateway\SubSchema; $localSchema = new Schema([ 'query' => new ObjectType([ 'name' => 'Query', 'fields' => [ 'person' => [ 'type' => new ObjectType([ 'name' => 'Person', 'fields' => [ 'name' => Type::nonNull(Type::string()), 'fromCountry' => Type::nonNull(Type::string()), ], ]), 'resolve' => fn() => ['name' => 'John Doe', 'fromCountry' => 'VN'] ], ], ]), ]); $localSubSchema = new SubSchema('local', $localSchema); $remoteSchema = HttpSchemaFactory::createFromIntrospectionQuery( new HttpDelegator('https://countries.trevorblades.com/'), ); $remoteSubSchema = new SubSchema('remote', $remoteSchema); $countryRelation = new Relation( 'Person', 'remoteCountry', RelationOperation::QUERY, 'country', new class implements RelationArgumentResolverInterface, MandatorySelectionSetProviderInterface { public function shouldKeep(string $argumentName, Relation $relation): bool { return false; } public function resolve(array $objectValue, array $currentArgs, Relation $relation): array { return ['code' => $objectValue['fromCountry']]; } public function getMandatorySelectionSet(Relation $relation): string { return '{ fromCountry }'; } } ); $schemaGateway = SchemaGatewayFactory::create([$localSubSchema, $remoteSubSchema], [$countryRelation]); $query = <<<'GQL' query { continents { name } person { name remoteCountry { name code } } } GQL; var_dump(SchemaPrinter::doPrint($schemaGateway)); var_dump(GraphQL::executeQuery($schemaGateway, $query)->toArray());
Rules when merging sub schemas:
- Top-level field names need to be unique across all merged schemas (case-sensitive match).
- Types with the exact same name and structure will be merged. But types with the same name but different structure will result in type conflicts.
Inspiration
This library has been inspired by many others related work including:
Thanks to all the great people who created these projects!
Credits
Created by Minh Vuong