Giter Club home page Giter Club logo

graphql-codegen-reason's Introduction

GraphQL Codegen: Reason Client

A plugin for GraphQL Codegen to generate ReasonML types based on your GraphQL schema for use in a client application.

Quick Start

Install using npm/yarn:

$ yarn add graphql-codegen-reason-client -D

Set up your project per the GraphQL Codegen Docs, and specify this plugin in your codegen.yml:

schema: http://path.to.your.app
generates:
  src/GraphQLTypes.re:
    - reason-client

__typename is REQUIRED

In order to verify that the JSON object we're working with is of the expected GraphQL type, this lib requires that the __typename field be present for all GraphQL query respones. (If you're using apollo-client, this is easily accomplished via a config setting that defaults to true - chances are you're already doing it!)

Configuration

Currently the only supported configruation is specifying custom scalar values, like so:

schema: http://path.to.your.app
generates:
  src/GraphQLTypes.re:
    plugins:
      - reason-client
    config:
      scalars:
        "DateTime": "string"

Note that any custom scalars must be able to be decoded to a scalar Reason type (string, bool, float, etc.). Eventually it'd be great to support providing a reference to a custom decoder module...

Working with the generated types

The API for the generated types was inspired by the [@bs.deriving abstract] syntax recently released for bs-platform. This plugin will generate an abstract type that corresponds to each of your GraphQL type definitions, as well as a module for each that contains "getters" for the field. For example, a schema like this:

type Post {
  title: String!
  content: String
}

type Query {
  posts: [Post!]!
}

...generates some code that looks like this:

type query = Js.Json.t;
type post;

module Query = {
  type t = query;
  let typename = "Query";
  let posts: field(t, array(post)) = getArray(~fieldName="posts", ~typename);
};

module Post = {
  type t = post;
  let typename = "Post";
  let title: field(t, string) = getString(~fieldName="title", ~typename);
  let content: field(t, option(string)) = getNullableString(~fieldName="title", ~typename);
};

Then, you'd take the JSON returned from your GraphQL client and use it like so:

let postTitle = response->Query.posts[0]->Post.title;
let postContent = response->Query.posts[1]->Post.content->Belt.Option.getExn;

Enums get typed using [@bs.deriving jsConverter].

Why not use graphql-ppx?

graphql-ppx is a pretty awesome library that performs compile-time transforms of your actual GraphQL queries to generate a type that's specific to that query. It's great for what it does, but it doesn't allow for shared types that get defined in one place and are shared across your codebase, as each query generates its own type (even if you're fetching the same underlying GraphQL types).

This plugin provides a 1:1 relationship between your GraphQL types and your Reason types. In a large codebase, this can be a lot easier to reason (pardon the pun) about.

Usage with reason-apollo

// TODO: Add example of how to use with reason-apollo ๐Ÿ˜‰

Conributing

Contributions are very welcome! At this point the library covers very basic GraphQL usage, but there are still some scenarios that aren't handled, including:

  • Interfaces
  • Unions
  • Input types (and re-encoding as JSON for variables, etc.)
  • Probably some other things I'm not even thinking of right now

Development workflow

I've set the repo up such that the tests are written in ReasonML against the generated types. The idea is that the test suite is testing not just the generated code but the ability of the code to actually parse some JSON and use it like you'd expect.

In the tester directory, you'll find a schema.graphql that's the basis for our tests. To add a new feature, amend the schema to include a new scenario. Then run tsc in watch mode:

$ yarn build:ts -watch

As you make changes to the schema and/or the .ts files, re-generate the Reason types by running:

$ yarn generate

Then you'll also want to have bsb running to tip you off to any issues with the generated output:

$ yarn build:re -w

Finally, you can add a test to CodegenTest.re for the scenario you're trying to cover. The tests follow a basic pattern of defining a fixture that represents the JSON returned from a GraphQL query, then parsing the JSON into Reason, accessing some data, and asserting that it's what we expect it to be.

graphql-codegen-reason's People

Contributors

dependabot[bot] avatar kgoggin avatar larvanitis avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

graphql-codegen-reason's Issues

Duplicate "graphql" modules cannot be used at the same time

Current Version of @graphql-codegen/cli does not work and will present the following on generating:

Found 1 error

  โœ– src/GraphQLTypes.re
    Error: Cannot use GraphQLDirective "@include" from another module or realm.

    Ensure that there is only one instance of "graphql" in the node_modules
    directory. If different versions of "graphql" are the dependencies of other
    relied on modules, use "resolutions" to ensure only one version is installed.

    https://yarnpkg.com/en/docs/selective-version-resolutions

    Duplicate "graphql" modules cannot be used at the same time since different
    versions may have different capabilities and behavior. The data from one
    version used in the function from another could produce confusing and
    spurious results.

It looks like version 1.5.0 of codegen now uses "graphql": "^15.5.0", which is resulting in this error.

`Node` type

I tried running your project against the swapi-graphql schema. The schema and output can be see here: https://github.com/idkjs/graphql-codegen-reason/tree/master/tester. Side note: Only way I could get this to run is to run it on your master repo and switching out the schema. Installing the codegen per the instructions did not work for me. Probably just to thick in the head to understand your readme, but none the less.

Is this a bug or not an intended use case? Thanks for the feedback.

Running the codegen produces the following error:

>>>> Finish compiling(exit: 1)
>>>> Start compiling
[1/1] Building tester/generated/GraphQLTypes-GqlToReasonTester.cmj

  We've found a bug for you!
  /Users/prisc_000/working/graphql-codegen-reason-fork/tester/generated/GraphQLTypes.re 664:29-32

  662 โ”‚   let vehicle: field(t, option(vehicle)) =
  663 โ”‚     getNullableField(~fieldName="vehicle", ~typename);
  664 โ”‚   let node: field(t, option(node)) =
  665 โ”‚     getNullableField(~fieldName="node", ~typename);
  666 โ”‚ };

  This type constructor's parameter, `node`, can't be found. Is it a typo?

>>>> Finish compiling(exit: 1)

Error Reformatting

Ran some random schemas to check it out. Great project, sir. Kept trying stuff until I got an error. Finally got one with this SpaceX schema

Steps:

  1. Generate the schema with npx fetch-graphql-schema https://yv004pqnq9.sse.codesandbox.io/graphql -o schema.graphql -r
schema: ./schema.graphql
generates:
  GraphQLTypes3.re:
    plugins:
      - reason-client
    config:
      scalars:
        "DateTime": "string"

Run: [master*]node_modules/.bin/gql-gen

Output.

server [master*]node_modules/.bin/gql-gen
  โœ” Parse configuration
  โฏ Generate outputs
    โฏ Generate GraphQLTypes3.re
      โœ” Load GraphQL schemas
      โœ” Load GraphQL documents
      โœ– Generate
        โ†’ 1685: <syntax error>


  Found 1 error

   โœ– GraphQLTypes3.re
    [object Object]

How do we render that object object so we can chase it down?

schema.graphql gist

Thanks. And thanks for sharing.

Update exceptions to be more meaningful

Currently if there's an issue with decoding the JSON, I'm Js.loging the problem and throwing a generic Not_found exception. It'd be better to have a specific exception that gets thrown with better error messages.

Provide an option for running refmt on the generated output

Currently the plugin isn't running refmt after generating the string, because it makes it harder to deal with any errors in the output.

This was helpful during development, but in most scenarios we probably want to make sure we actually format the code - we'll add an option to not run it for scenarios where it might be useful.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.