Как исправить циклическую зависимость с подключениями GraphQL Relay

Я выделил свое соединение с собственным файлом и могу использовать его в моем корневом запросе (он работал нормально, когда соединение было определено в типе), но при попытке использовать его, импортировав его в тип, для которого соединение предназначено, я просто вернуться:

Ошибка: тип поля PageEdge.node должен быть типом вывода, но получено: undefined

Я могу заставить соединения работать в моем QueryType, но не в PageType. Моя схема примерно такая.

QueryType {
  pages: [PageType]
}

PageType {
  _id: string
  pages: [PageType]
}

Вот ссылка на репозиторий проекта, где находится материал graphql (я просто нажал фиксацию с ошибкой, чтобы увидеть весь код): https://github.com/DaveyEdwards/myiworlds/tree/master/src/data

Я сделал преобразователи полей QueryType и PageType (решение, которое, кажется, решает большинство проблем людей), а также попытался сделать преобразование из интерфейсов:

interfaces: () => [nodeInterface]

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

UserType: {
  friends: [UserType]
}

My PageType:

import { nodeInterface } from '../nodeInterface';
import PageConnection from './connections/PageConnection';

const PageType = new ObjectType({
  name: 'Page',
  description: 'Everything you see can be placed inside a page.',
  fields: () => ({
    id: globalIdField('Page', page => page._id),
    _id: {
      type: new NonNull(ID),
      description: 'A unique id used to instantly locate this page inside the database',
    },
    pageEdge: {
      type: PageConnection,
      args: connectionArgs,
      resolve: async (page, { args }, { loaders }) => {
        if (page.pageEdge) {
          const pageEdge = await loaders.pageLoader.loadMany(page.pageEdge);
          const connection = connectionFromArray(pageEdge, args);
          return connection;
        }
      },
    },
  }),
  interfaces: () => [nodeInterface],
});

export default PageType;

Подключение к моей странице:

import { connectionDefinitions } from 'graphql-relay';

import PageType from '../PageType';

const { connectionType: PageConnection } = connectionDefinitions({
  name: 'Page',
  nodeType: PageType,
});

export default PageConnection;

Мой nodeInterface:

import { nodeDefinitions } from 'graphql-relay';
import { getNode, getNodeType } from './type-registry';

export const { nodeInterface, nodeField } = nodeDefinitions(getNode, getNodeType);

Мой реестр типов:

import { fromGlobalId } from 'graphql-relay';
require('babel-polyfill');

const types = {};

export const registerType = (model, type, lookupFn) => {
  types[type.name] = { model, type, lookupFn };
};

export const getNode = async (globalId) => {
  const { type: typeName, id } = fromGlobalId(globalId);
  console.log('getNode', globalId, typeName, id);

  if (types[typeName]) {
    const object1 = await types[typeName].lookupFn(id);
    const Class = types[typeName].model;
    // let result  = Object.create(types[typeName].model, object1);
    const result = new Class(object1);
    console.log('getNode result', result);
    return result;
  }
  return null;
};

export const getNodeType = (obj) => {
  const keys = Object.keys(types);
  let ret = null;
  keys.map((typeName) => {
    if (obj instanceof types[typeName].model) {
      ret = types[typeName].type;
    }
    return true;
  });
  return ret;
};

My QueryType, где работает импортированное соединение

import {
  GraphQLObjectType as ObjectType,
  GraphQLList as List,
  GraphQLString as StringType,
} from 'graphql';
import { connectionArgs, connectionFromArray, connectionDefinitions } from 'graphql-relay';
import { nodeField } from '../nodeInterface';
import PageType from './PageType';
import { getPageList } from '../queries/googleDatastore/pageQueries';
import PageConnection from './connections/PageConnection';

const QueryType = new ObjectType({
  name: 'QueryType',
  fields: () => ({
    pages: {
      type: PageConnection,
      args: connectionArgs,
      resolve: async (obj, args) => {
        const response = [];
        try {
          const pageEdge = await getPageList();
          const connection = connectionFromArray(pageEdge, args);
          return connection;
        } catch (err) {
          console.log('pages err', err);
        }
        return response;
      },
    },
    node: nodeField,
  }),
});

export default QueryType;

Ресурсы по этой проблеме, которые я пытаюсь найти:

Части этого репо - это то, что я реализовал, чтобы в первую очередь заставить работать соединения https://github.com/bondz/learn-graphql-relay/blob/47211fdec44ce4bb10f487bddfc7411e5690b894/src/types/projectConnection.js

Тип поля Edge.node должен быть типом вывода, но получил: undefined

https://github.com/graphql/graphql-js/issues/612

https://github.com/graphql/graphql-js/issues/373

https://gist.github.com/fbaiodias/77406c29ddf37fe46c3c


person Davey    schedule 13.06.2017    source источник


Ответы (1)


Просто удалите import PageConnection в верхней части PageType.js и используйте требование среды выполнения:

...
pageEdge: {
  type: require('./connections/PageConnection'),
  args: connectionArgs,
...
person yachaka    schedule 13.06.2017
comment
Это возвратило ошибку: тип поля Page.pageEdge должен быть типом вывода, но получено: [объект объекта]. - person Davey; 13.06.2017
comment
Также попытался поместить требование внутри функции и типа вызова: pages () и pages () [0/1], но по-прежнему ничего - person Davey; 14.06.2017
comment
Попробуйте require('./connections/PageConnection').default - person RomanHotsiy; 14.06.2017
comment
OMG, большое спасибо вам обоим !!!! Потратил более 3 дней на работу над этим и собирался вернуть соединение в тип. Мне также пришлось добавить еще одну вещь, потому что это давало мне свойство Cannot read "after" undefined. Я заменил {args} на {... args} в методе разрешения, и он исправил его. - person Davey; 14.06.2017
comment
Я собирался сойти с ума, прежде чем увидел это решение. Спас мой день, спасибо. - person C.Lee; 27.10.2017