Skip to content

v0.9.0-federation

Pre-release
Pre-release
Compare
Choose a tag to compare
@dariuszkuc dariuszkuc released this 19 Oct 19:16
· 1 commit to federation since this release

DO NOT USE: Use v0.9.1-federation instead


This release adds Apollo Federation support to the graphql-go/graphql library.

Usage

Apollo Federation relies on the usage of directives to specify relationships between various subgraphs. All federated directives are provided in the federation package.

Once our GraphQL schema is defined, then we can then generate Federation compatible schema using federation.NewFederatedSchema(config FederatedSchemaConfig) function.
In order to be able to resolve the federated Product type, we need to provide EntityTypeResolver to resolve _Entity union type and a EntitiesFieldResolver to resolve
_entities query.

type Product struct {
	ID          string `json:"id"`
	Description string `json:"description"`
}

productType := graphql.NewObject(graphql.ObjectConfig{
    Name: "Product",
    Fields: graphql.Fields{
        "id": &graphql.Field{
            Name: "id",
            Type: graphql.NewNonNull(graphql.ID),
        },
        "description": &graphql.Field{
            Name: "description",
            Type: graphql.String,
        },
    },
    AppliedDirectives: []*graphql.AppliedDirective{
        federation.KeyAppliedDirective("id", true),
    },
})

schema, err := federation.NewFederatedSchema(federation.FederatedSchemaConfig{
    EntitiesFieldResolver: func(p graphql.ResolveParams) (interface{}, error) {
        representations, ok := p.Args["representations"].([]interface{})
        results := make([]interface{}, 0)
        if ok {
            for _, representation := range representations {
                raw, isAny := representation.(map[string]interface{})
                if isAny {
                    typeName, _ := raw["__typename"].(string)
                    if typeName == "Product" {
                        id, _ := raw["id"].(string)
                        product := &Product{
                            ID:          id,
                            Description: "Federated Description",
                        }
                        results = append(results, product)
                    }
                }
            }
        }
        return results, nil
    },
    EntityTypeResolver: func(p graphql.ResolveTypeParams) *graphql.Object {
        if _, ok := p.Value.(*Product); ok {
            return productType
        }
        return nil
    },
    SchemaConfig: schemaConfig = graphql.SchemaConfig{
        // root query can be omitted when creating federated schema
        // Query: graphql.NewObject(graphql.ObjectConfig{...}) // specify your query object
        Types: []graphql.Type{
            // if entities are not resolvable by queries, they have to be explicitly specified here
            productType,
        },
    },
})

Above code will generate the following GraphQL schema (directive definitions and scalars are omitted for brevity):

schema @link(url: "https://specs.apollo.dev/federation/v2.1", import: ["composeDirective", "external", "inaccessible", "key", "override", "provides", "requires", "shareable", "tag", "FieldSet"]) {
  query: Query
}

type Product @key(fields: "id", resolvable: true) {
  description: String
  id: ID!
}

type Query {
  _entities(representations: [_Any!]!): [_Entity]
  _service: _Service
}

type _Service {
  sdl: String!
}

union _Entity = Product