t3n/graphql-apollofederation

There is no license information available for the latest version (0.2.0) of this package.

Apollo Federation spec implementation for t3n.GraphQL

Installs: 4 138

Dependents: 0

Suggesters: 0

Security: 0

Stars: 3

Watchers: 8

Forks: 0

Open Issues: 0

Type:neos-package

0.2.0 2019-12-23 06:53 UTC

This package is auto-updated.

Last update: 2024-10-23 17:20:57 UTC


README

Sidecar package for t3n.GraphQL to implement the Apollo Federation specification within your GraphQL schema.

Simply install it via composer:

composer require "t3n/graphql-apollofederation"

Note: This package is still under progress and might change in it's implementation

About Apollo Federation

Apollo Federation is an architecture for composing multiple GraphQL services into a single graph. This package provides all functionality to implement the specification to your endpoints so you can use your service with Apollo's tools.

Adjustments

In order to implement the specification you need do add some small adjustments to your existing schema. You can see an example implementation here.

Add Federation Spec schema

  1. Add the graphql specification to your schema:
t3n:
  GraphQL:
    endpoints:
      'your-endpoint':
        schemas:
          federationSpec: # make sure to start this key with "federation"
            typeDefs: 'resource://t3n.GraphQL.ApolloFederation/Private/GraphQL/federation-schema.graphql'
              resolvers:
                _Entity: 't3n\GraphQL\ApolloFederation\Resolver\EntityResolver'
                _Service: 't3n\GraphQL\ApolloFederation\Resolver\ServiceResolver'
  1. Add the ServiceQueryTrait to your Query-Resolver
<?php

declare(strict_types=1);

namespace Some\Vendor\Namespace\Resolver;

use t3n\GraphQL\ApolloFederation\Resolver\ServiceQueryTrait;
use t3n\GraphQL\ResolverInterface;

class QueryResolver implements ResolverInterface
{
    use ServiceQueryTrait;

    // [...]
}
  1. Add a new Entity union to your schema:

You need to make each of your entities part of the _Entity union. In order to do so add a new schema file to your Endpoint that defines the union:

# Resources/Private/GraphQL/federation.graphql
union _Entity = User | Product | _allOfYourEntities_
t3n:
  GraphQL:
    endpoints:
      'your-endpoint':
        schemas:
          federationEntity: # make sure to start this key with "federation"
            typeDefs: 'resource://Your.Package/Private/GraphQL/federation.graphql'
  1. Add the EntitiesQueryTrait to your query resolver

This step is optional if do not have any entities.

The Federation specification needs a new query _entities. Add the trait to all of your QueryResolver:

<?php

declare(strict_types=1);

namespace Some\Vendor\Namespace\Resolver;

use t3n\GraphQL\ApolloFederation\Resolver\EntitiesQueryTrait;
use t3n\GraphQL\ResolverInterface;

class QueryResolver implements ResolverInterface
{
    use EntitiesQueryTrait;

    // [...]
}

Also add the _entities to your query type:

type Query @extends {
  _entities(representations: [_Any!]!): [_Entity]!
}
  1. Implement EntityResolverInterface

Once the _entities query is called the Entity union will be resolved. The Apollo Gateway server will send queries like

query($representations: [_Any!]!) {
  _entities(representations: $representations) {
    ... on User {
      name
    }
  }
}

Depending on the representation input a concrete resolver will be instantiated. All of your Resolvers that resolves entities must therefore implement the EntityResolverInterface:

    # Return the typename of your Entity
    public function __resolveType(): string;

    /**
     * This method actually has to resolve your object/array that represents your entity
     *
     * @param array $variables those variables are passed down via the representation array
     */
    public function __resolveEntity(array $variables);
  1. Implement GraphQLTypeAwareInterface if needed

All of your data that you actually resolve and return which is part of the _Entity union type must be aware of it's type name. If it's an object you must implement the GraphQLTypeAwareInterface. If your data is an array there must be a key __typename on the first level.