Crate juniper [] [src]

GraphQL

GraphQL is a data query language developed by Facebook intended to serve mobile and web application frontends. A server provides a schema, containing types and fields that applications can query. Queries are hierarchical, composable, and statically typed. Schemas are introspective, which lets clients statically verify their queries against a server without actually executing them.

This library provides data types and traits to expose Rust types in a GraphQL schema, as well as an optional integration into the Iron framework and Rocket. It tries to keep the number of dynamic operations to a minimum, and give you as the schema developer the control of the query execution path.

Juniper only depends on serde and serde_derive by default, making it lightweight and easy to drop into any project. If you enable any of the optional framework integrations, it will naturally depend on those frameworks too.

Exposing data types

The GraphQLType trait is the primary interface towards application developers. By deriving this trait, you can expose your types as either objects, enums, interfaces, unions, or scalars.

However, due to the dynamic nature of GraphQL's type system, deriving this trait manually is a bit tedious, especially in order to do it in a fully type safe manner. To help with this task, this library provides a couple of macros; the most common one being graphql_object!. Use this macro to expose your already existing object types as GraphQL objects:

#[macro_use] extern crate juniper;
use juniper::{Context, FieldResult};

struct User { id: String, name: String, friend_ids: Vec<String>  }
struct QueryRoot;
struct Database { users: HashMap<String, User> }

impl Context for Database {}

// GraphQL objects can access a "context object" during execution. Use this
// object to provide e.g. database access to the field accessors. This object
// must implement the `Context` trait. If you don't need a context, use the
// empty tuple `()` to indicate this.
//
// In this example, we use the Database struct as our context.
graphql_object!(User: Database |&self| {

    // Expose a simple field as a GraphQL string.
    field id() -> &String {
        &self.id
    }

    field name() -> &String {
        &self.name
    }

    // FieldResult<T> is an alias for Result<T, String> - simply return
    // a string from this method and it will be correctly inserted into
    // the execution response.
    field secret() -> FieldResult<&String> {
        Err("Can't touch this".to_owned())
    }

    // Field accessors can optionally take an "executor" as their first
    // argument. This object can help guide query execution and provides
    // access to the context instance.
    //
    // In this example, the context is used to convert the friend_ids array
    // into actual User objects.
    field friends(&executor) -> Vec<&User> {
        self.friend_ids.iter()
            .filter_map(|id| executor.context().users.get(id))
            .collect()
    }
});

// The context object is passed down to all referenced types - all your exposed
// types need to have the same context type.
graphql_object!(QueryRoot: Database |&self| {

    // Arguments work just like they do on functions.
    field user(&executor, id: String) -> Option<&User> {
        executor.context().users.get(&id)
    }
});

Adding per type, field, and argument documentation is possible directly from this macro. For more in-depth information on how to expose fields and types, see the graphql_object! macro.

Integrating with Iron

The most obvious usecase is to expose the GraphQL schema over an HTTP endpoint. To support this, the library provides optional and customizable handlers for both Iron and Rocket.

For example, continuing from the schema created above and using Iron to expose the schema on an HTTP endpoint supporting both GET and POST requests:

extern crate iron;

use iron::prelude::*;
use juniper::iron_handlers::GraphQLHandler;
use juniper::{Context, EmptyMutation};


// This function is executed for every request. Here, we would realistically
// provide a database connection or similar. For this example, we'll be
// creating the database from scratch.
fn context_factory(_: &mut Request) -> Database {
    Database {
        users: vec![
            ( "1000".to_owned(), User {
                id: "1000".to_owned(), name: "Robin".to_owned(),
                friend_ids: vec!["1001".to_owned()] } ),
            ( "1001".to_owned(), User {
                id: "1001".to_owned(), name: "Max".to_owned(),
                friend_ids: vec!["1000".to_owned()] } ),
        ].into_iter().collect()
    }
}

impl Context for Database {}

fn main() {
    // GraphQLHandler takes a context factory function, the root object,
    // and the mutation object. If we don't have any mutations to expose, we
    // can use the empty tuple () to indicate absence.
    let graphql_endpoint = GraphQLHandler::new(
        context_factory, QueryRoot, EmptyMutation::<Database>::new());

    // Start serving the schema at the root on port 8080.
    Iron::new(graphql_endpoint).http("localhost:8080").unwrap();
}

See the iron_handlers module and the GraphQLHandler documentation for more information on what request methods are supported. There's also a built-in GraphiQL handler included.

Modules

graphiql

Utility module to generate a GraphiQL interface

http

Utilities for building HTTP endpoints in a library-agnostic manner

iron_handlers

Optional handlers for the Iron framework. Requires the iron-handlers feature enabled.

meta

Types used to describe a GraphQL schema

parser

Query parser and language utilities

Macros

graphql_enum

Expose simple enums

graphql_input_object

Create an input object

graphql_interface

Expose GraphQL interfaces

graphql_object

Expose GraphQL objects

graphql_scalar

Expose GraphQL scalars

graphql_union

Expose GraphQL unions

jtry

Helper macro to produce FieldResults.

Structs

Arguments

Field argument container

EmptyMutation

Utility type to define read-only schemas

ExecutionError

Error type for errors that occur during query execution

Executor

Query execution engine

ID

An ID as defined by the GraphQL specification

Registry

A type registry used to build schemas

RootNode

Root query node of a schema

RuleError

Query validation error

Enums

GraphQLError

An error that prevented query execution

InputValue

A JSON-like value that can be passed into the query execution, either out-of-band, or in-band as default variable values. These are not constant and might contain variables.

Selection

Entry in a GraphQL selection set

Type

A type literal in the syntax tree

TypeKind

GraphQL type kind

Value

Serializable value returned from query and field execution.

Traits

Context

Marker trait for types that can act as context objects for GraphQL types.

FromContext

Conversion trait for context types

FromInputValue

Parse an unstructured input value into a Rust data type.

GraphQLType

Primary trait used to expose Rust types in a GraphQL schema

ResultExt

Helper trait to produce FieldResults

ToInputValue

Losslessly clones a Rust data type into an InputValue.

Functions

execute

Execute a query in a provided schema

Type Definitions

ExecutionResult

The result of resolving an unspecified field

FieldResult

The result of resolving the value of a field of type T

Variables

The map of variables used for substitution during query execution