Apollo-server: How to use remote schema stitching in express or lambda in apollo server 2.0

Created on 6 Aug 2018  ยท  9Comments  ยท  Source: apollographql/apollo-server

I cannot remote schema in apollo server 2.0.
example

// index.js
import schema from './remoteSchema'
const server = new Apollo({
  ...
  schema: await makeMergedSchema(urls), <- This is impossible becuase of promise pattern
  ...
})
// remoteSchema.js
async function makeSchemaLink(uri: string) {
  const link = new HttpLink({
    uri,
    fetch,
  })
  return makeRemoteExecutableSchema({
    schema: await introspectSchema(link),
    link,
  })
}

export async function makeMergedSchema(URIs: string[]) {
  return mergeSchemas({
    schemas: await Promise.all(_.map(URIs, (uri) => {
      return makeSchemaLink(`${uri}`)
    })),
  })
}

I use Serverless framework with AWS Lambda. However, Express middleware and Lambda handler of Apollo-server-{} are no support remote schema that be made promise pattern. Just only support callback pattern. please help me. ๐Ÿ˜‚

Most helpful comment

@yoonhoGo here's a full working example of Apollo Server 2.0 running on a Lambda function and remotely stitching two schemas together.

"use strict";
const express = require("express"),
  app = express(),
  { ApolloServer } = require("apollo-server-express"),
  { introspectSchema,  makeRemoteExecutableSchema, mergeSchemas } = require("graphql-tools"),
  { createHttpLink } = require("apollo-link-http"),
  fetch = require("node-fetch");

const createSchema = async () => {
  const createCosmicJsServiceSchema = async () => {
    const cosmicJsServiceLink = createHttpLink({
      uri: `https://graphql.cosmicjs.com/v1`,
      fetch
    });

    const schema = await introspectSchema(cosmicJsServiceLink);

    return makeRemoteExecutableSchema({
      schema,
      link: cosmicJsServiceLink
    });
  };

  const createMovieServiceSchema = async () => {
    const movieServiceLink = createHttpLink({
      uri: `https://w5vwzkn9zz.lp.gql.zone/graphql`,
      fetch
    });

    const schema = await introspectSchema(movieServiceLink);

    return makeRemoteExecutableSchema({
      schema,
      link: movieServiceLink
    });
  };

  const movieServiceSchema = await createMovieServiceSchema();
  const cosmicJsServiceSchema = await createCosmicJsServiceSchema();

  return mergeSchemas({
    schemas: [movieServiceSchema, cosmicJsServiceSchema]
  });
};

createSchema().then(schema => {
  const server = new ApolloServer({ schema });
  server.applyMiddleware({ app });
  console.log(`๐Ÿš€ Server ready at ${server.graphqlPath}`);
});

app.get("/hello", (req, res) => res.send("Hello from Express!"));

module.exports = app;

lambda

You might wanna close this issue.

All 9 comments

Hi @yoonhoGo. Don't know is it still relevant for you... I'm not a Node.js developer but I'm using Apollo
GraphQL in our Java-based projects to do a remote schema stitching, and this is what we have:

// URLs of the remote GraphQL schemas
const urls = [...];

// Loading schemas and starting an ApolloServer
makeMergedSchema(urls).then(schema => {
new ApolloServer({
schema
}).listen().then(({url}) => {
console.log('Server ready at ${url}')
})
});

where makeMergedSchema is pretty much what you posted above.

@dsborets
Thank for your answer. Unfortunately, I have still this problem. I had many advance via complexed way. But I were stopped because of delegateToSchema(). This method is not working in remote stitching schema.

@yoonhoGo here's a full working example of Apollo Server 2.0 running on a Lambda function and remotely stitching two schemas together.

"use strict";
const express = require("express"),
  app = express(),
  { ApolloServer } = require("apollo-server-express"),
  { introspectSchema,  makeRemoteExecutableSchema, mergeSchemas } = require("graphql-tools"),
  { createHttpLink } = require("apollo-link-http"),
  fetch = require("node-fetch");

