如何在没有循环依赖的情况下在GraphQL中拆分模式?
我的问题与Javascript circular dependency in GraphQL code类似,但我的问题不在于结构和数据库级别,而是在JavaScript(ES6)中。如何在没有循环依赖的情况下在GraphQL中拆分模式?
我的模式定义越来越大,但我没有看到我可以将文件分割成几部分。这似乎是合乎逻辑的基础上,不同的对象类型削减,但带来的循环依赖与此同样非常简单,非工作例如:
// -- 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();
}
}
}
}
})
谢谢,我接受你的解决方案,因为它绝对可以解决我的问题。我仍然试图找到一种不使用grunt的方法,因为这似乎是矫枉过正的,只是因为这个问题才使用它。但是如果没有其他办法,我会执行这一个。 –
如果你想给Apollo的graphql-tools一个镜头,它会真正简化你的代码并使其更具可读性。如果你使用它,我已经写了一个名为schemaglue.js的工具来解决你确切的问题。我已经写了关于扩展和组织您的GraphQL代码:https://hackernoon.com/graphql-schemas-easier-better-structure-31677a640d18希望这有助于。 –
有你发现了其他解决方案? –