如何在没有循环依赖的情况下在GraphQL中拆分模式

How to split schema in GraphQL without having circular dependencies?

本文关键字:GraphQL 情况下 拆分 模式 依赖 循环      更新时间:2023-09-26

我的问题类似于GraphQL代码中的Javascript循环依赖,但我的问题不在于结构和数据库级别,而在于Javascript (ES6)。

我的模式定义变得太大了,但我不知道在哪里可以将文件分成几个部分。根据不同的对象类型进行切割似乎是合乎逻辑的,但这带来了类似于这个非常简化的,不工作的示例的循环依赖:

    // -- file A.js
    import { bConnection, getBs } from 'B';
    export class A { /*...*/ };
    export var getA = (a) => { /*...*/ };
    export var getAs = (array_of_as) => { /*...*/ };
    export var aType = new GraphQLObjectType ({
      name: 'A',
      fields: () => ({
        bs: {
          type: bConnection,
          /*...*/
        },
        resolve: (a, args) => connectionFromPromisedArray (
          getBs (a.bs)
        ),
        /*...*/
      }),
      interfaces: () => [ require ('./nodeDefs').nodeInterface ],
      /*...*/
    })
    export var {
        connectionType: aConnection,
        edgeType: aEdge
      } = connectionDefinitions ({
        name: 'A',
        nodeType: aType
      });
    // -- file B.js
    import { aConnection, getAs } from 'A';
    export class B { /*...*/ };
    export var getB = (b) => { /*...*/ };
    export var getBs = (array_of_bs) => { /*...*/ };
    export var bType = new GraphQLObjectType ({
      name: 'B',
      fields: () => ({
        as: {
          type: aConnection,
          /*...*/
        },
        resolve: (b, args) => connectionFromPromisedArray (
          getAs (b.bs)
        ),
        /*...*/
      }),
      interfaces: () => [ require ('./nodeDefs').nodeInterface ],
      /*...*/
    })
    export var {
        connectionType: bConnection,
        edgeType: bEdge
      } = connectionDefinitions ({
        name: 'B',
        nodeType: bType
      });
    // -- file nodeDefs.js
    import {
      fromGlobalId,
      nodeDefinitions,
    } from 'graphql-relay';
    import { A, getA, aType } from 'A'
    import { B, getB, bType } from 'B'
    export var {nodeInterface, nodeField} = nodeDefinitions (
      (globalId) => {
        var {type, id} = fromGlobalId (globalId);
        if (type === 'A') {
          return getA (id);
        } else if (type === 'B') {
          return getB (id);
        }
      },
      (obj) => {
        if (obj instanceof A) {
          return aType;
        } else if (obj instanceof B) {
          return bType;
        }
      }
    )
    // -- file schema.js
    import {
      GraphQLObjectType,
      GraphQLSchema,
    } from 'graphql';
    import { nodeField } from './nodeDefs';
    var queryType = new GraphQLObjectType ({
      name: 'Query',
      fields: () => ({
        node: nodeField,
        /*...*/
      }),
    });

是否有通用的方法或最佳实践?

我也有同样的问题。我认为更干净的解决方案是使用gruntjs concat。

grunt.initConfig({
  concat: {
    js: {
      src: ['lib/before.js', 'lib/*', 'lib/after.js'],
      dest: 'schema.js',
    }
  }
});

使用此配置,您可以将模式拆分为几个文件,创建最终的schema.js。

before.js可以这样写:

 import {
    GraphQLObjectType,
    GraphQLInt,
    GraphQLString,
    GraphQLSchema,
    GraphQLList,
    GraphQLNonNull
} from 'graphql';
import db from '../models/index.js';
import Auth from '../classes/auth';

after.js可以这样:

const Schema = new GraphQLSchema({
    query: Query,
    mutation: Mutation
})
export default Schema;

其他文件将包含如下对象:

const Funcionario = new GraphQLObjectType({
name: 'Funcionario',
description: 'This represent a Funcionario',
fields: () => {
    return {
        id: {
            type: GraphQLInt,
            resolve(funcionario, args) {
                return funcionario.id;
            }
        },
        CPF: {
            type: GraphQLString,
            resolve(funcionario, args) {
                return funcionario.CPF;
            }
        },
        nome: {
            type: GraphQLString,
            resolve(funcionario, args) {
                return funcionario.nome;
            }
        },
        sobrenome: {
            type: GraphQLString,
            resolve(funcionario, args) {
                return funcionario.sobrenome;
            }
        },
        sessions: {
            type: new GraphQLList(Session),
            resolve(funcionario, args) {
                return funcionario.getSessions();
            }
        }
    }
}
})

参见https://github.com/francoisa/todo/tree/master/server/graphql/types

todoType.js有一个viewerType的引用,它在viewerType.js

中定义

viewtype .js from todoType