const createSchema = async () => {
  const createCosmicJsServiceSchema = async () => {
    const cosmicJsServiceLink = createHttpLink({
      uri: `https://graphql.cosmicjs.com/v1`,
      fetch
    });

    const schema = await introspectSchema(cosmicJsServiceLink);

    return makeRemoteExecutableSchema({
      schema,
      link: cosmicJsServiceLink
    });
  };

  const createMovieServiceSchema = async () => {
    const movieServiceLink = createHttpLink({
      uri: `https://w5vwzkn9zz.lp.gql.zone/graphql`,
      fetch
    });

    const schema = await introspectSchema(movieServiceLink);

    return makeRemoteExecutableSchema({
      schema,
      link: movieServiceLink
    });
  };

  const movieServiceSchema = await createMovieServiceSchema();
  const cosmicJsServiceSchema = await createCosmicJsServiceSchema();

  return mergeSchemas({
    schemas: [movieServiceSchema, cosmicJsServiceSchema]
  });
};

createSchema().then(schema => {
  const server = new ApolloServer({ schema });
  server.applyMiddleware({ app });
  console.log(`๐Ÿš€ Server ready at ${server.graphqlPath}`);
});

app.get("/hello", (req, res) => res.send("Hello from Express!"));

module.exports = app;

lambda

You might wanna close this issue.

Thx. I'm not test it yet. but I'm going to close this issue.

@hugocore would this work with stitching lambdas together? I have not been successful in my attempts to stitch them

Hum I don't see a reason not to โ€” they expose GraphQL endpoints that you should be able to stitch.

In my example, instead of

uri: `https://w5vwzkn9zz.lp.gql.zone/graphql`

It would be:

uri: `https://<your lambda url>.amazonaws.com/latest/graphql`

Keep in mind that this async code uses promises to connect and stitch the schema together. So it could take a few seconds to connect, introspect and stitch.

@yoonhoGo here's a full working example of Apollo Server 2.0 running on a Lambda function and remotely stitching two schemas together.

"use strict";
const express = require("express"),
  app = express(),
  { ApolloServer } = require("apollo-server-express"),
  { introspectSchema,  makeRemoteExecutableSchema, mergeSchemas } = require("graphql-tools"),
  { createHttpLink } = require("apollo-link-http"),
  fetch = require("node-fetch");

const createSchema = async () => {
  const createCosmicJsServiceSchema = async () => {
    const cosmicJsServiceLink = createHttpLink({
      uri: `https://graphql.cosmicjs.com/v1`,
      fetch
    });

    const schema = await introspectSchema(cosmicJsServiceLink);

    return makeRemoteExecutableSchema({
      schema,
      link: cosmicJsServiceLink
    });
  };

  const createMovieServiceSchema = async () => {
    const movieServiceLink = createHttpLink({
      uri: `https://w5vwzkn9zz.lp.gql.zone/graphql`,
      fetch
    });

    const schema = await introspectSchema(movieServiceLink);

    return makeRemoteExecutableSchema({
      schema,
      link: movieServiceLink
    });
  };

  const movieServiceSchema = await createMovieServiceSchema();
  const cosmicJsServiceSchema = await createCosmicJsServiceSchema();

  return mergeSchemas({
    schemas: [movieServiceSchema, cosmicJsServiceSchema]
  });
};

createSchema().then(schema => {
  const server = new ApolloServer({ schema });
  server.applyMiddleware({ app });
  console.log(`๐Ÿš€ Server ready at ${server.graphqlPath}`);
});

app.get("/hello", (req, res) => res.send("Hello from Express!"));

module.exports = app;

lambda

You might wanna close this issue.

That is not even a lambda function... you are exporting the express app, where is the handler?

That is not even a lambda function... you are exporting the express app, where is the handler?

@carlosdubus Oh... This issue is made very long ago. At that time, I was using aws-serverless-express.
So, exported app of that file was wrapt.
Does that answer your question? :)

@yoonhoGo Ahhh, that makes sense. My bad. I was not expecting a reply. Thanks!

Was this page helpful?
0 / 5 - 0 ratings