GithubHelp home page GithubHelp logo

skillshare / apollo-federation-php Goto Github PK

View Code? Open in Web Editor NEW
33.0 40.0 7.0 280 KB

๐ŸŒ A PHP implementation of the Apollo Federation specification

License: MIT License

PHP 100.00%
php graphql apollo-federation graphql-php pod-crops

apollo-federation-php's Introduction

Apollo Federation PHP

This package provides classes and utilities for webonyx/graphql-php for creating federated GraphQL subgraphs in PHP to be consumed by the Apollo Gateway.

โš ๏ธ IMPORTANT: This package is still in active development and it might introduce breaking changes.

Usage

Via composer:

composer require skillshare/apollo-federation-php

Entities

An entity is an object type that you define canonically in one subgraph and can then reference and extend in other subgraphs. It can be defined via the EntityObjectType which takes the same configuration as the default ObjectType plus a keyFields and __resolveReference properties.

use Apollo\Federation\Types\EntityObjectType;

$userType = new EntityObjectType([
    'name' => 'User',
    'keyFields' => ['id', 'email'],
    'fields' => [
        'id' => ['type' => Type::int()],
        'email' => ['type' => Type::string()],
        'firstName' => ['type' => Type::string()],
        'lastName' => ['type' => Type::string()]
    ],
    '__resolveReference' => static function ($ref) {
        // .. fetch from a data source.
    }
]);
  • keyFields โ€” defines the entity's primary key, which consists of one or more of the type's. An entity's key cannot include fields that return a union or interface.

  • __resolveReference โ€” resolves the representation of the entity from the provided reference. Subgraphs use representations to reference entities from other subgraphs. A representation requires only an explicit __typename definition and values for the entity's primary key fields.

For more detail on entities, see the official docs.

Entity references

A subgraph can reference entities from another subgraph by defining a stub including just enough information to know how to interact with the referenced entity. Entity references are created via the EntityRefObjectType which takes the same configuration as the base EntityObjectType.

use Apollo\Federation\Types\EntityRefObjectType;

$userType = new EntityRefObjectType([
    'name' => 'User',
    'keyFields' => ['id', 'email'],
    'fields' => [
        'id' => ['type' => Type::int()],
        'email' => ['type' => Type::string()]
    ]
]);

For more detail on entity references, see the official docs.

Extending

A subgraph can add fields to an entity that's defined in another subgraph. This is called extending the entity. When a subgraph extends an entity, the entity's originating subgraph is not aware of the added fields. Only the extending subgraph (along with the gateway) knows about these fields.

use Apollo\Federation\Types\EntityRefObjectType;

$userType = new EntityRefObjectType([
    'name' => 'User',
    'keyFields' => ['id', 'email'],
    'fields' => [
        'id' => [
            'type' => Type::int(),
            'isExternal' => true
        ],
        'email' => [
            'type' => Type::string(),
            'isExternal' => true
        ]
    ]
]);

The subgraph can extend using the following configuration properties:

  • isExternal โ€” marks a field as owned by another service. This allows service A to use fields from service B while also knowing at runtime the types of that field.

  • provides โ€” used to annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway.

  • requires โ€” used to annotate the required input fieldset from a base type for a resolver. It is used to develop a query plan where the required fields may not be needed by the client, but the service may need additional information from other services.

Federated schema

The FederatedSchema class extends from the base GraphQL\Schema class and augments a schema configuration using entity types and federated field annotations with Apollo Federation metadata. See the docs for more info.

use GraphQL\GraphQL;
use Apollo\Federation\FederatedSchema;


$schema = new FederatedSchema($config);
$query = 'query GetServiceSDL { _service { sdl } }';

$result = GraphQL::executeQuery($schema, $query);

Config

The config parameter for the FederatedSchema object is entirely compatible with the Schema config argument. On top of this, we support the following optional parameters:

  1. entityTypes - the entity types (which extend EntityObjectType) which will form the _Entity type on the federated schema. If not provided, the Schema will scan the Query type tree for all types extending EntityObjectType.

Disclaimer

Documentation in this project include content quoted directly from the Apollo official documentation to reduce redundancy.

apollo-federation-php's People

Contributors

emfrouin avatar jeffreybaird avatar jmauerhan avatar jpasquers avatar ldiego08 avatar maccath avatar tarekul avatar xiian avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

apollo-federation-php's Issues

Different Root Query name than 'Query' breaks federation sdl

Regarding the following line we experienced some trouble because the root of our subgraph is called RootQuery and not just Query. While this in general is no problem it is lacking some documentation. It took us quite some hours and the help of @margnusnordlander (issue) to figure this out.

Maybe this convention should be mentioned in the docs or could be dynamically adjusted to the defined query name.

if ($type->name === 'Query') {

Entities subscription

Hi,

I'm having the following issue with the library in this part of the code:

*/
private function extractEntityTypes(array $config): array
{
$resolvedTypes = TypeInfo::extractTypes($config['query']);
$entityTypes = [];
foreach ($resolvedTypes as $type) {
if ($type instanceof EntityObjectType) {
$entityTypes[$type->name] = $type;
}
}
return $entityTypes;

The issue is that the library is unable to subscribe entities that aren't returned by a query.

Thank you!

Adding a field with args to an EntityRefObjectType

Hi I have a product entity

new EntityRefObjectType([
                'name' => 'Product',
                'keyFields' => ['id'],
                'fields' => [
                    'id' => fn() => [
                        'description' => 'The ID of the Product.',
                        'type' => Type::nonNull(Type::int()),
                    ],
                    'accessorySlot' => fn() => [
                        'description' =>
                            'Accessory alternatives that share a product type and or fiter set and or classification',
                        'type' => $this->createConfiguratorSlotType(),
                        'resolve' => $this->productAccessorySlotResolver,
                        'args' => [ 'criteria' => [
            'name' => 'AccessorySlotCriteria',
            'description' => 'The criteria an accessory slot should satisfy.',
            'keyFields' => ['productTypeId limit classificationId filterSetId'],
            'fields' => [
                'productTypeId' => fn() => [
                    'description' => "The accessory's product type.",
                    'type' => Type::nonNull(Type::int()),
                ],
            ],
        ] ]
                    ]
                ]
            ]);

And I this field (accessorySlot) Im contributing requires extra args namely productTypeId to be resolved. I used this configuration, but it seems that the args from the accessorySlot property are not picked up in the GraphQL schema
image

Is this intended behavior or is it simply not build yet? If the latter can you point me in the right direction to contribute this feature?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.