//! This library contains a procedural macro that reads a GraphQL schema file, and generates the
//! corresponding [Juniper](https://crates.io/crates/juniper) [macro calls]. This means you can
//! have a real schema file and be guaranteed that it matches your Rust implementation. It also
//! removes most of the boilerplate involved in using Juniper.
//!
//! [macro calls]: https://graphql-rust.github.io/types/objects/complex_fields.html
//!
//! # Table of contents
//!
//! - [Example](#example)
//! - [Example web app](#example-web-app)
//! - [GraphQL features](#graphql-features)
//! - [The `ID` type](#the-id-type)
//! - [Custom scalar types](#custom-scalar-types)
//! - [Special case scalars](#special-case-scalars)
//! - [Interfaces](#interfaces)
//! - [Union types](#union-types)
//! - [Input objects](#input-objects)
//! - [Enumeration types](#enumeration-types)
//! - [Default argument values](#default-argument-values)
//! - [Supported schema directives](#supported-schema-directives)
//! - [Definition for `@juniper`](#definition-for-juniper)
//! - [Customizing ownership](#customizing-ownership)
//! - [Infallible fields](#infallible-fields)
//! - [GraphQL to Rust types](#graphql-to-rust-types)
//! - [Query trails](#query-trails)
//! - [Abbreviated example](#abbreviated-example)
//! - [Types](#types)
//! - [Downcasting for interface and union `QueryTrail`s](#downcasting-for-interface-and-union-querytrails)
//! - [`QueryTrail`s for fields that take arguments](#querytrails-for-fields-that-take-arguments)
//! - [Customizing the error type](#customizing-the-error-type)
//! - [Customizing the context type](#customizing-the-context-type)
//! - [Inspecting the generated code](#inspecting-the-generated-code)
//!
//! # Example
//!
//! Schema:
//!
//! ```graphql
//! schema {
//! query: Query
//! mutation: Mutation
//! }
//!
//! type Query {
//! // The directive makes the return value `FieldResult<String>`
//! // rather than the default `FieldResult<&String>`
//! helloWorld(name: String!): String! @juniper(ownership: "owned")
//! }
//!
//! type Mutation {
//! noop: Boolean!
//! }
//! ```
//!
//! How you could implement that schema:
//!
//! ```
//! #[macro_use]
//! extern crate juniper;
//!
//! use juniper_from_schema::graphql_schema_from_file;
//!
//! // This is the important line
//! graphql_schema_from_file!("tests/schemas/doc_schema.graphql");
//!
//! pub struct Context;
//! impl juniper::Context for Context {}
//!
//! pub struct Query;
//!
//! impl QueryFields for Query {
//! fn field_hello_world(
//! &self,
//! executor: &juniper::Executor<'_, Context>,
//! name: String,
//! ) -> juniper::FieldResult<String> {
//! Ok(format!("Hello, {}!", name))
//! }
//! }
//!
//! pub struct Mutation;
//!
//! impl MutationFields for Mutation {
//! fn field_noop(&self, executor: &juniper::Executor<'_, Context>) -> juniper::FieldResult<&bool> {
//! Ok(&true)
//! }
//! }
//!
//! fn main() {
//! let ctx = Context;
//!
//! let query = "query { helloWorld(name: \"Ferris\") }";
//!
//! let (result, errors) = juniper::execute(
//! query,
//! None,
//! &Schema::new(Query, Mutation),
//! &juniper::Variables::new(),
//! &ctx,
//! )
//! .unwrap();
//!
//! assert_eq!(errors.len(), 0);
//! assert_eq!(
//! result
//! .as_object_value()
//! .unwrap()
//! .get_field_value("helloWorld")
//! .unwrap()
//! .as_scalar_value::<String>()
//! .unwrap(),
//! "Hello, Ferris!",
//! );
//! }
//! ```
//!
//! And with `graphql_schema_from_file!` expanded your code would look something like this:
//!
//! ```
//! #[macro_use]
//! extern crate juniper;
//!
//! pub struct Context;
//! impl juniper::Context for Context {}
//!
//! pub struct Query;
//!
//! juniper::graphql_object!(Query: Context |&self| {
//! field hello_world(&executor, name: String) -> juniper::FieldResult<String> {
//! <Self as QueryFields>::field_hello_world(&self, &executor, name)
//! }
//! });
//!
//! trait QueryFields {
//! fn field_hello_world(
//! &self,
//! executor: &juniper::Executor<'_, Context>,
//! name: String,
//! ) -> juniper::FieldResult<String>;
//! }
//!
//! impl QueryFields for Query {
//! fn field_hello_world(
//! &self,
//! executor: &juniper::Executor<'_, Context>,
//! name: String,
//! ) -> juniper::FieldResult<String> {
//! Ok(format!("Hello, {}!", name))
//! }
//! }
//!
//! pub struct Mutation;
//!
//! juniper::graphql_object!(Mutation: Context |&self| {
//! field noop(&executor) -> juniper::FieldResult<&bool> {
//! <Self as MutationFields>::field_noop(&self, &executor)
//! }
//! });
//!
//! trait MutationFields {
//! fn field_noop(&self, executor: &juniper::Executor<'_, Context>) -> juniper::FieldResult<&bool>;
//! }
//!
//! impl MutationFields for Mutation {
//! fn field_noop(&self, executor: &juniper::Executor<'_, Context>) -> juniper::FieldResult<&bool> {
//! Ok(&true)
//! }
//! }
//!
//! type Schema = juniper::RootNode<'static, Query, Mutation>;
//!
//! fn main() {
//! let ctx = Context;
//!
//! let query = "query { helloWorld(name: \"Ferris\") }";
//!
//! let (result, errors) = juniper::execute(
//! query,
//! None,
//! &Schema::new(Query, Mutation),
//! &juniper::Variables::new(),
//! &ctx,
//! )
//! .unwrap();
//!
//! assert_eq!(errors.len(), 0);
//! assert_eq!(
//! result
//! .as_object_value()
//! .unwrap()
//! .get_field_value("helloWorld")
//! .unwrap()
//! .as_scalar_value::<String>()
//! .unwrap(),
//! "Hello, Ferris!",
//! );
//! }
//! ```
//!
//! # Example web app
//!
//! You can find an example of how to use this library together with [Rocket] and [Diesel] to make
//! a GraphQL web app at <https://github.com/davidpdrsn/graphql-app-example> or an example of how
//! to use this library with [Actix] and [Diesel] at
//! <https://github.com/husseinraoouf/graphql-actix-example>.
//!
//! [Rocket]: https://rocket.rs
//! [Diesel]: http://diesel.rs
//! [Actix]: https://actix.rs/
//!
//! # GraphQL features
//!
//! The goal of this library is to support as much of GraphQL as Juniper does.
//!
//! Here is the complete list of features:
//!
//! Supported:
//! - Object types including converting lists and non-nulls to Rust types
//! - Custom scalar types including the `ID` type
//! - Interfaces
//! - Unions
//! - Input objects
//! - Enumeration types
//!
//! Not supported yet:
//! - Subscriptions (will be supported once Juniper supports subscriptions)
//! - Type extensions
//!
//! ## The `ID` type
//!
//! The `ID` GraphQL type will be generated into [`juniper::ID`].
//!
//! [`juniper::ID`]: https://docs.rs/juniper/latest/juniper/struct.ID.html
//!
//! ## Custom scalar types
//!
//! Custom scalar types will be generated into a newtype wrapper around a `String`. For example:
//!
//! ```graphql
//! scalar Cursor
//! ```
//!
//! Would result in
//!
//! ```
//! pub struct Cursor(pub String);
//! ```
//!
//! ## Special case scalars
//!
//! A couple of scalar names have special meaning. Those are:
//!
//! - `Url` becomes
//! [`url::Url`](https://docs.rs/url/2.1.0/url/struct.Url.html).
//! - `Uuid` becomes
//! [`uuid::Uuid`](https://docs.rs/uuid/0.7.4/uuid/struct.Uuid.html).
//! - `Date` becomes
//! [`chrono::naive::NaiveDate`](https://docs.rs/chrono/0.4.6/chrono/naive/struct.NaiveDate.html).
//! - `DateTimeUtc` becomes [`chrono::DateTime<chrono::offset::Utc>`] by default but if defined with
//! `scalar DateTimeUtc @juniper(with_time_zone: false)` it will become [`chrono::naive::NaiveDateTime`].
//!
//! Juniper doesn't support [`chrono::Date`](https://docs.rs/chrono/0.4.9/chrono/struct.Date.html)
//! so therefore this library cannot support that either. You can read about Juniper's supported
//! integrations [here](https://docs.rs/juniper/0.13.1/juniper/integrations/index.html).
//!
//! [`chrono::DateTime<chrono::offset::Utc>`]: https://docs.rs/chrono/0.4.9/chrono/struct.DateTime.html
//! [`chrono::naive::NaiveDateTime`]: https://docs.rs/chrono/0.4.9/chrono/naive/struct.NaiveDateTime.html
//!
//! ## Interfaces
//!
//! Juniper has several ways of representing GraphQL interfaces in Rust. They are listed
//! [here](https://graphql-rust.github.io/types/interfaces.html#enums) along with their advantages
//! and disadvantages.
//!
//! For the generated code we use the `enum` pattern because we found it to be the most flexible.
//!
//! Abbreviated example (find [complete example here](https://github.com/davidpdrsn/juniper-from-schema/blob/master/examples/interface.rs)):
//!
//! ```
//! # #[macro_use]
//! # extern crate juniper;
//! # use juniper::*;
//! # use juniper_from_schema::graphql_schema;
//! # fn main() {}
//! # pub struct Context;
//! # impl juniper::Context for Context {}
//! # pub struct Article { id: ID, text: String }
//! # impl ArticleFields for Article {
//! # fn field_id(
//! # &self,
//! # executor: &Executor<'_, Context>,
//! # ) -> FieldResult<&ID> { unimplemented!() }
//! # fn field_text(
//! # &self,
//! # executor: &Executor<'_, Context>,
//! # ) -> FieldResult<&String> { unimplemented!() }
//! # }
//! # pub struct Tweet { id: ID, text: String }
//! # impl TweetFields for Tweet {
//! # fn field_id(
//! # &self,
//! # executor: &Executor<'_, Context>,
//! # ) -> FieldResult<&ID> { unimplemented!() }
//! # fn field_text(
//! # &self,
//! # executor: &Executor<'_, Context>,
//! # ) -> FieldResult<&String> { unimplemented!() }
//! # }
//! #
//! graphql_schema! {
//! schema {
//! query: Query
//! }
//!
//! type Query {
//! search(query: String!): [SearchResult!]! @juniper(ownership: "owned")
//! }
//!
//! interface SearchResult {
//! id: ID!
//! text: String!
//! }
//!
//! type Article implements SearchResult {
//! id: ID!
//! text: String!
//! }
//!
//! type Tweet implements SearchResult {
//! id: ID!
//! text: String!
//! }
//! }
//!
//! pub struct Query;
//!
//! impl QueryFields for Query {
//! fn field_search(
//! &self,
//! executor: &Executor<'_, Context>,
//! trail: &QueryTrail<'_, SearchResult, juniper_from_schema::Walked>,
//! query: String,
//! ) -> FieldResult<Vec<SearchResult>> {
//! let article: Article = Article { id: ID::new("1"), text: "Business".to_string() };
//! let tweet: Tweet = Tweet { id: ID::new("2"), text: "1 weird tip".to_string() };
//!
//! let posts = vec![
//! SearchResult::from(article),
//! SearchResult::from(tweet),
//! ];
//!
//! Ok(posts)
//! }
//! }
//! ```
//!
//! The enum that gets generated has variants for each type that implements the interface and also
//! implements `From<T>` for each type.
//!
//! ## Union types
//!
//! Union types are basically just interfaces so they work in very much the same way.
//!
//! Abbreviated example (find [complete example here](https://github.com/davidpdrsn/juniper-from-schema/blob/master/examples/union_types.rs)):
//!
//! ```
//! # #[macro_use]
//! # extern crate juniper;
//! # use juniper::*;
//! # use juniper_from_schema::graphql_schema;
//! # fn main() {}
//! # pub struct Context;
//! # impl juniper::Context for Context {}
//! # pub struct Article { id: ID, text: String }
//! # impl ArticleFields for Article {
//! # fn field_id(
//! # &self,
//! # executor: &Executor<'_, Context>,
//! # ) -> FieldResult<&ID> { unimplemented!() }
//! # fn field_text(
//! # &self,
//! # executor: &Executor<'_, Context>,
//! # ) -> FieldResult<&String> { unimplemented!() }
//! # }
//! # pub struct Tweet { id: ID, text: String }
//! # impl TweetFields for Tweet {
//! # fn field_id(
//! # &self,
//! # executor: &Executor<'_, Context>,
//! # ) -> FieldResult<&ID> { unimplemented!() }
//! # fn field_text(
//! # &self,
//! # executor: &Executor<'_, Context>,
//! # ) -> FieldResult<&String> { unimplemented!() }
//! # }
//! #
//! graphql_schema! {
//! schema {
//! query: Query
//! }
//!
//! type Query {
//! search(query: String!): [SearchResult!]! @juniper(ownership: "owned")
//! }
//!
//! union SearchResult = Article | Tweet
//!
//! type Article {
//! id: ID!
//! text: String!
//! }
//!
//! type Tweet {
//! id: ID!
//! text: String!
//! }
//! }
//!
//! pub struct Query;
//!
//! impl QueryFields for Query {
//! fn field_search(
//! &self,
//! executor: &Executor<'_, Context>,
//! trail: &QueryTrail<'_, SearchResult, juniper_from_schema::Walked>,
//! query: String,
//! ) -> FieldResult<Vec<SearchResult>> {
//! let article: Article = Article { id: ID::new("1"), text: "Business".to_string() };
//! let tweet: Tweet = Tweet { id: ID::new("2"), text: "1 weird tip".to_string() };
//!
//! let posts = vec![
//! SearchResult::from(article),
//! SearchResult::from(tweet),
//! ];
//!
//! Ok(posts)
//! }
//! }
//! ```
//!
//! ## Input objects
//!
//! Input objects will be converted into Rust structs with public fields.
//!
//! Abbreviated example (find [complete example here](https://github.com/davidpdrsn/juniper-from-schema/blob/master/examples/input_types.rs)):
//!
//! ```
//! # #[macro_use]
//! # extern crate juniper;
//! # use juniper::*;
//! # use juniper_from_schema::graphql_schema;
//! # fn main() {}
//! # pub struct Context;
//! # impl juniper::Context for Context {}
//! # pub struct Post { id: ID }
//! # impl PostFields for Post {
//! # fn field_id(
//! # &self,
//! # executor: &Executor<'_, Context>,
//! # ) -> FieldResult<&ID> {
//! # unimplemented!()
//! # }
//! # fn field_title(
//! # &self,
//! # executor: &Executor<'_, Context>,
//! # ) -> FieldResult<&String> {
//! # unimplemented!()
//! # }
//! # }
//! # pub struct Query;
//! # impl QueryFields for Query {
//! # fn field_noop(
//! # &self,
//! # executor: &Executor<'_, Context>,
//! # ) -> FieldResult<&bool> {
//! # unimplemented!()
//! # }
//! # }
//! graphql_schema! {
//! schema {
//! query: Query
//! mutation: Mutation
//! }
//!
//! type Mutation {
//! createPost(input: CreatePost!): Post @juniper(ownership: "owned")
//! }
//!
//! input CreatePost {
//! title: String!
//! }
//!
//! type Post {
//! id: ID!
//! title: String!
//! }
//!
//! type Query { noop: Boolean! }
//! }
//!
//! pub struct Mutation;
//!
//! impl MutationFields for Mutation {
//! fn field_create_post(
//! &self,
//! executor: &Executor<'_, Context>,
//! trail: &QueryTrail<'_, Post, juniper_from_schema::Walked>,
//! input: CreatePost,
//! ) -> FieldResult<Option<Post>> {
//! let title: String = input.title;
//!
//! unimplemented!()
//! }
//! }
//! ```
//!
//! From that example `CreatePost` will be defined as
//!
//! ```
//! pub struct CreatePost {
//! pub title: String,
//! }
//! ```
//!
//! ## Enumeration types
//!
//! GraphQL enumeration types will be converted into normal Rust enums. The name of each variant
//! will be camel cased.
//!
//! Abbreviated example (find [complete example here](https://github.com/davidpdrsn/juniper-from-schema/blob/master/examples/enumeration_types.rs)):
//!
//! ```
//! # #[macro_use]
//! # extern crate juniper;
//! # use juniper::*;
//! # use juniper_from_schema::graphql_schema;
//! # fn main() {}
//! # pub struct Context;
//! # impl juniper::Context for Context {}
//! # pub struct Post { id: ID }
//! # impl PostFields for Post {
//! # fn field_id(
//! # &self,
//! # executor: &Executor<'_, Context>,
//! # ) -> FieldResult<&ID> {
//! # Ok(&self.id)
//! # }
//! # }
//! #
//! graphql_schema! {
//! schema {
//! query: Query
//! }
//!
//! enum Status {
//! PUBLISHED
//! UNPUBLISHED
//! }
//!
//! type Query {
//! allPosts(status: Status!): [Post!]! @juniper(ownership: "owned")
//! }
//!
//! type Post {
//! id: ID!
//! }
//! }
//!
//! pub struct Query;
//!
//! impl QueryFields for Query {
//! fn field_all_posts(
//! &self,
//! executor: &Executor<'_, Context>,
//! trail: &QueryTrail<'_, Post, juniper_from_schema::Walked>,
//! status: Status,
//! ) -> FieldResult<Vec<Post>> {
//! match status {
//! Status::Published => unimplemented!("find published posts"),
//! Status::Unpublished => unimplemented!("find unpublished posts"),
//! }
//! }
//! }
//! ```
//!
//! ## Default argument values
//!
//! In GraphQL you are able to provide default values for field arguments, provided the argument is
//! nullable.
//!
//! Arguments of the following types support default values:
//! - `Float`
//! - `Int`
//! - `String`
//! - `Boolean`
//! - Enumerations
//! - Input objects (as field arguments, see below)
//! - Lists containing some other supported type
//!
//! Abbreviated example (find [complete example here](https://github.com/davidpdrsn/juniper-from-schema/blob/master/examples/default_argument_values.rs)):
//!
//! ```
//! # #[macro_use]
//! # extern crate juniper;
//! # use juniper::*;
//! # use juniper_from_schema::graphql_schema;
//! # fn main() {}
//! # pub struct Context;
//! # impl juniper::Context for Context {}
//! # pub struct Post { id: ID }
//! # impl PostFields for Post {
//! # fn field_id(
//! # &self,
//! # executor: &Executor<'_, Context>,
//! # ) -> FieldResult<&ID> {
//! # Ok(&self.id)
//! # }
//! # }
//! #
//! graphql_schema! {
//! schema {
//! query: Query
//! }
//!
//! enum Status {
//! PUBLISHED
//! UNPUBLISHED
//! }
//!
//! input Pagination {
//! pageSize: Int!
//! cursor: ID
//! }
//!
//! type Query {
//! allPosts(
//! status: Status = PUBLISHED,
//! pagination: Pagination = { pageSize: 20 }
//! ): [Post!]! @juniper(ownership: "owned")
//! }
//!
//! type Post {
//! id: ID!
//! }
//! }
//!
//! pub struct Query;
//!
//! impl QueryFields for Query {
//! fn field_all_posts(
//! &self,
//! executor: &Executor<'_, Context>,
//! trail: &QueryTrail<'_, Post, juniper_from_schema::Walked>,
//! status: Status,
//! pagination: Pagination,
//! ) -> FieldResult<Vec<Post>> {
//! // `status` will be `Status::Published` if not given in the query
//!
//! match status {
//! Status::Published => unimplemented!("find published posts"),
//! Status::Unpublished => unimplemented!("find unpublished posts"),
//! }
//! }
//! }
//! ```
//!
//! ### Input object gotchas
//!
//! Defaults for input objects are only supported as field arguments. The following is not
//! supported
//!
//! ```graphql
//! input SomeType {
//! field: Int = 1
//! }
//! ```
//!
//! This isn't supported because [the spec is unclear about how to handle multiple nested
//! defaults](https://github.com/webonyx/graphql-php/issues/350).
//!
//! Also, defaults are only used if no arguments are passed. So given the schema
//!
//! ```graphql
//! input Input {
//! a: String
//! b: String
//! }
//!
//! type Query {
//! field(arg: Input = { a: "a" }): Int!
//! }
//! ```
//!
//! and the query
//!
//! ```graphql
//! query MyQuery {
//! field(arg: { b: "my b" })
//! }
//! ```
//!
//! The value of `arg` inside the resolver would be `Input { a: None, b: Some("my b") }`. Note that
//! even though `a` has a default value in the field doesn't get used here because we set `arg` in
//! the query.
//!
//! # Supported schema directives
//!
//! A number of [schema directives][] are supported that lets you customize the generated code:
//!
//! - `@juniper(ownership: "owned|borrowed|as_ref")`. For customizing ownership of returned data.
//! More info [here](#customizing-ownership).
//! - `@juniper(infallible: true|false)`. Customize if a field should return `Result<T, _>` or
//! just `T`. More info
//! [here](http://localhost:4000/juniper_from_schema/index.html#infallible-fields).
//! - `@deprecated`. For deprecating types in your schema. Also supports supplying a reason with
//! `@deprecated(reason: "...")`
//!
//! [schema directives]: https://www.apollographql.com/docs/apollo-server/schema/directives/
//!
//! ## Definition for `@juniper`
//!
//! Some tools that operate on your GraphQL schema require you to include the definition for all
//! directives used. So in case you need it the definition for `@juniper` is:
//!
//! ```graphql
//! directive @juniper(
//! ownership: String = "borrowed",
//! infallible: Boolean = false,
//! with_time_zone: Boolean = true
//! ) on FIELD_DEFINITION
//! ```
//!
//! This directive definition is allowed in your schema, as well as any other directive definition.
//! Definitions of `@juniper` that differ from this are not allowed though.
//!
//! The definition might change in future versions. Please refer to the [changelog][].
//!
//! juniper-from-schema doesn't require to put this in your schema, so you only need to include it
//! if some other tool requires it.
//!
//! [changelog]: https://github.com/davidpdrsn/juniper-from-schema/blob/master/CHANGELOG.md
//!
//! ## Customizing ownership
//!
//! By default all fields return borrowed values. Specifically the type is
//! `juniper::FieldResult<&'a T>` where `'a` is the lifetime of `self`. This works well for
//! returning data owned by `self` and avoids needless `.clone()` calls you would need if fields
//! returned owned values.
//!
//! However if you need to change the ownership you have to add the directive
//! `@juniper(ownership:)` to the field in the schema.
//!
//! It takes the following arguments:
//!
//! - `@juniper(ownership: "borrowed")`: The data returned will be borrowed from `self`
//! (`FieldResult<&T>`).
//! - `@juniper(ownership: "owned")`: The return type will be owned (`FieldResult<T>`).
//! - `@juniper(ownership: "as_ref")`: Only applicable for `Option` and `Vec` return types. Changes
//! the inner type to be borrowed (`FieldResult<Option<&T>>` or `FieldResult<Vec<&T>>`).
//!
//! Example:
//!
//! ```
//! # #[macro_use]
//! # extern crate juniper;
//! # use juniper_from_schema::*;
//! # use juniper::*;
//! # pub struct Context;
//! # impl juniper::Context for Context {}
//! # fn main() {}
//! graphql_schema! {
//! schema {
//! query: Query
//! }
//!
//! type Query {
//! borrowed: String!
//! owned: String! @juniper(ownership: "owned")
//! asRef: String @juniper(ownership: "as_ref")
//! }
//! }
//!
//! pub struct Query;
//!
//! impl QueryFields for Query {
//! fn field_borrowed(&self, _: &Executor<'_, Context>) -> FieldResult<&String> {
//! // ...
//! # unimplemented!()
//! }
//!
//! fn field_owned(&self, _: &Executor<'_, Context>) -> FieldResult<String> {
//! // ...
//! # unimplemented!()
//! }
//!
//! fn field_as_ref(&self, _: &Executor<'_, Context>) -> FieldResult<Option<&String>> {
//! // ...
//! # unimplemented!()
//! }
//! }
//! ```
//!
//! All field arguments will be owned.
//!
//! ## Infallible fields
//!
//! By default the generated resolvers are fallible, meaining they return a `Result<T, _>` rather
//! than a bare `T`. You can customize that using `@juniper(infallible: true)`.
//!
//! Example:
//!
//! ```
//! # #[macro_use]
//! # extern crate juniper;
//! # use juniper_from_schema::*;
//! # use juniper::*;
//! # pub struct Context;
//! # impl juniper::Context for Context {}
//! # fn main() {}
//! graphql_schema! {
//! schema {
//! query: Query
//! }
//!
//! type Query {
//! canError: String!
//! cannotError: String! @juniper(infallible: true)
//! cannotErrorAndOwned: String! @juniper(infallible: true, ownership: "owned")
//! }
//! }
//!
//! pub struct Query;
//!
//! impl QueryFields for Query {
//! fn field_can_error(&self, _: &Executor<'_, Context>) -> FieldResult<&String> {
//! // ...
//! # unimplemented!()
//! }
//!
//! fn field_cannot_error(&self, _: &Executor<'_, Context>) -> &String {
//! // ...
//! # unimplemented!()
//! }
//!
//! fn field_cannot_error_and_owned(&self, _: &Executor<'_, Context>) -> String {
//! // ...
//! # unimplemented!()
//! }
//! }
//! ```
//!
//! # GraphQL to Rust types
//!
//! This is how the standard GraphQL types will be mapped to Rust:
//!
//! - `Int` -> `i32`
//! - `Float` -> `f64`
//! - `String` -> `String`
//! - `Boolean` -> `bool`
//! - `ID` -> [`juniper::ID`](https://docs.rs/juniper/latest/juniper/struct.ID.html)
//!
//! # Query trails
//!
//! If you're not careful about preloading associations for deeply nested queries you risk getting
//! lots of [N+1 query bugs][]. Juniper provides a [look ahead API][] which lets you inspect things
//! coming up further down a query. However the API is string based, so you risk making typos and
//! checking for fields that don't exist.
//!
//! `QueryTrail` is a thin wrapper around Juniper look aheads with generated methods for each field
//! on all your types. This means the compiler will reject your code if you're checking for invalid
//! fields.
//!
//! Resolver methods (`field_*`) that return object types (non scalar values) will also get a
//! `QueryTrail` argument besides the executor.
//!
//! Since the `QueryTrail` type itself is defined in this crate (rather than being inserted into
//! your code) we cannot directly add methods for your GraphQL fields. Those methods have to be
//! added through ["extension traits"](http://xion.io/post/code/rust-extension-traits.html). So if
//! you see an error like
//!
//! ```text
//! | trail.foo();
//! | ^^^ method not found in `&juniper_from_schema::QueryTrail<'a, User, juniper_from_schema::Walked>`
//! |
//! = help: items from traits can only be used if the trait is in scope
//! help: the following trait is implemented but not in scope, perhaps add a `use` for it:
//! |
//! 2 | use crate::graphql_schema::query_trails::QueryTrailUserExtensions;
//! |
//! ```
//!
//! Then adding `use crate::graphql_schema::query_trails::*` to you module should fix it. This is
//! necessary because all the extention traits are generated inside a module called `query_trails`.
//! This is done so you can glob import the `QueryTrail` extension traits without glob importing
//! everything from your GraphQL schema.
//!
//! If you just want everything from the schema `use crate::graphql_schema::*` will also bring in
//! the extension traits.
//!
//! [N+1 query bugs]: https://secure.phabricator.com/book/phabcontrib/article/n_plus_one/
//! [look ahead API]: https://docs.rs/juniper/0.11.1/juniper/struct.LookAheadSelection.html
//!
//! ## Abbreviated example
//!
//! Find [complete example here](https://github.com/davidpdrsn/juniper-from-schema/blob/master/examples/query_trails.rs)
//!
//! ```
//! # #[macro_use]
//! # extern crate juniper;
//! # use juniper::*;
//! # use juniper_from_schema::graphql_schema;
//! # fn main() {}
//! # pub struct Context;
//! # impl juniper::Context for Context {}
//! #
//! graphql_schema! {
//! schema {
//! query: Query
//! }
//!
//! type Query {
//! allPosts: [Post!]! @juniper(ownership: "owned")
//! }
//!
//! type Post {
//! id: Int!
//! author: User!
//! }
//!
//! type User {
//! id: Int!
//! }
//! }
//!
//! pub struct Query;
//!
//! impl QueryFields for Query {
//! fn field_all_posts(
//! &self,
//! executor: &Executor<'_, Context>,
//! trail: &QueryTrail<'_, Post, juniper_from_schema::Walked>,
//! ) -> FieldResult<Vec<Post>> {
//! // Check if the query includes the author
//! if let Some(_) = trail.author().walk() {
//! // Somehow preload the users to avoid N+1 query bugs
//! // Exactly how to do this depends on your setup
//! }
//!
//! // Normally this would come from the database
//! let post = Post {
//! id: 1,
//! author: User { id: 1 },
//! };
//!
//! Ok(vec![post])
//! }
//! }
//!
//! pub struct Post {
//! id: i32,
//! author: User,
//! }
//!
//! impl PostFields for Post {
//! fn field_id(&self, executor: &Executor<'_, Context>) -> FieldResult<&i32> {
//! Ok(&self.id)
//! }
//!
//! fn field_author(
//! &self,
//! executor: &Executor<'_, Context>,
//! trail: &QueryTrail<'_, User, juniper_from_schema::Walked>,
//! ) -> FieldResult<&User> {
//! Ok(&self.author)
//! }
//! }
//!
//! pub struct User {
//! id: i32,
//! }
//!
//! impl UserFields for User {
//! fn field_id(
//! &self,
//! executor: &Executor<'_, Context>,
//! ) -> FieldResult<&i32> {
//! Ok(&self.id)
//! }
//! }
//! ```
//!
//! ## Types
//!
//! A query trail has two generic parameters: `QueryTrail<'a, T, K>`. `T` is the type the current
//! field returns and `K` is either `Walked` or `NotWalked`.
//!
//! The lifetime `'a` comes from Juniper and is the lifetime of the incoming query.
//!
//! ### `T`
//!
//! The `T` allows us to implement different methods for different types. For example in the
//! example above we implement `id` and `author` for `QueryTrail<'_, Post, K>` but only `id` for
//! `QueryTrail<'_, User, K>`.
//!
//! If your field returns a `Vec<T>` or `Option<T>` the given query trail will be `QueryTrail<'_,
//! T, _>`. So `Vec` or `Option` will be removed and you'll only be given the inner most type.
//! That is because in the GraphQL query syntax it doesn't matter if you're querying a `User`
//! or `[User]`. The fields you have access to are the same.
//!
//! ### `K`
//!
//! The `Walked` and `NotWalked` types are used to check if a given trail has been checked to
//! actually be part of a query. Calling any method on a `QueryTrail<'_, T, K>` will return
//! `QueryTrail<'_, T, NotWalked>`, and to check if the trail is actually part of the query you have
//! to call `.walk()` which returns `Option<QueryTrail<'_, T, Walked>>`. If that is a `Some(_)`
//! you'll know the trail is part of the query and you can do whatever preloading is necessary.
//!
//! Example:
//!
//! ```ignore
//! if let Some(walked_trail) = trail
//! .some_field()
//! .some_other_field()
//! .third_field()
//! .walk()
//! {
//! // preload stuff
//! }
//! ```
//!
//! You can always run `cargo doc` and inspect all the methods on `QueryTrail` and in which
//! contexts you can call them.
//!
//! ## Downcasting for interface and union `QueryTrail`s
//!
//! _This section is mostly relevant if you're using
//! [juniper-eager-loading](https://crates.io/crates/juniper-eager-loading) however it isn't
//! specific to that library._
//!
//! If you have a `QueryTrail<'a, T, Walked>` where `T` is an interface or union type you can use
//! `.downcast()` to convert that `QueryTrail` into one of the implementors of the interface or
//! union.
//!
//! Example:
//!
//! ```
//! # #[macro_use]
//! # extern crate juniper;
//! # use juniper::*;
//! # use juniper_from_schema::graphql_schema;
//! # fn main() {}
//! # pub struct Context;
//! # impl juniper::Context for Context {}
//! # pub struct Article { id: ID }
//! # impl ArticleFields for Article {
//! # fn field_id(
//! # &self,
//! # executor: &Executor<'_, Context>,
//! # ) -> FieldResult<&ID> { unimplemented!() }
//! # }
//! # pub struct Tweet { id: ID, text: String }
//! # impl TweetFields for Tweet {
//! # fn field_id(
//! # &self,
//! # executor: &Executor<'_, Context>,
//! # ) -> FieldResult<&ID> { unimplemented!() }
//! # }
//! #
//! graphql_schema! {
//! schema {
//! query: Query
//! }
//!
//! type Query {
//! search(query: String!): [SearchResult!]!
//! }
//!
//! interface SearchResult {
//! id: ID!
//! }
//!
//! type Article implements SearchResult {
//! id: ID!
//! }
//!
//! type Tweet implements SearchResult {
//! id: ID!
//! }
//! }
//!
//! pub struct Query;
//!
//! impl QueryFields for Query {
//! fn field_search(
//! &self,
//! executor: &Executor<'_, Context>,
//! trail: &QueryTrail<'_, SearchResult, juniper_from_schema::Walked>,
//! query: String,
//! ) -> FieldResult<&Vec<SearchResult>> {
//! let article_trail: QueryTrail<'_, Article, Walked> = trail.downcast();
//! let tweet_trail: QueryTrail<'_, Tweet, Walked> = trail.downcast();
//!
//! // ...
//! # unimplemented!()
//! }
//! }
//! ```
//!
//! ### Why is this useful?
//!
//! If you were do perform some kind of preloading of data you might have a function that inspects
//! a `QueryTrail` and loads the necessary data from a database. Such a function could look like
//! this:
//!
//! ```ignore
//! fn preload_users(
//! mut users: Vec<User>,
//! query_trail: &QueryTrail<'_, User, Walked>,
//! db: &Database,
//! ) -> Vec<User> {
//! // ...
//! }
//! ```
//!
//! This function works well when we have field that returns `[User!]!`. That field is going to get
//! a `QueryTrail<'a, User, Walked>` which is exactly what `preload_users` needs.
//!
//! However, now imagine you have a schema like this:
//!
//! ```graphql
//! type Query {
//! search(query: String!): [SearchResult!]!
//! }
//!
//! union SearchResult = User | City | Country
//!
//! type User {
//! id: ID!
//! city: City!
//! }
//!
//! type City {
//! id: ID!
//! country: Country!
//! }
//!
//! type Country {
//! id: ID!
//! }
//! ```
//!
//! The method `QueryFields::field_search` will receive a `QueryTrail<'a, SearchResult, Walked>`.
//! That type doesn't work with `preload_users`. So we have to convert our `QueryTrail<'a,
//! SearchResult, Walked>` into `QueryTrail<'a, User, Walked>`.
//!
//! This can be done by calling `.downcast()` which automatically gets implemented for interface and
//! union query trails. See above for an example.
//!
//! ## `QueryTrail`s for fields that take arguments
//!
//! Sometimes you have GraphQL fields that take arguments that impact which things your resolvers
//! should return. `QueryTrail` therefore also allows you inspect arguments to fields.
//!
//! Abbreviated example:
//!
//! ```
//! # #[macro_use]
//! # extern crate juniper;
//! # use juniper_from_schema::*;
//! # pub struct Context;
//! # impl juniper::Context for Context {}
//! # fn main() {}
//! # pub struct Country {}
//! # impl CountryFields for Country {
//! # fn field_users<'a>(
//! # &self,
//! # executor: &juniper::Executor<'a, Context>,
//! # trail: &QueryTrail<'a, User, Walked>,
//! # active_since: DateTime<Utc>,
//! # ) -> juniper::FieldResult<Vec<User>> {
//! # unimplemented!()
//! # }
//! # }
//! # pub struct User {}
//! # impl UserFields for User {
//! # fn field_id<'a>(
//! # &self,
//! # executor: &juniper::Executor<'a, Context>,
//! # ) -> juniper::FieldResult<&juniper::ID> {
//! # unimplemented!()
//! # }
//! # }
//! use chrono::prelude::*;
//!
//! graphql_schema! {
//! schema {
//! query: Query
//! }
//!
//! type Query {
//! countries: [Country!]! @juniper(ownership: "owned")
//! }
//!
//! type Country {
//! users(activeSince: DateTimeUtc!): [User!]! @juniper(ownership: "owned")
//! }
//!
//! type User {
//! id: ID!
//! }
//!
//! scalar DateTimeUtc
//! }
//!
//! pub struct Query;
//!
//! impl QueryFields for Query {
//! fn field_countries<'a>(
//! &self,
//! executor: &'a juniper::Executor<'a, Context>,
//! trail: &'a QueryTrail<'a, Country, Walked>
//! ) -> juniper::FieldResult<Vec<Country>> {
//! // Get struct that has all arguments passed to `Country.users`
//! let args: CountryUsersArgs<'a> = trail.users_args();
//!
//! // The struct has methods for each argument, e.g. `active_since`.
//! //
//! // Notice that it automatically converts the incoming value to
//! // a `DateTime<Utc>`.
//! let _: DateTime<Utc> = args.active_since();
//!
//! # unimplemented!()
//! // ...
//! }
//! }
//! ```
//!
//! You can also elide the `'a` lifetime:
//!
//! ```
//! # #[macro_use]
//! # extern crate juniper;
//! # use juniper_from_schema::*;
//! # pub struct Context;
//! # impl juniper::Context for Context {}
//! # fn main() {}
//! # pub struct Country {}
//! # impl CountryFields for Country {
//! # fn field_users<'a>(
//! # &self,
//! # executor: &juniper::Executor<'a, Context>,
//! # trail: &QueryTrail<'a, User, Walked>,
//! # active_since: DateTime<Utc>,
//! # ) -> juniper::FieldResult<Vec<User>> {
//! # unimplemented!()
//! # }
//! # }
//! # pub struct User {}
//! # impl UserFields for User {
//! # fn field_id<'a>(
//! # &self,
//! # executor: &juniper::Executor<'a, Context>,
//! # ) -> juniper::FieldResult<&juniper::ID> {
//! # unimplemented!()
//! # }
//! # }
//! # use chrono::prelude::*;
//! # graphql_schema! {
//! # schema {
//! # query: Query
//! # }
//! # type Query {
//! # countries: [Country!]! @juniper(ownership: "owned")
//! # }
//! # type Country {
//! # users(activeSince: DateTimeUtc!): [User!]! @juniper(ownership: "owned")
//! # }
//! # type User {
//! # id: ID!
//! # }
//! # scalar DateTimeUtc
//! # }
//! # pub struct Query;
//! #
//! impl QueryFields for Query {
//! fn field_countries(
//! &self,
//! executor: &juniper::Executor<'_, Context>,
//! trail: &QueryTrail<'_, Country, Walked>
//! ) -> juniper::FieldResult<Vec<Country>> {
//! let args: CountryUsersArgs = trail.users_args();
//!
//! # unimplemented!()
//! // ...
//! }
//! }
//! ```
//!
//! The name of the arguments struct will always be `{name of type}{name of field}Args` (e.g.
//! `CountryUsersArgs`). The method names will always be the name of the arguments in snake case.
//!
//! The `*_args` method is only defined on `Walked` query trails so if you get an error like:
//!
//! ```text
//! ---- src/lib.rs - (line 10) stdout ----
//! error[E0599]: no method named `users_args` found for type `&QueryTrail<'_, Country, Walked>` in the current
//! scope
//! --> src/lib.rs:10:1
//! |
//! 10 | trail.users_args();
//! | ^^^^^^^^^^^^ method not found in `&QueryTrail<'_, Country, Walked>`
//! ```
//!
//! It is likely because you've forgotten to call [`.walk()`][] on `trail`.
//!
//! [`.walk()`]: struct.QueryTrail.html#method.walk
//!
//! Remember that you can always run `cargo doc` to get a high level overview of the generated
//! code.
//!
//! # Customizing the error type
//!
//! By default the return type of the generated field methods will be [`juniper::FieldResult<T>`].
//! That is just a type alias for `std::result::Result<T, juniper::FieldError>`. Should you want to
//! use a different error type than [`juniper::FieldError`] that can be done by passing `,
//! error_type: YourType` to [`graphql_schema_from_file!`].
//!
//! Just keep in that your custom error type must implement [`juniper::IntoFieldError`] to
//! type check.
//!
//! Example:
//!
//! ```
//! # #[macro_use]
//! # extern crate juniper;
//! # use juniper::*;
//! # use juniper_from_schema::graphql_schema_from_file;
//! # fn main() {}
//! # pub struct Context;
//! # impl juniper::Context for Context {}
//! # pub struct Mutation;
//! # impl MutationFields for Mutation {
//! # fn field_noop(&self, executor: &Executor<'_, Context>) -> Result<&bool, MyError> {
//! # Ok(&true)
//! # }
//! # }
//! graphql_schema_from_file!("tests/schemas/doc_schema.graphql", error_type: MyError);
//!
//! pub struct MyError(String);
//!
//! impl juniper::IntoFieldError for MyError {
//! fn into_field_error(self) -> juniper::FieldError {
//! // Perform custom error handling
//! juniper::FieldError::from(self.0)
//! }
//! }
//!
//! pub struct Query;
//!
//! impl QueryFields for Query {
//! fn field_hello_world(
//! &self,
//! executor: &Executor<'_, Context>,
//! name: String,
//! ) -> Result<String, MyError> {
//! Ok(format!("Hello, {}!", name))
//! }
//! }
//! ```
//!
//! [`graphql_schema!`] does not support changing the error type.
//!
//! [`graphql_schema!`]: macro.graphql_schema.html
//! [`graphql_schema_from_file!`]: macro.graphql_schema_from_file.html
//! [`juniper::IntoFieldError`]: https://docs.rs/juniper/0.11.1/juniper/trait.IntoFieldError.html
//! [`juniper::FieldError`]: https://docs.rs/juniper/0.11.1/juniper/struct.FieldError.html
//! [`juniper::FieldResult<T>`]: https://docs.rs/juniper/0.11.1/juniper/type.FieldResult.html
//!
//! # Customizing the context type
//!
//! By default the generate code will assume your context type is called `Context`. If that is not
//! the case you can customize it by calling [`graphql_schema_from_file!`] with `context_type: NewName`.
//!
//! Example:
//!
//! ```
//! # #[macro_use]
//! # extern crate juniper;
//! # use juniper::*;
//! # use juniper_from_schema::graphql_schema_from_file;
//! # fn main() {}
//! # pub struct Mutation;
//! # impl MutationFields for Mutation {
//! # fn field_noop(&self, executor: &Executor<'_, MyContext>) -> juniper::FieldResult<&bool> {
//! # Ok(&true)
//! # }
//! # }
//! graphql_schema_from_file!("tests/schemas/doc_schema.graphql", context_type: MyContext);
//!
//! pub struct MyContext;
//! impl juniper::Context for MyContext {}
//!
//! pub struct Query;
//!
//! impl QueryFields for Query {
//! fn field_hello_world(
//! &self,
//! executor: &Executor<'_, MyContext>,
//! name: String,
//! ) -> juniper::FieldResult<String> {
//! Ok(format!("Hello, {}!", name))
//! }
//! }
//! ```
//!
//! [`graphql_schema!`] does not support changing the context type.
//!
//! [`graphql_schema!`]: macro.graphql_schema.html
//! [`graphql_schema_from_file!`]: macro.graphql_schema_from_file.html
//!
//! # Inspecting the generated code
//!
//! If you wish to see exactly what code gets generated you can set the env var
//! `JUNIPER_FROM_SCHEMA_DEBUG` to `1` when compiling. For example:
//!
//! ```bash
//! JUNIPER_FROM_SCHEMA_DEBUG=1 cargo build
//! ```
//!
//! The code will not be formatted so it might be tricky to read. The easiest way to fix this is to
//! copy the printed code to a file and run it through [rustfmt].
//!
//! Alternatively you can include the [feature] called `"format-debug-output"`. This will run the
//! output through [rustfmt] before printing it. That way you don't have to do that manually.
//! Example `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! juniper-from-schema = { version = "x.y.z", features = ["format-debug-output"] }
//! ```
//!
//! Unfortunately this requires that you're using nightly, because [rustfmt requires
//! nightly](https://github.com/rust-lang/rustfmt#installing-from-source). It might also break your
//! build because [rustfmt] doesn't always compile for some reason ¯\\\_(ツ)\_/¯. If you experience
//! this just remove the `"format-debug-output"` feature and format the output manually.
//!
//! [feature]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#choosing-features
//! [rustfmt]: https://github.com/rust-lang/rustfmt
use ;
use PhantomData;
pub use ;
/// A type used to parameterize `QueryTrail` to know that `walk` has been called.
;
/// A type used to parameterize `QueryTrail` to know that `walk` has *not* been called.
;
/// A wrapper around a `juniper::LookAheadSelection` with methods for each possible child.