Модуляризация типов GraphQL в отдельные файлы - PullRequest
0 голосов
/ 14 сентября 2018

У меня есть реализация GraphQL с одним монолитным types / index.js файлом, который в настоящее время содержит два определения типов:

const graphql = require('graphql');
const Book = require('../../../models/book');
const Author = require('../../../models/author');

const {
  GraphQLObjectType,
  GraphQLString,
  GraphQLSchema,
  GraphQLID,
  GraphQLInt,
  GraphQLList,
  GraphQLNonNull,
} = graphql;

const BookType = new GraphQLObjectType({
  name: 'Book',
  fields: () => ({
    id: { type: GraphQLID },
    name: { type: GraphQLString },
    genre: { type: GraphQLString },
    author: {
      type: AuthorType,
      resolve: (parent, args) => {
        // code to get data from db
        return Author.findById(parent.authorId);
      },
    },
  }),
});

const AuthorType = new GraphQLObjectType({
  name: 'Author',
  fields: () => ({
    id: { type: GraphQLID },
    name: { type: GraphQLString },
    age: { type: GraphQLInt },
    books: {
      type: new GraphQLList(BookType),
      resolve: (parent, args) => {
        // code to get data from db
        return Book.find({authorId: parent.id});
      },
    },
  }),
});

module.exports = {BookType, AuthorType};

Это файл, который я импортирую в свою схему.Файл js, в котором он используется корневыми запросами и мутациями:

const {
  GraphQLObjectType,
  GraphQLString,
  GraphQLSchema,
  GraphQLID,
  GraphQLInt,
  GraphQLList,
  GraphQLNonNull,
} = require('graphql');
const Book = require('../../../models/book');
const Author = require('../../../models/author');
const {BookType, AuthorType} = require('../types');

// QUERIES
//------------------------------------------------------------------------------------------------------
const RootQuery = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {
    book: {
      type: BookType,
      args: { id: { type: GraphQLID } },
      resolve: (parent, args) => {
        // code to get data from db
        return Book.findById(args.id);
      },
    },
    author: {
      type: AuthorType,
      args: { id: { type: GraphQLID } },
      resolve: (parent, args) => {
        // code to get data from db
        return Author.findById(args.id);
      },
    },
    books: {
      type: new GraphQLList(BookType),
      resolve: (parent, args) => {
        // code to get data from db
        return Book.find({});
      },
    },
    authors: {
      type: new GraphQLList(AuthorType),
      resolve: (parent, args) => {
        // code to get data from db
        return Author.find({});
      }
    },
  },
});

// MUTATIONS
//------------------------------------------------------------------------------------------------------
const Mutation = new GraphQLObjectType({
  name: 'Mutation',
  fields: {
    addAuthor: {
      type: AuthorType,
      args: {
        name: { type: new GraphQLNonNull(GraphQLString) },
        age: { type: new GraphQLNonNull(GraphQLInt) }
      },
      resolve(parent, args) {
        let author = new Author({
          name: args.name,
          age: args.age
        });
        return author.save();
      }
    },
    addBook: {
      type: BookType,
      args: {
        name: { type: new GraphQLNonNull(GraphQLString) },
        genre: { type: new GraphQLNonNull(GraphQLString) },
        authorId: { type: new GraphQLNonNull(GraphQLID) },
      },
      resolve(parent, args) {
        let book = new Book({
          name: args.name,
          genre: args.genre,
          authorId: args.authorId,
        });
        return book.save();
      },
    },
  }
});

module.exports = new GraphQLSchema({
  query: RootQuery,
  mutation: Mutation,
});

Но по мере роста проекта я ожидаю десятки типов с множеством двусторонних отношений.Поэтому я хотел бы объединить все мои типы в отдельные файлы, такие как types / BookType.js , types / AuthorType.js и т. Д., А не отдельные типы /index.js, как у меня сейчас.Как лучше всего добиться этого, учитывая двусторонние отношения?

1 Ответ

0 голосов
/ 10 августа 2019

При разделении типов в отдельные файлы вам необходимо обрабатывать двусторонние отношения.В этом случае AuthorType требуется BookType и наоборот.Поэтому вам нужно импортировать AuthorType в типах / BookTypes.js и BookType в типах / AuthorType.js, но это приведет к классической проблеме циклической зависимости (перед экспортом AuthorType требуется BookType и наоборот), котораяраспространено в проектах узлов.Вы можете прочитать больше об этом здесь .Чтобы справиться с этим, сдвиньте требуемые вызовы в конце файла в обоих типах.Так что ваш код выглядит примерно так:

types / BookType.js

const graphql = require('graphql');
const Book = require('../../../models/book');
const Author = require('../../../models/author');

const {
  GraphQLObjectType,
  GraphQLString,
  GraphQLSchema,
  GraphQLID,
  GraphQLInt,
  GraphQLList,
  GraphQLNonNull,
} = graphql;

const BookType = new GraphQLObjectType({
  name: 'Book',
  fields: () => ({
    id: { type: GraphQLID },
    name: { type: GraphQLString },
    genre: { type: GraphQLString },
    author: {
      type: AuthorType,
      resolve: (parent, args) => {
        // code to get data from db
        return Author.findById(parent.authorId);
      },
    },
  }),
});

module.exports = BookType;

// This is here to prevent circular dependencies problem which will lead to the formation of infinite loop
const AuthorType = require("./AuthorType");

Типы / AuthorType.js

const graphql = require('graphql');
const Book = require('../../../models/book');
const Author = require('../../../models/author');

const {
  GraphQLObjectType,
  GraphQLString,
  GraphQLSchema,
  GraphQLID,
  GraphQLInt,
  GraphQLList,
  GraphQLNonNull,
} = graphql;

const AuthorType = new GraphQLObjectType({
  name: 'Author',
  fields: () => ({
    id: {
      type: GraphQLID
    },
    name: {
      type: GraphQLString
    },
    age: {
      type: GraphQLInt
    },
    books: {
      type: new GraphQLList(BookType),
      resolve: (parent, args) => {
        // code to get data from db
        return Book.find({
          authorId: parent.id
        });
      },
    },
  }),
});

module.exports = AuthorType;

// This is here to prevent circular dependencies problem which will lead to the formation of infinite loop
const BookType = require("./BookType");

Кроме того, лучше иметь тип / index.js, который будет действовать как обработчик для импорта / экспорта.Вы экспортируете каждый тип в index.js и берете из него все, что хотите.Это избавит вас от большого количества грязного кода, потому что теперь вы можете сделать что-то вроде этого:

const { BookType, AuthorType, OtherType } = require("../types/index");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...