graphqlhasurafederationapollo-federation

Hasura GraphQL Endpoint behind Apollo Federated Gateway


Has anyone successfully placed a Hasura GraphQL endpoint, behind an Apollo Federated Gateway? I know Hasura wants to act as the point of federation but I would rather not do that...current thought is to create an apollo server with a remote schema to connect Hasura, and then but that beind the gateway...looking for any thoughts or guidance on whether this is possible?

I'm tempted to say it's not because I can't see anyone who has attempted it. I'm not sure if the Hasura endpoint will allow. "itself" to be federated in this way.

I've started the process but intially haven't been able to get an Express Apollo Server with a remote schemea to connect to the Hasura endpoint so a smaller question is whether or not that is even possible.

Cheers.


Solution

  • It is possible to mount Hasura over apollo-gateway [1] using a simple workaround. The fundamental requirement is to have a field called _service in your graphql schema [2]. The _service field is nothing but the Hasura schema in the Schema Definition Language (SDL) format.

    You can add this field to your query type using a Remote Schema [3]. Here is a sample remote schema:

    const { ApolloServer } = require('apollo-server');
    const gql = require('graphql-tag');
    const hasuraSchema = require('./schema.js');
    
    const typeDefs = gql`
    
      schema {
        query: query_root
      }
    
      type _Service {
        sdl: String
      }
    
      type query_root {
        _service: _Service!
      }
    
    `;
    
    const resolvers = {
        query_root: {
            _service: () =>  { return {sdl: hasuraSchema} },
        },
    };
    
    const schema = new ApolloServer({ typeDefs, resolvers });
    
    schema.listen({ port: process.env.PORT}).then(({ url }) => {
        console.log(`schema ready at ${url}`);
    });
    

    The key value here is const hasuraSchema which is the Hasura schema in the SDL format i.e.

    // schema.js
    
    const hasuraSchema = `
    
    # NOTE: does not have subscription field
    schema {
      query: query_root
      mutation: mutation_root
    }
    
    type articles {
      id: Int!
      title: String!
    }
    
    type query_root {
     ...
    }
    
    type mutation_root {
     ...
    }
    `
    
    module.exports = hasuraSchema;
    

    You can get the SDL of the Hasura schema automatically using many community tools including graphql-js [4] or graphqurl [5].

    A completely automated example is posted here: https://gist.github.com/tirumaraiselvan/65c6fa80542994ed6ad06fa87a443364

    NOTE: apollo-gateway doesn't currently support subscriptions [6] so you will need to remove the subscription field from the schema root in the generated SDL, otherwise it throws a weird error.

    1. This only allows serving Hasura via apollo-gateway and does not mean it enables federation capabilities.
    2. https://www.apollographql.com/docs/apollo-server/federation/federation-spec/#fetch-service-capabilities
    3. https://docs.hasura.io/1.0/graphql/manual/remote-schemas/index.html
    4. https://graphql.org/graphql-js/utilities/#printintrospectionschema
    5. https://github.com/hasura/graphqurl#export-schema
    6. https://github.com/apollographql/apollo-server/issues/2360#issuecomment-531849628