-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
dynamic GraphQL server schema and babel-relay-plugin #383
Comments
I think there was a discussion around this in Reactiflux (and I thought in an issue as well, but I can't find it). The conclusion, as I recall, was basically to avoid it. If there's stuff you want to avoid exposing to users (such as admin-only stuff), you could generate two schemas and compile the app with each. Otherwise you return null for stuff a user can't access. What prevents you from knowing the schema at compile-time? |
Forgot compiling, how would you even write product code against a schema that is effectively unknown? |
An architecture where the complete schema is only known at runtime is quite common in software in my experience. Take a CMS where users can create new types of content using a UI during runtime. Or take any random enterprise software system where types and their fields are defined in a database, again by users with an UI. Not everybody is building single-deployment web applications. A lot of software has a multiple independent deployments, each with a different configuration and extensions. Some core types and fields will be in common between all of them, but there are also fields and entire types unique to a deployment. Each schema effectively has its own schema. Whether this is the best way to architect a system is another debate: can we discuss this accepting that such systems already exist and that it may be interesting to use Relay with them? In some ways a database-generated schema makes software like this a great fit for GraphQL, as this kind of software typically already has sufficient information in its database to generate a schema. There are multiple ways you can write UIs for software where you don't know the complete schema:
graphql-js seems, as far as I can see, to be explicitly engineered to allow the generation of schema information at runtime where needed. But babel-relay-plugin, whatever it does exactly (I don't quite understand yet), is a problem. Can babel-relay-plugin be avoided entirely? What are the consequences of doing so? @cesarandreu points at a possible approach: it may be possible to know a subset of the complete schema at compile time. But how would this work for new fields or complete types that only known during runtime? @josephsavona I chatted with you briefly at React Conf Europe I believe, just before your Relay talk. So, are you asking me how people can write code in a dynamically typed language? I can try to explain... :) |
@faassen I apologize if my question came off as snarky, but I was genuinely curious and want to further understand the problem space. What I was getting at with my question is that the code clearly has to have some understanding of the structure of the data it will receive (this isn't about static/dynamic languages). Let's take as example a simple CMS that allows users to define custom types, custom fields on those types, and provides UIs for editing objects of these types. It would seem that all product code in this system would fall into one of two categories:
In both cases, the schema is actually knowable at build time. In the meta-code example the schema is the meta-schema - the schema the CMS framework uses to describe the custom types and fields. In the product-specific case, the product schema can be dynamically generated at build time to validate the code. Overall, it's absolutely possible to build Relay apps using the type of system you're describing. The schema is required for compiling queries, but this can be dynamically generated by executing the introspection query against the server prior to the build step. This is actually how we compile Relay queries at Facebook - by fetching the introspection queries from our GraphQL server and caching the results on disk.
No, because Relay needs information about the schema in order to process queries. However, as described above it should always be possible to get a schema such that queries can be compiled. |
@faassen Did this address your question? It definitely seems that what you're looking for is possible, unless I'm missing something. |
@josephsavno Thank you for the helpful answer! I think meta code is a good way to understand the problem of dynamically generated UIs, and instead of a concrete schema we'd have a schema that describes the schema and build on that. That leaves what you call "product-specific code". I think the question transforms into how one would create a composable GraphQL server. So imagine you're working on an extension to a CMS that handles a particular type of content, say "customer". You can define the schema that deals with customer-related information as part of this extension. In it, you can also build on the schema defined by the core of the CMS, and possibly the schemas of other extensions that your extension depends on. So, during development you could export this schema and use it to compile the JS code. But in reality this schema is only a subset of the complete subset available during deployment. What is available during deployment depends on what extensions get installed. Is it possible to compile the code against a partial schema (a working subset of the full schema) or is the full schema necessary? Would recompilation be needed during deployment once the full schema is known or can this be avoided entirely? This depends a bit on what babel-relay-plugin actually does: if it's just about validating a query, then it sounds like recompilation after deployment can be avoided, but if it's also about intelligent cache invalidation, then perhaps it cannot. In other words, can one develop code against a subset of a larger schema that only contains those aspects of the total schema that are in fact in use by the code? |
Yes. So long as every field/type that your queries use are in the schema that you compile against, this should be fine. The plugin does a combination of validation (do those types/fields/arguments exist?) and annotation. Annotation includes marking fields as connections so that they can be processed as such, or ensuring that queries contain an |
Okay, that's good to know! So recompilation would not be needed after code composition time; this is something that one would like to avoid in some architectures. Thanks for helping to make this whole issue more clear in my head. I'll close this issue now. If we ever end up implementing this we'll undoubtedly run into details but I'll ask those if and when needed. |
For future googlers: I'm using it in graphql-compose-mongoose, so live demos with dynamic field's type can be found here: |
@nodkz Is there then a way to specify which fields within |
@limscoder field As solution may be used |
Imagine a server that dynamically generates a GraphQL schema based on database content. The schema is only known during runtime, not compile time.
How does this interact with babel-relay-plugin? babel-relay-plugin requires a static dump of the server schema, but with a dynamic GraphQL schema that schema does not exist at this time. Recompiling the JS frontend code each time the server schema changes is not an option.
How would you make this work?
The text was updated successfully, but these errors were encountered: