1 | <img src="https://cdn.jsdelivr.net/gh/martimatix/logo-graphqelm/logo.svg" alt="dillonearns/elm-graphql logo" width="40%" align="right">
|
2 |
|
3 | # dillonkearns/elm-graphql
|
4 |
|
5 | [![Build Status](https://travis-ci.org/dillonkearns/elm-graphql.svg?branch=master)](https://travis-ci.org/dillonkearns/elm-graphql) [![Elm package](https://img.shields.io/elm-package/v/dillonkearns/elm-graphql.svg)](https://package.elm-lang.org/packages/dillonkearns/elm-graphql/latest/)
|
6 | [![npm](https://img.shields.io/npm/v/@dillonkearns/elm-graphql.svg)](https://npmjs.com/package/@dillonkearns/elm-graphql)
|
7 |
|
8 | Why use this package over the other available Elm GraphQL packages? This is the only one that
|
9 | generates type-safe code for your entire schema. Check out this blog post, [Type-Safe & Composable GraphQL in Elm](https://medium.com/open-graphql/type-safe-composable-graphql-in-elm-b3378cc8d021), to learn more about the motivation for this library. (It's also the only type-safe
|
10 | library with Elm 0.18 or 0.19 support, see
|
11 | [this discourse thread](https://discourse.elm-lang.org/t/introducing-graphqelm-a-tool-for-type-safe-graphql-queries/472/5?u=dillonkearns)).
|
12 |
|
13 | I built this package because I wanted to have something that:
|
14 |
|
15 | 1. Gives you type-safe GraphQL queries (if it compiles, it's valid according to the schema),
|
16 | 2. Creates decoders for you in a seamless and failsafe way, and
|
17 | 3. Eliminates GraphQL features in favor of Elm language constructs where possible for a simpler UX (for example, GraphQL variables & fragments should just be Elm functions, constants, lets).
|
18 |
|
19 | See an [example in action on Ellie](https://rebrand.ly/graphqelm). See more end-to-end example code in the
|
20 | [`examples/`](https://github.com/dillonkearns/elm-graphql/tree/master/examples)
|
21 | folder.
|
22 |
|
23 | ## Overview
|
24 |
|
25 | `dillonkearns/elm-graphql` is an Elm package and accompanying command-line code generator that creates type-safe Elm code for your GraphQL endpoint. You don't write any decoders for your API with `dillonkearns/elm-graphql`, instead you simply select which fields you would like, similar to a standard GraphQL query but in Elm. For example, this GraphQL query
|
26 |
|
27 | ```graphql
|
28 | query {
|
29 | human(id: "1001") {
|
30 | name
|
31 | homePlanet
|
32 | }
|
33 | }
|
34 | ```
|
35 |
|
36 | would look [like this](https://github.com/dillonkearns/elm-graphql/blob/master/examples/src/ExampleFromReadme.elm)
|
37 | in `dillonkearns/elm-graphql` (the code in this example that is prefixed with `StarWars` is auto-generated)
|
38 |
|
39 | ```elm
|
40 | import Graphql.Operation exposing (RootQuery)
|
41 | import Graphql.SelectionSet as SelectionSet exposing (SelectionSet)
|
42 | import StarWars.Object.Human as Human
|
43 | import StarWars.Query as Query
|
44 | import StarWars.Scalar exposing (Id(..))
|
45 |
|
46 |
|
47 | query : SelectionSet (Maybe Human) RootQuery
|
48 | query =
|
49 | Query.human { id = Id "1001" } humanSelection
|
50 |
|
51 |
|
52 | type alias HumanData =
|
53 | { name : String
|
54 | , homePlanet : Maybe String
|
55 | }
|
56 |
|
57 |
|
58 | humanSelection : SelectionSet Human StarWars.Object.Human
|
59 | humanSelection =
|
60 | SelectionSet.map2 HumanData
|
61 | Human.name
|
62 | Human.homePlanet
|
63 | ```
|
64 |
|
65 | GraphQL and Elm are a perfect match because GraphQL is used to enforce the types that your API takes as inputs and outputs, much like Elm's type system does within Elm. `elm-graphql` simply bridges this gap by making your Elm code aware of your GraphQL server's schema. If you are new to GraphQL, [graphql.org/learn/](http://graphql.org/learn/) is an excellent way to learn the basics.
|
66 |
|
67 | After following the installation instructions to install the [`@dillonkearns/elm-graphql`](https://npmjs.com/package/@dillonkearns/elm-graphql)
|
68 | NPM package and the proper Elm packages (see the [Setup section](https://github.com/dillonkearns/elm-graphql#setup) for details).
|
69 | Once you've installed everything, running the `elm-graphql` code generation tool
|
70 | is as simple as this:
|
71 |
|
72 | ```bash
|
73 | elm-graphql https://elm-graphql.herokuapp.com --base StarWars --output examples/src
|
74 | ```
|
75 |
|
76 | If headers are required, such as a Bearer Token, the `--header` flag can be supplied.
|
77 |
|
78 | ```bash
|
79 | elm-graphql https://elm-graphql.herokuapp.com --base StarWars --output examples/src --header 'headerKey: header value'
|
80 | ```
|
81 |
|
82 | ## Learning Resources
|
83 |
|
84 | - There is a thorough tutorial in [the `SelectionSet` docs](https://package.elm-lang.org/packages/dillonkearns/elm-graphql/latest/Graphql-SelectionSet). `SelectionSet`s are the core concept in this library, so I recommend reading through the whole page (it's not very long!).
|
85 |
|
86 | - The [`examples/`](https://github.com/dillonkearns/elm-graphql/tree/master/examples) folder is another great place to start.
|
87 |
|
88 | - If you want to learn more GraphQL basics, this is a great tutorial, and a short read: [graphql.org/learn/](http://graphql.org/learn/)
|
89 |
|
90 | - My Elm Conf 2018 talk goes into the philosophy behind `dillonkearns/elm-graphql`
|
91 |
|
92 | [![Types Without Borders Elm Conf Talk](./assets/types-without-borders.png)](https://www.youtube.com/watch?v=memIRXFSNkU)
|
93 |
|
94 | ([Skip to 13:06](https://youtu.be/memIRXFSNkU?t=786) to go straight to the `dillonkearns/elm-graphql` demo).
|
95 |
|
96 | - My 10-minute video tutorial on how to leverage Custom Scalars in `elm-graphql` using the Scalar Codecs feature.
|
97 | [![Scalar Codecs Tutorial](./assets/scalar-codecs-tutorial.png)](https://incrementalelm.com/scalar-codecs-tutorial)
|
98 |
|
99 | * [A Beginner's Guide to GraphQL with Elm](https://medium.com/@zenitram.oiram/a-beginners-guide-to-graphql-with-elm-315b580f0aad) by [@martimatix](https://github.com/martimatix)
|
100 | * [Graphqelm: Optional Arguments in a Language Without Optional Arguments](https://medium.com/@zenitram.oiram/graphqelm-optional-arguments-in-a-language-without-optional-arguments-d8074ca3cf74) by [@martimatix](https://github.com/martimatix)
|
101 | * [Comprehensive tutorial by the Hasura Team](https://learn.hasura.io/graphql/elm-graphql/introduction)
|
102 |
|
103 | If you're wondering why code is generated a certain way, you're likely to find an answer in the [Frequently Asked Questions (FAQ)](https://github.com/dillonkearns/elm-graphql/blob/master/FAQ.md).
|
104 |
|
105 | There's a very helpful group of people in the #graphql channel in [the Elm Slack](http://elmlang.herokuapp.com/). Don't hesitate to ask any questions about getting started, best practices, or just general GraphQL in there!
|
106 |
|
107 | ## Setup
|
108 |
|
109 | `dillonkearns/elm-graphql` generates Elm code that allows you to build up type-safe GraphQL requests. Here are the steps to setup `dillonkearns/elm-graphql`.
|
110 |
|
111 | 1. Add [the `dillonkearns/elm-graphql` elm package](http://package.elm-lang.org/packages/dillonkearns/elm-graphql/latest)
|
112 | as a dependency in your `elm.json`. You will also need to make sure that `elm/json` is a dependency of your project
|
113 | since the generated code has lots of JSON decoders in it.
|
114 | ```shell
|
115 | elm install dillonkearns/elm-graphql
|
116 | elm install elm/json
|
117 | ```
|
118 | 2. Install the `@dillonkearns/elm-graphql` command line tool through npm. This is what you will use to generate Elm code for your API.
|
119 | It is recommended that you save the `@dillonkearns/elm-graphql` command line tool as a dev
|
120 | dependency so that everyone on your project is using the same version.
|
121 |
|
122 | ```shell
|
123 | npm install --save-dev @dillonkearns/elm-graphql
|
124 | # you can now run it locally with the ./node_modules/.bin/elm-graphql binary,
|
125 | # or by calling it through an npm script as in this project's package.json
|
126 | ```
|
127 |
|
128 | 3. Run the `@dillonkearns/elm-graphql` command line tool installed above to generate your code. If you used the `--save-dev` method above, you can simply create a script in your package.json like the following:
|
129 |
|
130 | ```
|
131 | {
|
132 | "name": "star-wars-elm-graphql-project",
|
133 | "version": "1.0.0",
|
134 | "scripts": {
|
135 | "api": "elm-graphql https://elm-graphql.herokuapp.com/api --base StarWars"
|
136 | }
|
137 | ```
|
138 |
|
139 | 4. With the above in your `package.json`, running `npm run api` will generate `dillonkearns/elm-graphql` code for you to call in `./src/StarWars/`. You can now use the generated code as in this [Ellie example](https://rebrand.ly/graphqelm) or in the [`examples`](https://github.com/dillonkearns/elm-graphql/tree/master/examples) folder.
|
140 |
|
141 | ## Subscriptions Support
|
142 |
|
143 | You can do real-time APIs using GraphQL Subscriptions and `dillonkearns/elm-graphql`.
|
144 | Just wire in the framework-specific JavaScript code for opening the WebSocket connection
|
145 | through a port. Here's a [live demo](http://www.dillonkearns.com/elm-graphql/) and its
|
146 | [source code](https://github.com/dillonkearns/elm-graphql/tree/master/examples/subscription). The [demo server is running Elixir/Absinthe](https://github.com/dillonkearns/graphqelm-demo).
|
147 |
|
148 | ## Contributors
|
149 |
|
150 | Thank you Mario Martinez ([martimatix](https://github.com/martimatix)) for
|
151 | all your feedback, the elm-format PR, and for [the incredible logo design](https://github.com/martimatix/logo-graphqelm/)!
|
152 |
|
153 | Thank you Mike Stock ([mikeastock](https://github.com/mikeastock/)) for
|
154 | setting up Travis CI!
|
155 |
|
156 | Thanks for [the reserved words pull request](https://github.com/dillonkearns/elm-graphql/pull/41) @madsflensted!
|
157 |
|
158 | A huge thanks to [@xtian](https://github.com/xtian) for doing the vast majority
|
159 | of the [0.19 upgrade work](https://github.com/dillonkearns/elm-graphql/pull/60)! :tada:
|
160 |
|
161 | Thank you [Josh Adams (@knewter)](https://github.com/knewter) for the code example for
|
162 | Subscriptions with Elixir/Absinthe wired up through Elm ports!
|
163 |
|
164 | Thank you [Romario](https://github.com/romariolopezc) for adding [`OptionalArgument.map`](https://github.com/dillonkearns/elm-graphql/pull/73)!
|
165 |
|
166 | Thank you [Aaron White](https://github.com/aaronwhite) for [your pull request to improve the performance and
|
167 | stability of the `elm-format` step](https://github.com/dillonkearns/elm-graphql/pull/87)! 🎉
|
168 |
|
169 | ## Roadmap
|
170 |
|
171 | All core features are supported. That is, you can build any query or mutation
|
172 | with your `dillonkearns/elm-graphql`-generated code, and it is guaranteed to be valid according
|
173 | to your server's schema.
|
174 |
|
175 | `dillonkearns/elm-graphql` will generate code for you to generate subscriptions
|
176 | and decode the responses, but it doesn't deal with the low-level details for
|
177 | how to send them over web sockets. To do that, you will need to use
|
178 | custom code or a package that knows how to communicate over websockets (or whichever
|
179 | protocol) to setup a subscription with your particular framework. See
|
180 | [this discussion](https://github.com/dillonkearns/elm-graphql/issues/43) for why
|
181 | those details are not handled by this library directly.
|
182 |
|
183 | I would love to hear feedback if you are using GraphQL Subscriptions. In particular,
|
184 | I'd love to see live code examples to drive any improvements to the Subscriptions
|
185 | design. Please ping me on Slack, drop a message in the
|
186 | [#graphql](https://elmlang.slack.com/channels/graphql) channel, or open up a
|
187 | Github issue to discuss!
|
188 |
|
189 | I would like to investigate generating helpers to make pagination simpler
|
190 | for Connections (based on the
|
191 | [Relay Cursor Connections Specification](https://facebook.github.io/relay/graphql/connections.htm)).
|
192 | If you have ideas on this chime in on [this thread](https://github.com/dillonkearns/elm-graphql/issues/29).
|
193 |
|
194 | See [the full roadmap on Trello](https://trello.com/b/BCIWtZeL/dillonkearns-elm-graphql).
|
195 |
|
\ | No newline at end of file |