ardatan / graphql-tools

:wrench: Utility library for GraphQL to build, stitch and mock GraphQL schemas in the SDL-first approach
https://www.graphql-tools.com
MIT License
5.35k stars 815 forks source link

Help for remote schema #645

Closed Ouradze closed 6 years ago

Ouradze commented 6 years ago

Hello,

I am trying my hand with schema stitching. Basically, I used apollo-tutorial-kit repository to initiate the project. Then I went on to add a remote schema which I want to merge.

Here is my current schema.js file:

import {
  addMockFunctionsToSchema,
  introspectSchema,
  makeExecutableSchema,
  makeRemoteExecutableSchema,
  mergeSchemas,
} from 'graphql-tools';
import mocks from './mocks';

import { HttpLink } from 'apollo-link-http';
import fetch from 'node-fetch';

async function makeMergedSchema(){
  // local schema
  const typeDefs = `
  type Query {
    testString: String
  }
  `;
  const localSchema = makeExecutableSchema({ typeDefs });

  addMockFunctionsToSchema({ localSchema, mocks });

  // github schema
  const githubLink = new HttpLink({
    uri: 'http://api.githunt.com/graphql',
    //uri: 'http://127.0.0.1:7004/graphql/',
    fetch,
  });

  const githubSchema = makeRemoteExecutableSchema({
    schema: await introspectSchema(githubLink),
    link: githubLink,
  });

  // apollo lunchpad schema
  const apolloHubLink = new HttpLink({
    uri: 'https://q5kq9z15p.lp.gql.zone/graphql',
    fetch,
  });

  const apolloHubSchema = makeRemoteExecutableSchema({
    schema: await introspectSchema(apolloHubLink),
    link: apolloHubLink,
  });

  // schemas merging
  const mergeSchema = mergeSchemas({
    schemas: [localSchema, githubSchema, apolloHubSchema]
  });

  return mergeSchema;
}

export const schema = makeMergedSchema();

And here is the server.js

import express from 'express';
import { graphqlExpress, graphiqlExpress } from 'apollo-server-express';
import bodyParser from 'body-parser';
import schema from './data/schema';

const GRAPHQL_PORT = 3000;

(async () => {
  const resolvedSchema = await schema;

  const graphQLServer = express();

  graphQLServer.use('/graphql', bodyParser.json(), graphqlExpress({ schema: resolvedSchema }));
  graphQLServer.use('/graphiql', graphiqlExpress({ endpointURL: '/graphql' }));

  graphQLServer.listen(GRAPHQL_PORT, () =>
    console.log(
      `GraphiQL is now running on http://localhost:${GRAPHQL_PORT}/graphiql`
    )
  );
})();

At the moment, on start up the server doesn't catch any error but when I open GraphiQL, I encouter an error which states that no schema is defined.

Any help would be appriciated, if I manage to make it work, I would gladly edit the apollo page about it to make it a bit clearer on the subject.

Thanks in advance

NicolaiSchmid commented 6 years ago

Hey, how did you resolve your issue?

Ouradze commented 6 years ago

I resolved it by adding a try catch around the remote schema creation in the server. It seems that without it node was not resolving the promise properly.


// schema.js
import {
  addMockFunctionsToSchema,
  introspectSchema,
  makeExecutableSchema,
  makeRemoteExecutableSchema,
  mergeSchemas,
} from 'graphql-tools';
import mocks from './mocks';

import { HttpLink, execute, makePromise } from 'apollo-link';
import { createApolloFetch } from 'apollo-fetch';

export async function makeMergedSchema(){
  // github schema
  const githubFetcher = createApolloFetch({ uri: 'http://api.githunt.com/graphql' });

  const githubSchema = makeRemoteExecutableSchema({
    schema: await introspectSchema(githubFetcher),
    fetcher: githubFetcher,
  });

  // apollo lunchpad schema
  const apolloHubFetcher = createApolloFetch({ uri: 'https://q5kq9z15p.lp.gql.zone/graphql' });

  const apolloHubSchema = makeRemoteExecutableSchema({
    schema: await introspectSchema(apolloHubFetcher),
    fetcher: apolloHubFetcher,
  });

  // schemas merging
  const mergedSchema = mergeSchemas({
    schemas: [githubSchema, apolloHubSchema],
  });

  return mergedSchema;
}

// server.js
import express from 'express';
import { graphqlExpress, graphiqlExpress } from 'apollo-server-express';
import bodyParser from 'body-parser';
import { makeMergedSchema } from './data/schema';

async function run(){
  const GRAPHQL_PORT = 3000;

  const graphQLServer = express();

  try{
    graphQLServer.use('/graphql', bodyParser.json(), graphqlExpress({ schema: await makeMergedSchema() }));
  } catch(e){
    console.log(e);
  }
  graphQLServer.use('/graphiql', graphiqlExpress({ endpointURL: '/graphql' }));

  graphQLServer.listen(GRAPHQL_PORT, () =>
    console.log(
      `GraphiQL is now running on http://localhost:${GRAPHQL_PORT}/graphiql`
    )
  );
}

try {
    run();
} catch (e) {
    console.log(e, e.message, e.stack);
}
NicolaiSchmid commented 6 years ago

Okay, thank you!