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: