【问题标题】:How to split schema in GraphQL without having circular dependencies?如何在没有循环依赖的情况下在 GraphQL 中拆分模式?
【发布时间】:2016-12-24 19:48:20
【问题描述】:

我的问题类似于Javascript circular dependency in GraphQL code,但我的问题不在结构和数据库级别,而是在 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,
        /*...*/
      }),
    });

对此有通用方法或最佳实践吗?

【问题讨论】:

  • 您找到其他解决方案了吗?

标签: javascript graphql


【解决方案1】:

我也有同样的问题。我认为更简洁的解决方案是使用 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();
            }
        }
    }
}
})

【讨论】:

  • 谢谢您,我接受您的解决方案,因为它确实解决了我的问题。我仍在试图找到一种不使用 grunt 的方法,因为仅仅因为这个问题而使用它似乎有点矫枉过正。但是如果没有别的办法,我就实现这个。
  • 如果你想试一试 Apollo 的 graphql-tools,它会真正简化你的代码并使其更具可读性。如果您使用它,我已经编写了一个名为 schemaglue.js 的工具来解决您的确切问题。我在这里写过关于缩放和组织你的 GraphQL 代码的文章:hackernoon.com/…希望这会有所帮助。
【解决方案2】:

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

tod​​oType.js 引用了 viewerType.js 中定义的 viewerType

viewerType.js 从 todoType 导入

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-29
    • 2021-03-31
    • 2020-11-11
    • 1970-01-01
    • 2016-03-31
    • 2017-07-20
    • 1970-01-01
    相关资源
    最近更新 更多