Skip to content

Commit

Permalink
feat (FEDERATION) nuwave#911: Initial idea of how we could implement …
Browse files Browse the repository at this point in the history
…the federation support into lighthouse
  • Loading branch information
renepardon committed Nov 21, 2019
1 parent d4ecc18 commit 2d574a9
Show file tree
Hide file tree
Showing 15 changed files with 692 additions and 0 deletions.
14 changes: 14 additions & 0 deletions config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,20 @@

'transactional_mutations' => true,

/*
|--------------------------------------------------------------------------
| Apollo federation support
|--------------------------------------------------------------------------
|
| Possible types are "service" and "gateway". Defaults to
| "service" because you may implement more services than gateways ;)
|
*/

'federation' => [
'type' => 'service',
],

/*
|--------------------------------------------------------------------------
| GraphQL Subscriptions
Expand Down
10 changes: 10 additions & 0 deletions src/Exceptions/FederationException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Nuwave\Lighthouse\Exceptions;

use Exception;

class FederationException extends Exception
{
//
}
40 changes: 40 additions & 0 deletions src/Federation/Directives/ExtendsDirective.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace Nuwave\Lighthouse\Federation\Directives;

use Nuwave\Lighthouse\Schema\Directives\BaseDirective;

class ExtendsDirective extends BaseDirective
{
/**
* Directive name.
*
* @return string
*/
public function name(): string
{
return 'extends';
}

/**
* @return string
* @see https://www.apollographql.com/docs/apollo-server/federation/federation-spec/#schema-modifications-glossary
*/
public static function definition(): string
{
return /* @lang GraphQL */
<<<'SDL'
"""
Some libraries such as graphql-java don't have native support for type extensions in their printer. Apollo Federation
supports using an @extends directive in place of extend type to annotate type references:
type User @key(fields: "id") @extends {
instead of:
extend type User @key(fields: "id") {
"""
directive @extends on OBJECT | INTERFACE
SDL;
}
}
35 changes: 35 additions & 0 deletions src/Federation/Directives/ExternalDirective.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace Nuwave\Lighthouse\Federation\Directives;

use Nuwave\Lighthouse\Schema\Directives\BaseDirective;

class ExternalDirective extends BaseDirective
{
/**
* Name of the directive.
*
* @return string
*/
public function name(): string
{
return 'external';
}

/**
* @return string
* @see https://www.apollographql.com/docs/apollo-server/federation/federation-spec/#schema-modifications-glossary
*/
public static function definition(): string
{
return /* @lang GraphQL */
<<<'SDL'
"""
Individual federated services should be runnable without having the entire graph present. Fields marked with @external
are declarations of fields that are defined in another service. All fields referred to in @key, @requires, and @provides
directives need to have corresponding @external fields in the same service.
"""
directive @external on FIELD_DEFINITION
SDL;
}
}
41 changes: 41 additions & 0 deletions src/Federation/Directives/KeyDirective.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace Nuwave\Lighthouse\Federation\Directives;

use Nuwave\Lighthouse\Schema\Directives\BaseDirective;

class KeyDirective extends BaseDirective
{
/**
* Directive name.
*
* @return string
*/
public function name(): string
{
return 'key';
}

/**
* @return string
* @see https://www.apollographql.com/docs/apollo-server/federation/federation-spec/#schema-modifications-glossary
*/
public static function definition(): string
{
return /* @lang GraphQL */
<<<'SDL'
"""
The @key directive is used to indicate a combination of fields that can be used to uniquely identify and fetch an object
or interface. Multiple keys can be defined on a single object type:
type User @key(fields: "id") @key(fields: "another_field") @extends {
"""
directive @key(
"""
Fields that can be used to uniquely identify and fetch an object or interface
"""
fields: _FieldSet!
) on OBJECT | INTERFACE
SDL;
}
}
49 changes: 49 additions & 0 deletions src/Federation/Directives/ProvidesDirective.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace Nuwave\Lighthouse\Federation\Directives;

use Nuwave\Lighthouse\Schema\Directives\BaseDirective;

class ProvidesDirective extends BaseDirective
{
/**
* Name of the directive.
*
* @return string
*/
public function name(): string
{
return 'provides';
}

/**
* @return string
* @see https://www.apollographql.com/docs/apollo-server/federation/federation-spec/#schema-modifications-glossary
*/
public static function definition(): string
{
return /* @lang GraphQL */
<<<'SDL'
"""
The @provides directive is used to annotate the expected returned fieldset from a field on a base type that is
guaranteed to be selectable by the gateway. Given the following example:
type Review @key(fields: "id") {
product: Product @provides(fields: "name")
}
extend type Product @key(fields: "upc") {
upc: String @external
name: String @external
}
"""
directive @provides(
"""
Annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the
gateway.
"""
fields: _FieldSet!
) on FIELD_DEFINITION
SDL;
}
}
47 changes: 47 additions & 0 deletions src/Federation/Directives/RequiresDirective.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace Nuwave\Lighthouse\Federation\Directives;

use Nuwave\Lighthouse\Schema\Directives\BaseDirective;

class RequiresDirective extends BaseDirective
{
/**
* Name of the directive.
*
* @return string
*/
public function name(): string
{
return 'requires';
}

/**
* @return string
* @see https://www.apollographql.com/docs/apollo-server/federation/federation-spec/#schema-modifications-glossary
*/
public static function definition(): string
{
return /* @lang GraphQL */
<<<'SDL'
"""
The @requires directive is 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. For example:
extend type User @key(fields: "id") {
id: ID! @external
email: String @external
reviews: [Review] @requires(fields: "email")
}
"""
directive @requires(
"""
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.
"""
fields: _FieldSet!
) on FIELD_DEFINITION
SDL;
}
}
Loading

0 comments on commit 2d574a9

Please sign in to comment.