New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow to specify field type as a string #1979
Comments
You can just use thunk. You do not need const anotherModule = require('anotherModule');
const Type = new GraphQLObjectType({
name: 'MyType',
fields: () => ({
anotherType: { type: anotherModule.AnotherType }
})
}) With bundlers even import should work: import { AnotherType } from 'anotherModule';
const Type = new GraphQLObjectType({
name: 'MyType',
fields: () => ({
anotherType: { type: AnotherType }
})
}) But you must use thunk |
There are several reasons why it doesn't work in my case:
const { AnotherType } = require('anotherModule') If I follow suggested way, the code will look not consistent across the project. Also the suggested approach may not work in
Currently I use nexus to build my static schema and pure The issue with nexus is that in the recent version, they started to walk recursively over the whole graph of types (the same way as graphql-js does) and actually double the time to create |
That is ok. Nobody enforces you.
BTW did you add thunk for field everywhere? It may work even with require destructuring. (NOTE: By destructuring you destroy circular reference workaround in node.
Why not? It will work — because Ok, why I'm against this: I cannot imagine how to implement this nicely. Try open PR and play with it ;-) |
I see now that it's not easy to work with strings at least right now it will require a lot of changes. What if we introduce a new type Updated const { GraphQLObjectType, GraphQLRefType } = require('graphql')
const Type = new GraphQLObjectType({
name: 'MyType',
fields: {
anotherType: { type: new GraphQLRefType('AnotherType') } // AnotherType is referenced by its name
}
})
const AnotherType = new GraphQLObjectType({
name: 'AnotherType',
fields: {
....
}
})
const schema = new GraphQLSchema({
types: [Type, AnotherType]
}) |
And now compare with this: const { GraphQLObjectType } = require('graphql')
const Type = new GraphQLObjectType({
name: 'MyType',
fields: () => ({
anotherType: { type: AnotherType }
})
})
const AnotherType = new GraphQLObjectType({
name: 'AnotherType',
fields: {
....
}
}) It is perfectly fine implementation |
It’s fine while types in the same file :) I prefer code first approach to build schema because it’s easier to support and has less boilerplate. Also I structure my app by independent modules. In such cases, it’s sometimes useful to have some sort of indirection. It’s kind of simple DI container for types based on GraphQSchema. Also it would help to implement later something like After trying to overcome some implementation challenges now I see a conceptual issue:
So, if you don’t plan to do something with this, then ticket may be closed. However the minimum change which I would like to see is the possibility to extend GraphQLSchema class and override type iteration logic, so libraries like |
Added this snippet, so it's easier to understand what I want when saying "can provide prebuilt const { GraphQLSchema } = require('graphql')
class MyGraphQLSchema extends GraphQLSchema {
_traverseTypes(types) {
// returns typeMap
// line here https://github.com/graphql/graphql-js/blob/master/src/type/schema.js#L184
}
_traverseDirectives(directives) {
// returns typeMap for directives
// https://github.com/graphql/graphql-js/blob/master/src/type/schema.js#L187
}
_buildTypesImplementationIndex() {
// returns this._implementation
// lines https://github.com/graphql/graphql-js/blob/master/src/type/schema.js#L196-L211
}
} |
I'm trying to split my types in many packages and it is hard to do using type instances when you can't avoid circular references in types (most GraphQL schemas that I know). thunk solves part of this, but it makes it hard to add or remove fields to existing types you can do something like this
we could have a helper to handle both export const getObjectType = (typeOrString) => {
if (typeOrString instanceof GraphQLObjectType) {
return typeOrString;
}
return typeMap[typeOrString];
} |
So, is this something you guys want to see in graphql.js? just don't want to waste time in case you are against it :) |
can you send a PR for this? |
Yes, I can find some free time to do it but it won’t be quick. But, I want to understand that it’s something guys want to see in the codebase and eventually will not reject it because there is already thunk support for this (or something similar). My free time is currently quite expensive for me because I have a small baby. So I don’t want to throw this time in a trash bin at the end :) |
Right now resolving types at runtime is done with strings rather than exact objects, because of bug with schema regenerators that don’t wrap resolveType #2779 (comment) so it’s odd that you can’t build a schema with strings! |
Currently
graphql.js expects
type
option to be an instance of GraphQLType (GraphQLInputObjectType
,GraphQLObjectType
, etc).Example:
Desired
In order to split application into modules (which may have circular references in GraphQL types) it'd be helpful to be able to specify
type
parameter in fields as a string. Updated example:Workaround
Currently when nodejs modules have circular reference, I can use ugly workaround: calling
require
infields
thunk:Implementation details
We can add a restriction, that types which a referenced by their name must be included in
types
option ofGraphQLSchema
constructor:So, then the flow is this:
types
array, add them intotypeMap
Query
,Mutation
,Subscription
recursively and resolve typesThe text was updated successfully, but these errors were encountered: