Ошибка getDirectives при печати удаленной схемы с помощью graphql-tools - PullRequest
0 голосов
/ 05 апреля 2019

У меня есть два сервера узлов, оба обслуживающие graphql через express-graphql Я хотел бы, чтобы мой первый сервер соединял свою схему со схемой второго сервера.

Я следовал этим инструкциям по адресу: https://www.apollographql.com/docs/graphql-tools/remote-schemas

, поскольку я использую GraphQL-инструменты.

Я могу получить схему со своего сервера второго узла, но как только я пытаюсь распечатать ее (просто console.log), я получаю эту ошибку:

Uncaught exception TypeError: schema.getDirectives is not a function
    at printFilteredSchema (/Users/cchabert/git-repo/client-configuration-api/node_modules/graphql/utilities/schemaPrinter.js:61:27)
    at Object.printSchema (/Users/cchabert/git-repo/client-configuration-api/node_modules/graphql/utilities/schemaPrinter.js:47:10)
    at makeRemoteExecutableSchema (/Users/cchabert/git-repo/client-configuration-api/node_modules/graphql-tools/dist/stitching/makeRemoteExecutableSchema.js:60:30)
    at schema (/Users/cchabert/git-repo/client-configuration-api/app/api/schema.js:68:24)
    at module.exports (/Users/cchabert/git-repo/client-configuration-api/app/routes.js:102:13)
    at Object.<anonymous> (/Users/cchabert/git-repo/client-configuration-api/app/index.js:15:20)
    at Module._compile (internal/modules/cjs/loader.js:799:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:810:10)
    at Module.load (internal/modules/cjs/loader.js:666:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:606:12)
    at Function.Module._load (internal/modules/cjs/loader.js:598:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:862:12)
    at internal/main/run_main_module.js:21:11

, что приводит к смерти сервера, но я также могу как-то увидеть схему:

received schema:  {"_queryType":"Query","_mutationType":"Mutation",
"_subscriptionType":null,"_directives":["@skip","@include","@deprecated"],
"_typeMap":{"Query":"Query","String":"String","Client":"Client",
"ID":"ID","DateTime":"DateTime",[...]}

Я вижу поле _directives в определении удаленной схемы, но в документах не очень ясно, как с этим бороться.

Я также просмотрел проблемы с github репо graphql-tools, но ничего не смог найти.

Вот фрагмент кода:

const {
  addMockFunctionsToSchema,
  makeExecutableSchema,
  makeRemoteExecutableSchema,
  introspectSchema,
  mergeSchemas
} = require('graphql-tools')
const _ = require('lodash)
const { createHttpLink } = require('apollo-link-http')
const fetch = require('node-fetch')

[..]
const customFetch = (uri, options = {}) => {
  const httpOptions = _.merge(options, {
    headers: {
      'Content-type': 'application/json'
    }
  })
  return fetch(uri, httpOptions)
}

function schema() {
  const Query = `
    type Query {
      _empty: String
    }
    type Mutation {
      _empty: String
    }
  `
  const resolvers = {}

  const mocks = {}

  const localSchema = makeExecutableSchema({
    typeDefs: [Query, [...]],
    resolvers: [resolvers, [...]]
  }) // by itself this schema works without any issues

  const mergedMocks = _.merge(mocks, [...])

  addMockFunctionsToSchema({
    schema: localSchema,
    mocks: mergedMocks,
    preserveResolvers: true
  })

  const infoApiLink = createHttpLink({ uri, fetch: customFetch })

  const remoteSchema = makeRemoteExecutableSchema({
    schema: introspectSchema(infoApiLink).then(remoteSchema => {
      console.log('received schema: ', JSON.stringify(remoteSchema))
      return remoteSchema
    }),
    link: infoApiLink
  })

  return mergeSchemas({ schemas: [localSchema, remoteSchema] })
}

module.exports = {
  schema
}

Я также хотел бы сделать эту работу, используя только Обещания (без асинхронного / ожидающего), как указано в https://github.com/apollographql/graphql-tools/blob/master/docs/source/remote-schemas.md#--introspectschemafetcher-context

Любые предложения приветствуются.

1 Ответ

1 голос
/ 05 апреля 2019

makeRemoteExecutableSchema должен быть передан экземпляр GraphQLSchema, но вы этого не делаете - вы передаете ему Обещание, которое преобразуется в GraphQLSchema, что не сработает. Когда вы вызываете introspectSchema, он должен сделать самоанализ, который выполняется асинхронно. Он возвращает Обещание, которое разрешается в результирующий объект GraphQLSchema. Нам нужно использовать await или then, чтобы получить это значение, а затем мы можем использовать его по мере необходимости.

Неоправданно грязный путь без асинхронности / ожидания:

function schema () {
  // ... rest of your code
  return introspectSchema(infoApiLink).then(schema => {
    const remoteSchema = makeRemoteExecutableSchema({ schema, link: infoApiLink })
    return mergeSchemas({ schemas: [localSchema, remoteSchema] })
  })
}

Или используя async / await:

async function schema () {
  // ... rest of your code
  const schema = await introspectSchema(infoApiLink)
  const remoteSchema = makeRemoteExecutableSchema({ schema, link: infoApiLink })
  return mergeSchemas({ schemas: [localSchema, remoteSchema] })

}

В любом случае, имейте в виду, что, вызывая функцию schema, вы будете возвращать Promise, который разрешит значение, возвращаемое mergeSchemas. Поэтому, прежде чем вы могли бы импортировать функцию, вызывать ее и напрямую использовать результат, вам снова придется использовать либо then, либо await, чтобы получить значение, которое Обещание разрешает в первую очередь:

import { schema } from './some-module'

schema()
  .then(schema => {
    const server = new ApolloServer({ schema })
    server.listen()
  })
  .catch(error => {
    // handle the Promise rejecting
  })
...