Skip to content
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

Parsing schema definition language #126

Open
guiwoda opened this issue Mar 14, 2017 · 9 comments
Open

Parsing schema definition language #126

guiwoda opened this issue Mar 14, 2017 · 9 comments
Assignees

Comments

@guiwoda
Copy link

guiwoda commented Mar 14, 2017

Is there any way to parse a Schema Definition Language file with this library?
I'd rather write type definitions the GraphQL way than using php arrays and custom-made objects, so that my definitions are valid as long as the GraphQL spec remains compatible.

I can't find any example that does something like:

$schema = Schema::parse(
    file_get_contents('schema.graphsqls')
);
@colinmollenhour
Copy link

What is the best way to use Youshido/GraphQL and do GraphQL mocking?

It seems if the schema could be parsed from a schema file as suggested here then you could use graphql-tools to mock your schema based on it and then this schema file would be single "truth" for both the application and the mock.

Alternatively, is there a way to dump the PHP-based schema to a GraphQL standard format schema file? That would work too I think although it wouldn't help much if you were trying to develop your frontend before the backend exists fully.

@fritz-gerneth
Copy link
Contributor

fritz-gerneth commented May 17, 2017

I'm not sure that parsing a schema definition on the server side does make sense - it would be missing the one vital point: how to actually retrieve the data (from whatever data source). The schema definition used by the client does not and should not contain the logic on how to do so.
I see the information flow the other way - the client has to use the schema provided by the client. So it is the server's responsibility to provide the schema, not the client's to provide it for the server.

That being said, there are many ways on how to handle schema generation for clients. In the end, they simply all contain the result of an introspection query (like the one GraphiQL sends, which is from a server's perspective just any regular client). For PHPStorm, there is this plugin for generating the schema file.
We on our end have an application CLI command to generate the schema directly (which simply executes the introspection query and safes it to a file). This command as integrated into our webpack toolchain to always update the schema file.
This way not the schema file acts as the single source of trought but the server's implementation.

This same process of course can be used to have some simple mock server too. The libraries examples contain quite a few examples on how to have simple mocked servers. Yet the principle of keeping the schema file up to date is always the same.

@guiwoda
Copy link
Author

guiwoda commented May 17, 2017

@fritz-gerneth I don't follow: Why do you say a schema is used by the client only?
I understand a schema as a contract, an agreement between the data provider (server) and consumer (client). I understand you could have a different model or code to generate a schema for your consumers, but the schema exists in both ends nevertheless.

I don't see how building a schema with php and key-valued arrays is any different than parsing a file. Neither defines data retrieval, but only structure and messaging. Implementation is out of scope in both cases.

@guiwoda
Copy link
Author

guiwoda commented May 17, 2017

If you check apollo, they use GraphQL type language to define the schema, then js code to define implementations of messages:

http://dev.apollodata.com/tools/graphql-tools/generate-schema.html

Last step looks kind of like what I'm suggesting: based on this schema file and this implementation, make an executableSchema object.

@viniychuk
Copy link
Member

@colinmollenhour I guess the fastest way to do so is to create your own "DataResolver" and start passing it around to resolvers inside your fields. It's quite easy to do and will get your frontend a working version of the GraphQL Schema.

@guiwoda The last thought is to make it so we read/parse GraphQL Schema Language format and generate "base" classes that you can extend to set resolvers

@guiwoda
Copy link
Author

guiwoda commented May 18, 2017

I'm not a fan of code generation tools, but I guess that's the easiest way of reusing your existing schema code. 👍

@fritz-gerneth
Copy link
Contributor

@guiwoda I wasn't aware of that tool by apollo. We're only using the apollo-angular client on our end :) Personally I an not a fan of this approach (it decouples the type & implementation of the server side) but I can see the intention and use behind this.
You're right to see the schema as a contract between the server and the client. In my oppinion though, it is the server how defines the schema, not the client. In the link provided mostly makes sense in the server context (I think apollo uses it for the server only too). Any client actually only does need the schema part, which is pretty much the same as a regular introspection query (if I recall correctly the apollo client actually doesn't event read the schema?).
The point I'm trying to make is that it is really the server who defines the schema and the client has to act accordingly. Hence, it should be the server who is the source of trouth for the schema.

For apollo, even on the client, it certainly might be helpful to have a schema in written in javascript. But I think it should be the server to generate it, not the client to provide it for the server. So personally I'd go down the road to have some simple CLI tool to generate the schema.js as expected based on the schema defined on the server.
Doing it the other way arround is certainly not possible in the manner of creating the objects this lib expects on the fly, based on the schema.js. This could either be a code generator or by using the array configuration syntax. In either case I'd see this as an extension sitting in front on the graphql processor provided and configuring it before passing in the request. The biggest problem I see with this is, that the schema file is actual javascript, not JSON. This would make parsing the file in PHP relatively complicated. In my oppinion that's something that should live as an extra package though, not as part of this lib directly (as it's not a feature for the core graphql processor).

@colinmollenhour
Copy link

I love the way the schema is built programmatically as it will work great in modular and dynamic systems where fields are dynamic and modules can add new root-level and type-level fields using event observers and such. I think the apollo approach of having schema and resolvers defined separately is not so great in this case.

@iainmckay
Copy link

For our project we recently built out a system for programatically generating the server-side graph. If anyone is looking for ideas you can find an example here. It's not quite what you were asking about but we chose this approach because it has a good balance between development speed and it's verifiable against an existing spec.

We thought about making it standalone but it has quite tight coupling to some of our features and the structure of our GraphQL and we just don't have the time to generalize it. We also have a requirement to support multiple client interfaces (e.g. GraphQL, REST) in the near future so this all gets processed in to an agnostic format; although the format of the YAML file is influenced by GraphQL.

Our workflow currently consists of the front and back-end teams coming together to agree on a GraphQL schema for a feature and describing it as a .graphqls file. The front-end team uses a mock server to develop against. The back-end teams implement this file as per our YAML format. Our YAML file is then processed and generates PHP which pretty much looks like as if you had constructed the graph using the building blocks from the Youshido project. We then have a verification tool. It takes all of our .graphqls schema's and produces a result to an introspection query then it stands up our back-end GraphQL and diffs the introspection query from that to find non-conformity.

We found that once you get past a certain size or complexity in your graph, the time it takes to implement it by hand through the object structure provided by this project becomes unmanageable. I think code generation is going to be a must for most projects.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants