GithubHelp home page GithubHelp logo

graphql's Introduction

GraphQL server framework in Rust

This framework lets you write type-safe, efficient GraphQL servers in Rust. We make heavy use of macros to cut down on boilerplate and the trait system to allow maximum flexibility.

This project is at 'proof of concept' stage. It can only handle minimal examples and some key components are missing. However, I believe the results are already promising - Rust and GraphQL are a great match!

In the future we should use Rusts emerging async IO systems to make extremely performant servers.

Example

Use the schema macro to specify the schema for your server (using IDL):

schema! {
    schema {
        query: Query,
    }

    type Query {
        hero(episode: Episode): Character,
        human(id : ID!): Human,
    }

    enum Episode {
        NEWHOPE,
        EMPIRE,
        JEDI,
    }

    interface Character {
        id: ID!,
        name: String!,
        friends: [Character],
        appearsIn: [Episode]!,
    }

    type Human implements Character {
        id: ID!,
        name: String!,
        friends: [Character],
        appearsIn: [Episode]!,
        homePlanet: String,
    }
}

You can see the output for this example use of the schema macro at schema.out.

The macro generates concrete and abstract versions of each item. The library user must specify implementations for functions (e.g., hero in the above schema). You can then use the generated types - enums are Rust enums, types are Rust structs, etc.:

TODO these are equivalent to resolvers in the JS frameworks

struct MyServer;

impl Root for MyServer {
    type Query = DbQuery;

    fn query(&self) -> QlResult<DbQuery> {
        Ok(DbQuery)
    }
}

ImplRoot!(MyServer);


struct DbQuery;

impl AbstractQuery for DbQuery {
    fn hero(&self, episode: Option<Episode>) -> QlResult<Option<Character>> {
        match episode {
            Some(Episode::JEDI) => {
                // In real life, this would query the DB or execute business logic.
                Ok(Some(Character {
                    id: Id("0".to_owned()),
                    name: "Luke".to_owned(),
                    friends: Some(vec![]),
                    appearsIn: vec![],
                }))
            }
            _ => unimplemented!(),
        }
    }

    fn human(&self, _id: Id) -> QlResult<Option<Human>> {
        ...
    }
}

If you don't want to use the generated representation for a certain item, you can provide your own (perhaps using a HashMap of data, rather than fields). You then implement the abstract view of the item (e.g., AbstractHuman for Human) and override the relevant associated type (e.g., type Human = MyHuman; in the implementations of Root and AbstractQuery, and anywhere else the type is used):

struct MyHuman {
    id: usize,
    db_table: DbTablePtr,
}

ImplHuman!(MyHuman);

impl AbstractHuman for MyHuman {
    fn resolve_field(&self, field: &query::Field) -> QlResult<result::Value> {
        ...
    }
}

TODO show main

graphql's People

Contributors

ahmedcharles avatar cybai avatar nrc avatar scrogson 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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

graphql's Issues

Client?

Is it worth writing a Rust GraphQL client? Should it be a separate project or part of this one?

Statically generate validation code

In theory, we don't need to reflect the schema and use that to dynamically validate each query. We could generate a query validator from the schema at compile-time. This would in theory be more efficient, but I'm not sure if it makes enough difference to warrant the complexity. It would be fun to find out, in any case.

issue in build

getting issue while building.

error[E0554]: #![feature] may not be used on the stable release channel
--> /Users/minacssybase/.cargo/registry/src/github.com-1ecc6299db9ec823/rls-span-0.4.0/src/lib.rs:12:1
|
12 | #![feature(proc_macro)]
| ^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

error: Could not compile rls-span.
warning: build failed, waiting for other jobs to finish...
error: build failed

Use graphql-parser for parser and AST

Hi,

I've just published graphq-parser crate. The idea is that it's just plain query language parser, that can be used for many things including this library.

It's based on quite good combine library for parsing, and has custom tokenizer/lexer. The library works quite well without macros. And the grammar of graphql is quite good so I could implement it with combinators being very close to what is written in spec. The performance is quite close to what juniper has with custom parser (it's hard to compare to this crate because this crate lacks features).

Comparing to implementation here the library implements all the graphql spec and includes line numbers for AST nodes.

It's still early in development so we may change few things to make it more useful for this crate and juniper. Also, it was weekend project so may have some edge cases not covered yet (but at least we can parse the kitchen sink example from graphql-js repo. IDL is not yet started, but looks like no bigger than another weekend project :)

Thoughts?

Flesh out example

Do some computation, rather than just magic the same values out of thin air.

Tracking issue: documentation

Including, but not limited to:

  • guide-style documentation for creating a server and using custom implementations of the types
  • step-by-step through an example (hello-world-like)
  • API docs
  • comments and module docs

Tracking issue: Rust issues

Currently aware of:

  • several macro hygiene issues
  • no way to get whitespace when we parse the body of schema
  • default associated types

Cache query validations

Currently just a true/false, but we might in the future cache some lowered version of the query to save some work

Example with HTTP server

Add a Hyper frontend around the trilogy example (useful for demonstrating the async resolvers work).

Share code with Juniper

Juniper is an alternate GraphQL server implementation. It has a very different approach to specifying the API, but I imagine we could share a bunch of the internals code.

cc @theduke

Tracking issue: test suite

We need a framework for running integration tests. Then we need some tests. Ideally we could use an already established suite of tests from another GraphQL server. Would be good to include benchmarking too.

Phases for query validation

Is it worth separating name resolution from type checking? I think it probably will be once we're checking more queries. There might be other phases too. Also worth thinking about the data we store information in.

tracking issue: error messages

There are lots of places where error mesasges are sub-optimal, e.g., missing information, or returning a single error when multiple errors happen, etc.

async resolvers

It would be nice if resolvers could be either sync or async, but I think that is not possible in Rust and they must always be async (at least type-wise). Note that although they execute asyncronously, resolvers in a mutation must not be parallelised.

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.