Circular import components are common within nodejs and graphql. This article provide a easy way to resolve that warning. The easy solution is adding related imports to limited scope in javascript instead of importing them at file start position.
The example scenario contains three parts: User, Role and UserRoleRel. An user has many roles and a role has many user had been taken. The relationship of many-to-many is recorded at UserRoleRel
Below are excerpt solution code about nodejs with graphql:
User model:
// User.js
const graphql = require("graphql");
const joinMonster = require("join-monster");
const User = new graphql.GraphQLObjectType({
name: "User",
/*
skip
...
...
...
*/
// excerpt code
fields: () => {
const { Role } = require("./Role"); // <== critical import within fields scope
return {
id: {
type: graphql.GraphQLID,
extensions: {
joinMonster: {
sqlColumn: "id",
},
},
},
name: {
type: graphql.GraphQLString,
extensions: {
joinMonster: {
sqlColumn: "name",
},
},
},
roles: {
type: new graphql.GraphQLList(Role), // because here use "Role" the imported
description: "some roles",
joinMonster: {
junction: {
sqlTable: "user_role_rel",
sqlJoins: [
(userTable, userRoleRelTable) =>
`${userTable}.id = ${userRoleRelTable}.uid`,
(userRoleRelTable, roleTable) =>
`${userRoleRelTable}.rid = ${roleTable}.id`,
],
},
},
},
/*
* skip
* ...
* ...
* ...
*/
};
},
});
module.exports = {
User,
};
Role model:
// Role.js
const graphql = require("graphql");
const joinMonster = require("join-monster");
const Role = graphql.GraphQLObjectType({
name: "Role",
/*
* skip
* ...
* ...
* ...
*/
// excerpt code
fields: () => {
const { User } = require("./User"); // <== critical import within fields scope
return {
id: {
type: graphql.GraphQLID,
extensions: {
joinMonster: {
sqlColumn: "id",
},
},
},
name: {
type: graphql.GraphQLString,
extensions: {
joinMonster: {
sqlColumn: "name",
},
},
},
users: {
type: new graphql.GraphQLList(User), // // because here use "User" the imported
description: "some users",
extensions: {
joinMonster: {
junction: {
sqlTable: "user_role_rel",
sqlJoins: [
(roleTable, userRoleRelTable) =>
`${roleTable}.id = ${userRoleRelTable}.rid`,
(userRoleRelTable, userTable) =>
`${userRoleRelTable}.uid = ${userTable}.id`,
],
},
},
},
},
/*
* skip
* ...
* ...
* ...
*/
};
},
});
module.exports = {
Role,
};
UserRoleRel is a table in concept that has columns such as uid for refering id within table user and rid for id within table role. So I won’t go through detail.
Reference link: