Skip to content

Support to merge all GraphQL schemas into one and add relationships

License

Notifications You must be signed in to change notification settings

x-graphql/schema-gateway

Repository files navigation

Schema Gateway

unit tests codecov

Copyright GraphQL Stitching

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

About

Support to merge all GraphQL schemas into one and add relationships

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages