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

Added support for graphql-code-generator, and some other improvements #129

Closed
wants to merge 3 commits into from

Conversation

dotansimha
Copy link

@dotansimha dotansimha commented Oct 24, 2018

Hi @leebenson ! I'm using reactql for some of our projects, and it's awesome!

In this PR I added some nice features and extensions, that makes it easier to write client-side GraphQL apps with TypeScript.
I know this PR is big, but let me know what do you think, and I can separate it to smaller pieces if it will be easier to get it merged.

The changes in this PR are:

Added support for .graphql files

Added graphql-tag/loader to Webpack configuration, this way it's possible now to import from .graphql files directly, without wrapping it with .ts files.

image

Client-side schema declatation

Instead of using TypeScript schema for local-state, we can write the GraphQL client-side (local state) schema as regular GraphQL schema in .graphql file.

image

Added graphql-code-generator

I updated the boilerplate to use graphql-code-generator, and now it's generating typings, components and more.
The idea is to use type-safety, and use GraphQL-first approach.
I'm using the codegen to generate typings for both local and remote schema.

The codegen is running in watch mode during development, and single-time during build.

Also, during the generation, the codegen uses the schema and the client-side operations and fragments, and validates it, so you'll get the errors now during compilation, instead of during the app runtime:

image

Schema typings

Now that schema typings are available, for both remote schema and local schema, we can remove IRoot and IState declarations, and generate them directly from the declared schema.

image

React Wrapper components

Now it also generates React components that wraps <Query> and <Mutation > from react-apollo. And we are getting a full type-safe queries and mutations, with IDE auto-complete.

image

It's also generates typings for the selection set of queries and mutations, and you get auto-complete for the fields you requested on the query:

image

.graphql modules declaration

I'm using graphql-codegen-typescript-react-apollo-template template of the codegen, to generate typings for .graphql files import, this way we can import from .graphql files, and also have a type-safe on those imports (import { myQuery } from './my-query.graphql').

image

Changed remote GraphQL schema

I replaced graphqlhub with fakerql because graphqlhub uses a very old implementation of GraphQL server, and no longer maintained.
We can't use the codegen with this version, and it the basic idea is to have a query from a remote source, Todo should do the trick.
Also, fakerql has a very useful schema, including useful types such as Todo, User, Product, Post and more.

replace graphqlhub with fakerql api
replace ui example with todo app
added `graphql-tag/loader` to webpack build
@leebenson
Copy link
Owner

leebenson commented Oct 24, 2018

This is awesome work, thanks @dotansimha!

Give me a couple of days to play with this PR locally and get familiar with the new features, then I'll get this merged. On first glance, looks great!

@bmschwartz
Copy link

bmschwartz commented Oct 25, 2018

I love this! @prisma makes a similar tool called graphqlgen. It's only 10 days old but the prisma ecosystem has a lot of backing and seems promising. Probably not mature enough to integrate now though.

@dotansimha
Copy link
Author

@bmschwartz , The graphgen tool by Prisma only generates server-side typings for resolvers, so I think it might be irrelevant for ReactQL at this time. It also does not support local schema.

graphql-code-generator is a generic tool for generating anything from GraphQLSchema and GraphQL documents, and we have template for both client-side and server-side.
The templates I used here are relevant for client-side (based on the local-schema and the remote-schema together), and it generates typings for .graphql files (for auto complete), wrapper components for react-apollo package (that brings type-safety and auto-complete) and generated typings for the response objects from Apollo client, none of which graphgen is intending to do.

@bmschwartz , as a side note, even just for the backend, I believe our template is much better than what graphgen is doing. I won't write all the reasons why here but I would love if you could try them both on the server as well and tell me your thoughts

@bmschwartz
Copy link

bmschwartz commented Oct 26, 2018

Thanks @dotansimha, I'll read into both projects further. I remembered reading about graphqlgen the other day and thought it looked similar. I'm very excited to try out your PR though.

Didn't realize you were the author of that project. Awesome!

@dotansimha
Copy link
Author

@leebenson, now the code-generator has a Webpack plugin (dotansimha/graphql-code-generator#739, thanks to @kamilkisiela), I'll update this PR to use once we'll release a new version :)

@dotansimha
Copy link
Author

I updated the PR to the latest stable version of the codegen. It improves the performance, and much easier to read the output of it :)
@leebenson, did you had the chance to review this PR?

@leebenson
Copy link
Owner

@dotansimha - my apologies in the delay in getting back to you on this PR. Will try and get some time in the coming week to review.

@dotansimha
Copy link
Author

Hi @leebenson :) Any update?

@leebenson
Copy link
Owner

Sorry for my slow response to this.

When I run install the latest packages and run npm start against this PR, I get this:

Watchman:  Watchman was not found in PATH.  See https://facebook.github.io/watchman/docs/install.html for installation instructions
(node:68655) UnhandledPromiseRejectionWarning: Error: Watchman was not found in PATH.  See https://facebook.github.io/watchman/docs/install.html for installation instructions
    at Process.ChildProcess._handle.onexit (internal/child_process.js:246:19)
    at onErrorNT (internal/child_process.js:421:16)
    at process.internalTickCallback (internal/process/next_tick.js:72:19)
(node:68655) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:68655) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

I think it'd be nicer for ReactQL if we had a more graceful error message, since it's likely Watchman won't be installed by default on a target machine.

Is that something that can be handled in ReactQL-land code? Or does it need to be handled upstream in your own package?

@leebenson
Copy link
Owner

Some additional issues I came across...

  1. If a valid GraphQL server isn't reachable on start-up, it fails with a cryptic error:

screenshot 2019-01-20 at 19 20 11

(I've pasted it as a screenshot to give the full impression of what a user would first see.)

I'd love to see this updated with a friendlier message about what happened; it's not apparent exactly what went wrong. (In this case, it was a 404 on the route... distinguishing between a network error, an invalid schema, and dumping the attempted URL out to the console would be useful.


  1. The current tslint.json config balks at the generated files. This should be a relatively simple fix for the linter, but it's an issue that could throw off a git/CD/CI pipeline that checks code passes linting:

screenshot 2019-01-20 at 19 33 25


  1. There's a warning thrown by Node about not checking certificates:

ℹ Building development server...
(node:89668) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.

graphql-code-generators looks like it's mutating process.env.NODE_TLS_REJECT_UNAUTHORIZED directly, which seems inherently unsafe - wouldn't this have the effect of blocking validation across an entire app?


  1. The flow of generating GraphQL types feels off to me. In the current flow, it's required to first have Wacthman installed... then a valid, reachable GraphQL server configured (or it'll blow up with the first cryptic error)... then run npm start and then import any generated files... and then restart if the GraphQL server changes its schema, which could easily invalidate user code.

Those steps are quite opinionated and brittle.

I think it would be preferable to have GraphQL building as a separate NPM script/build step, so that:

a) Running npm start won't fail, irrespective of the state of the running GraphQL server.

b) If the GraphQL schema changes, there's a simple/explicit way to rebuild schema (which should, ideally, be then picked up by the Webpack watcher and automatically restart the dev server.) This would make it easir to then just open another Terminal window and rebuild the schema at will.


@dotansimha, if you have the free time/interest to tackle the above, I'd love to get this included. I can see this lib being of a great use in most every project... it's just the build/start-up flow that needs refining, IMO.

@leebenson
Copy link
Owner

In v4.2, I added graphql-code-generator along with demo schema and React plugins. The schema can be rebuilt with:

npm run gen:graphql

I think this is a great midway point between generating types, and having a full dev experience that re-gens on file save. With VSCode/other IDE plugins, the interop is pretty straightforward and it eliminates the need for Watchman or couple the generator too tightly to user-land code that may not require it.

@dotansimha, I want to thank you for your hard work on this, and for putting together an excellent package. I'd highly recommend anyone reading give it a shot - it really cuts down both on TS type generation, and manually wiring up Apollo HOCs. Love it!

@leebenson leebenson closed this Feb 20, 2019
@dotansimha
Copy link
Author

Thank you @leebenson ! sounds great!

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

Successfully merging this pull request may close these issues.

None yet

3 participants