2017-12-01 19:35:08 -06:00
|
|
|
//! This crate supplies custom derive implementations for the
|
|
|
|
//! [juniper](https://github.com/graphql-rust/juniper) crate.
|
|
|
|
//!
|
|
|
|
//! You should not depend on juniper_codegen directly.
|
|
|
|
//! You only need the `juniper` crate.
|
|
|
|
|
2019-07-29 10:06:22 -05:00
|
|
|
#![doc(html_root_url = "https://docs.rs/juniper_codegen/0.13.1")]
|
2017-06-24 06:23:20 -05:00
|
|
|
#![recursion_limit = "1024"]
|
|
|
|
|
|
|
|
extern crate proc_macro;
|
|
|
|
|
2017-08-02 20:55:33 -05:00
|
|
|
mod derive_enum;
|
|
|
|
mod derive_input_object;
|
2017-08-02 20:49:19 -05:00
|
|
|
mod derive_object;
|
2018-12-18 18:56:37 -06:00
|
|
|
mod derive_scalar_value;
|
2019-05-07 03:52:10 -05:00
|
|
|
mod impl_object;
|
2018-07-19 08:22:21 -05:00
|
|
|
mod util;
|
2017-06-24 06:23:20 -05:00
|
|
|
|
|
|
|
use proc_macro::TokenStream;
|
|
|
|
|
|
|
|
#[proc_macro_derive(GraphQLEnum, attributes(graphql))]
|
|
|
|
pub fn derive_enum(input: TokenStream) -> TokenStream {
|
2018-05-02 18:21:08 -05:00
|
|
|
let ast = syn::parse::<syn::DeriveInput>(input).unwrap();
|
2018-12-18 18:56:37 -06:00
|
|
|
let gen = derive_enum::impl_enum(&ast, false);
|
|
|
|
gen.into()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[proc_macro_derive(GraphQLEnumInternal, attributes(graphql))]
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub fn derive_enum_internal(input: TokenStream) -> TokenStream {
|
|
|
|
let ast = syn::parse::<syn::DeriveInput>(input).unwrap();
|
|
|
|
let gen = derive_enum::impl_enum(&ast, true);
|
2018-05-02 18:21:08 -05:00
|
|
|
gen.into()
|
2017-06-24 06:23:20 -05:00
|
|
|
}
|
2017-06-24 13:20:00 -05:00
|
|
|
|
|
|
|
#[proc_macro_derive(GraphQLInputObject, attributes(graphql))]
|
|
|
|
pub fn derive_input_object(input: TokenStream) -> TokenStream {
|
2018-05-02 18:21:08 -05:00
|
|
|
let ast = syn::parse::<syn::DeriveInput>(input).unwrap();
|
2018-12-18 18:56:37 -06:00
|
|
|
let gen = derive_input_object::impl_input_object(&ast, false);
|
|
|
|
gen.into()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[proc_macro_derive(GraphQLInputObjectInternal, attributes(graphql))]
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub fn derive_input_object_internal(input: TokenStream) -> TokenStream {
|
|
|
|
let ast = syn::parse::<syn::DeriveInput>(input).unwrap();
|
|
|
|
let gen = derive_input_object::impl_input_object(&ast, true);
|
2018-05-02 18:21:08 -05:00
|
|
|
gen.into()
|
2017-06-24 13:20:00 -05:00
|
|
|
}
|
2017-08-02 20:49:19 -05:00
|
|
|
|
|
|
|
#[proc_macro_derive(GraphQLObject, attributes(graphql))]
|
|
|
|
pub fn derive_object(input: TokenStream) -> TokenStream {
|
2018-05-02 18:21:08 -05:00
|
|
|
let ast = syn::parse::<syn::DeriveInput>(input).unwrap();
|
2019-05-07 03:52:10 -05:00
|
|
|
let gen = derive_object::build_derive_object(ast, false);
|
2018-05-02 18:21:08 -05:00
|
|
|
gen.into()
|
2017-08-02 20:49:19 -05:00
|
|
|
}
|
Introduce an abstraction for scalar values (#251)
Introduce an abstraction for scalar values
Before this change, possible scalar values were hard coded to be representable
by one of the following types: `i32`, `f64`, `String` or `bool`. This
restricts the types of custom scalar values that can be defined. For
example, it was not possible to define a scalar value that represents an
`i64` without mapping it to a string (which would be inefficient).
One solution to fix the example above would simply be to change the
internal representation to allow it to represent an `i64`, but this would
only fix the problem for one type (until someone wants to support
`i128` for example). Also this would make juniper not follow the
GraphQL standard closely.
This commit takes another approach, by making the exact "internal"
representation of scalar values swappable (in such a way that a downstream crate could provide its own representation tailored to their needs). This allows juniper to provide a default type that only
contains the types described in the standard whereas other crates could define custom scalars for their needs.
To accomplish this we need to change several things in the current implementation:
* Add some traits that abstract the behavior of such a scalar value representation
* Change `Value` and `InputValue` to have a scalar variant (with a
generic type) instead of hard coded variants for the standard
types. This implies adding a generic parameter to both enums that
needs to be added in the whole crate.
* Change the parser to allow deciding between different types of
scalar values. The problem is basically that the original parser
implementation had no way to know whether a parsed integer number is
a `i32` or a `i64` (for example). To fix this we added some knowledge
of the existing schema to the parser.
* Fix some macros and derives to follow the new behavior.
This commit also contains an unrelated change about the way `juniper_codegen`
resolves items from `juniper`. The `_internal` flag is removed and
the resolution is replaced by a macro.
The scalar parsing strategy is as follows:
* Pass optional type information all the way down in the parser. If a
field/type/… does note exist, just do not pass down the type
information.
* The lexer now distinguishes between several fundamental scalar types (`String`, `Float`, `Int`). It does not try to actually parse those values, instead it just annotates them that this is a floating point number, an integer number, or a string value, etc.
* If type information exists while parsing a scalar value, try the following:
1. Try parsing the value using that type information.
2. If that fails try parsing the value using the inferred type information from the lexer.
* If no type information exists, try parsing the scalar value using the inferred type from the lexer,
All macros support the introduced scalar value abstraction. It is now possible to specify if a certain implementation should be based on a specific scalar value representation or be generic about the exact representation. All macros now default to the `DefaultScalarValue` type provided by
`juniper` if no scalar value representation is specified. This is done with usability and backwards compatibility in mind.
Finally, we allow specifying the scalar value representations via an attribute
(`#[graphql(scalar = "Type")]`). A default generic implementation
is provided.
2018-10-22 22:40:14 -05:00
|
|
|
|
2019-05-26 04:09:27 -05:00
|
|
|
/// This custom derive macro implements the #[derive(GraphQLScalarValue)]
|
|
|
|
/// derive.
|
|
|
|
///
|
|
|
|
/// This can be used for two purposes.
|
|
|
|
///
|
|
|
|
/// ## Transparent Newtype Wrapper
|
|
|
|
///
|
|
|
|
/// Sometimes, you want to create a custerm scalar type by wrapping
|
|
|
|
/// an existing type. In Rust, this is often called the "newtype" pattern.
|
|
|
|
/// Thanks to this custom derive, this becomes really easy:
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// // Deriving GraphQLScalar is all that is required.
|
|
|
|
/// #[derive(juniper::GraphQLScalarValue)]
|
|
|
|
/// struct UserId(String);
|
|
|
|
///
|
|
|
|
/// #[derive(juniper::GraphQLObject)]
|
|
|
|
/// struct User {
|
|
|
|
/// id: UserId,
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// The type can also be customized.
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// /// Doc comments are used for the GraphQL type description.
|
|
|
|
/// #[derive(juniper::GraphQLScalarValue)]
|
|
|
|
/// #[graphql(
|
|
|
|
/// transparent,
|
|
|
|
/// // Set a custom GraphQL name.
|
|
|
|
/// name= "MyUserId",
|
|
|
|
/// // A description can also specified in the attribute.
|
|
|
|
/// // This will the doc comment, if one exists.
|
|
|
|
/// description = "...",
|
|
|
|
/// )]
|
|
|
|
/// struct UserId(String);
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// ### Base ScalarValue Enum
|
|
|
|
///
|
|
|
|
/// TODO: write documentation.
|
|
|
|
///
|
|
|
|
#[proc_macro_derive(GraphQLScalarValue, attributes(graphql))]
|
2018-12-18 18:56:37 -06:00
|
|
|
pub fn derive_scalar_value(input: TokenStream) -> TokenStream {
|
|
|
|
let ast = syn::parse::<syn::DeriveInput>(input).unwrap();
|
|
|
|
let gen = derive_scalar_value::impl_scalar_value(&ast, false);
|
|
|
|
gen.into()
|
|
|
|
}
|
|
|
|
|
2018-12-19 12:24:01 -06:00
|
|
|
#[deprecated(note = "ScalarValue has been renamed to GraphQLScalarValue")]
|
|
|
|
#[proc_macro_derive(ScalarValue)]
|
|
|
|
pub fn derive_scalar_value_deprecated(input: TokenStream) -> TokenStream {
|
|
|
|
derive_scalar_value(input)
|
|
|
|
}
|
|
|
|
|
2018-12-18 18:56:37 -06:00
|
|
|
#[proc_macro_derive(GraphQLScalarValueInternal)]
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub fn derive_scalar_value_internal(input: TokenStream) -> TokenStream {
|
Introduce an abstraction for scalar values (#251)
Introduce an abstraction for scalar values
Before this change, possible scalar values were hard coded to be representable
by one of the following types: `i32`, `f64`, `String` or `bool`. This
restricts the types of custom scalar values that can be defined. For
example, it was not possible to define a scalar value that represents an
`i64` without mapping it to a string (which would be inefficient).
One solution to fix the example above would simply be to change the
internal representation to allow it to represent an `i64`, but this would
only fix the problem for one type (until someone wants to support
`i128` for example). Also this would make juniper not follow the
GraphQL standard closely.
This commit takes another approach, by making the exact "internal"
representation of scalar values swappable (in such a way that a downstream crate could provide its own representation tailored to their needs). This allows juniper to provide a default type that only
contains the types described in the standard whereas other crates could define custom scalars for their needs.
To accomplish this we need to change several things in the current implementation:
* Add some traits that abstract the behavior of such a scalar value representation
* Change `Value` and `InputValue` to have a scalar variant (with a
generic type) instead of hard coded variants for the standard
types. This implies adding a generic parameter to both enums that
needs to be added in the whole crate.
* Change the parser to allow deciding between different types of
scalar values. The problem is basically that the original parser
implementation had no way to know whether a parsed integer number is
a `i32` or a `i64` (for example). To fix this we added some knowledge
of the existing schema to the parser.
* Fix some macros and derives to follow the new behavior.
This commit also contains an unrelated change about the way `juniper_codegen`
resolves items from `juniper`. The `_internal` flag is removed and
the resolution is replaced by a macro.
The scalar parsing strategy is as follows:
* Pass optional type information all the way down in the parser. If a
field/type/… does note exist, just do not pass down the type
information.
* The lexer now distinguishes between several fundamental scalar types (`String`, `Float`, `Int`). It does not try to actually parse those values, instead it just annotates them that this is a floating point number, an integer number, or a string value, etc.
* If type information exists while parsing a scalar value, try the following:
1. Try parsing the value using that type information.
2. If that fails try parsing the value using the inferred type information from the lexer.
* If no type information exists, try parsing the scalar value using the inferred type from the lexer,
All macros support the introduced scalar value abstraction. It is now possible to specify if a certain implementation should be based on a specific scalar value representation or be generic about the exact representation. All macros now default to the `DefaultScalarValue` type provided by
`juniper` if no scalar value representation is specified. This is done with usability and backwards compatibility in mind.
Finally, we allow specifying the scalar value representations via an attribute
(`#[graphql(scalar = "Type")]`). A default generic implementation
is provided.
2018-10-22 22:40:14 -05:00
|
|
|
let ast = syn::parse::<syn::DeriveInput>(input).unwrap();
|
2018-12-18 18:56:37 -06:00
|
|
|
let gen = derive_scalar_value::impl_scalar_value(&ast, true);
|
Introduce an abstraction for scalar values (#251)
Introduce an abstraction for scalar values
Before this change, possible scalar values were hard coded to be representable
by one of the following types: `i32`, `f64`, `String` or `bool`. This
restricts the types of custom scalar values that can be defined. For
example, it was not possible to define a scalar value that represents an
`i64` without mapping it to a string (which would be inefficient).
One solution to fix the example above would simply be to change the
internal representation to allow it to represent an `i64`, but this would
only fix the problem for one type (until someone wants to support
`i128` for example). Also this would make juniper not follow the
GraphQL standard closely.
This commit takes another approach, by making the exact "internal"
representation of scalar values swappable (in such a way that a downstream crate could provide its own representation tailored to their needs). This allows juniper to provide a default type that only
contains the types described in the standard whereas other crates could define custom scalars for their needs.
To accomplish this we need to change several things in the current implementation:
* Add some traits that abstract the behavior of such a scalar value representation
* Change `Value` and `InputValue` to have a scalar variant (with a
generic type) instead of hard coded variants for the standard
types. This implies adding a generic parameter to both enums that
needs to be added in the whole crate.
* Change the parser to allow deciding between different types of
scalar values. The problem is basically that the original parser
implementation had no way to know whether a parsed integer number is
a `i32` or a `i64` (for example). To fix this we added some knowledge
of the existing schema to the parser.
* Fix some macros and derives to follow the new behavior.
This commit also contains an unrelated change about the way `juniper_codegen`
resolves items from `juniper`. The `_internal` flag is removed and
the resolution is replaced by a macro.
The scalar parsing strategy is as follows:
* Pass optional type information all the way down in the parser. If a
field/type/… does note exist, just do not pass down the type
information.
* The lexer now distinguishes between several fundamental scalar types (`String`, `Float`, `Int`). It does not try to actually parse those values, instead it just annotates them that this is a floating point number, an integer number, or a string value, etc.
* If type information exists while parsing a scalar value, try the following:
1. Try parsing the value using that type information.
2. If that fails try parsing the value using the inferred type information from the lexer.
* If no type information exists, try parsing the scalar value using the inferred type from the lexer,
All macros support the introduced scalar value abstraction. It is now possible to specify if a certain implementation should be based on a specific scalar value representation or be generic about the exact representation. All macros now default to the `DefaultScalarValue` type provided by
`juniper` if no scalar value representation is specified. This is done with usability and backwards compatibility in mind.
Finally, we allow specifying the scalar value representations via an attribute
(`#[graphql(scalar = "Type")]`). A default generic implementation
is provided.
2018-10-22 22:40:14 -05:00
|
|
|
gen.into()
|
|
|
|
}
|
2019-05-07 03:52:10 -05:00
|
|
|
|
|
|
|
/**
|
2019-05-13 11:33:45 -05:00
|
|
|
The `object` proc macro is the primary way of defining GraphQL resolvers
|
2019-05-07 03:52:10 -05:00
|
|
|
that can not be implemented with the GraphQLObject derive.
|
|
|
|
|
2019-05-07 04:23:46 -05:00
|
|
|
It enables you to write GraphQL field resolvers for a type by declaring a
|
2019-05-07 03:52:10 -05:00
|
|
|
regular Rust `impl` block. Under the hood, the procedural macro implements
|
|
|
|
the GraphQLType trait.
|
|
|
|
|
2019-05-13 11:33:45 -05:00
|
|
|
`object` comes with many features that allow customization of
|
2019-05-07 03:52:10 -05:00
|
|
|
your fields, all of which are detailed below.
|
|
|
|
|
|
|
|
### Getting Started
|
|
|
|
|
2019-05-13 11:33:45 -05:00
|
|
|
This simple example will show you the most basic use of `object`.
|
2019-05-07 03:52:10 -05:00
|
|
|
More advanced use cases are introduced step by step.
|
|
|
|
|
|
|
|
```
|
|
|
|
// So we can declare it as a plain struct without any members.
|
|
|
|
struct Query;
|
|
|
|
|
|
|
|
// We prefix the impl Block with the procedural macro.
|
2019-05-13 11:33:45 -05:00
|
|
|
#[juniper::object]
|
2019-05-07 03:52:10 -05:00
|
|
|
impl Query {
|
|
|
|
|
|
|
|
// A **warning**: only GraphQL fields can be specified in this impl block.
|
|
|
|
// If you want to define normal methods on the struct,
|
|
|
|
// you have to do so in a separate, normal `impl` block.
|
|
|
|
|
|
|
|
|
|
|
|
// This defines a simple, static field which does not require any context.
|
2019-05-07 04:23:46 -05:00
|
|
|
// You can return any value that implements the `GraphQLType` trait.
|
2019-05-07 03:52:10 -05:00
|
|
|
// This trait is implemented for:
|
|
|
|
// - basic scalar types like bool, &str, String, i32, f64
|
|
|
|
// - GraphQL compatible wrappers like Option<_>, Vec<_>.
|
|
|
|
// - types which use the `#derive[juniper::GraphQLObject]`
|
2019-05-13 11:33:45 -05:00
|
|
|
// - `object` structs.
|
2019-05-07 04:23:46 -05:00
|
|
|
//
|
|
|
|
// An important note regarding naming:
|
2019-05-07 03:52:10 -05:00
|
|
|
// By default, field names will be converted to camel case.
|
|
|
|
// For your GraphQL queries, the field will be available as `apiVersion`.
|
2019-05-07 04:23:46 -05:00
|
|
|
//
|
2019-05-07 03:52:10 -05:00
|
|
|
// You can also manually customize the field name if required. (See below)
|
|
|
|
fn api_version() -> &'static str {
|
|
|
|
"0.1"
|
|
|
|
}
|
|
|
|
|
|
|
|
// This field takes two arguments.
|
|
|
|
// GraphQL arguments are just regular function parameters.
|
|
|
|
// **Note**: in Juniper, arguments are non-nullable by default.
|
|
|
|
// for optional arguments, you have to specify them with Option<T>.
|
|
|
|
fn add(a: f64, b: f64, c: Option<f64>) -> f64 {
|
|
|
|
a + b + c.unwrap_or(0.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
## Accessing self
|
|
|
|
|
|
|
|
```
|
|
|
|
struct Person {
|
|
|
|
first_name: String,
|
|
|
|
last_name: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Person {
|
|
|
|
// The full name method is useful outside of GraphQL,
|
|
|
|
// so we define it as a normal method.
|
|
|
|
fn build_full_name(&self) -> String {
|
|
|
|
format!("{} {}", self.first_name, self.last_name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-13 11:33:45 -05:00
|
|
|
#[juniper::object]
|
2019-05-07 03:52:10 -05:00
|
|
|
impl Person {
|
|
|
|
fn first_name(&self) -> &str {
|
|
|
|
&self.first_name
|
|
|
|
}
|
|
|
|
|
|
|
|
fn last_name(&self) -> &str {
|
|
|
|
&self.last_name
|
|
|
|
}
|
|
|
|
|
|
|
|
fn full_name(&self) -> String {
|
|
|
|
self.build_full_name()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
## Context (+ Executor)
|
|
|
|
|
|
|
|
You can specify a context that will be available across
|
|
|
|
all your resolvers during query execution.
|
|
|
|
|
|
|
|
The Context can be injected into your resolvers by just
|
2019-05-07 04:23:46 -05:00
|
|
|
specifying an argument with the same type as the context
|
2019-05-07 03:52:10 -05:00
|
|
|
(but as a reference).
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
# #[derive(juniper::GraphQLObject)] struct User { id: i32 }
|
|
|
|
# struct DbPool;
|
|
|
|
# impl DbPool { fn user(&self, id: i32) -> Option<User> { unimplemented!() } }
|
|
|
|
|
|
|
|
struct Context {
|
|
|
|
db: DbPool,
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mark our struct for juniper.
|
|
|
|
impl juniper::Context for Context {}
|
|
|
|
|
|
|
|
struct Query;
|
|
|
|
|
2019-05-13 11:33:45 -05:00
|
|
|
#[juniper::object(
|
2019-05-07 03:52:10 -05:00
|
|
|
// Here we specify the context type for this object.
|
|
|
|
Context = Context,
|
|
|
|
)]
|
|
|
|
impl Query {
|
|
|
|
// Context is injected by specifying a argument
|
|
|
|
// as a reference to the Context.
|
|
|
|
fn user(context: &Context, id: i32) -> Option<User> {
|
|
|
|
context.db.user(id)
|
|
|
|
}
|
|
|
|
|
2019-05-07 04:23:46 -05:00
|
|
|
// You can also gain access to the executor, which
|
2019-05-07 03:52:10 -05:00
|
|
|
// allows you to do look aheads.
|
|
|
|
fn with_executor(executor: &Executor) -> bool {
|
|
|
|
let info = executor.look_ahead();
|
2019-05-07 04:23:46 -05:00
|
|
|
// ...
|
2019-05-07 03:52:10 -05:00
|
|
|
true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
## Customization (Documentation, Renaming, ...)
|
|
|
|
|
|
|
|
```
|
|
|
|
struct InternalQuery;
|
|
|
|
|
|
|
|
// Doc comments can be used to specify graphql documentation.
|
|
|
|
/// GRAPHQL DOCUMENTATION.
|
|
|
|
/// More info for GraphQL users....
|
2019-05-13 11:33:45 -05:00
|
|
|
#[juniper::object(
|
2019-05-07 03:52:10 -05:00
|
|
|
// You can rename the type for GraphQL by specifying the name here.
|
|
|
|
name = "Query",
|
|
|
|
// You can also specify a description here.
|
|
|
|
// If present, doc comments will be ignored.
|
|
|
|
description = "...",
|
|
|
|
)]
|
|
|
|
impl InternalQuery {
|
|
|
|
// Documentation doc comments also work on fields.
|
|
|
|
/// GraphQL description...
|
|
|
|
fn field_with_description() -> bool { true }
|
|
|
|
|
|
|
|
// Fields can also be customized with the #[graphql] attribute.
|
|
|
|
#[graphql(
|
|
|
|
// overwrite the public name
|
|
|
|
name = "actualFieldName",
|
|
|
|
// Can be used instead of doc comments.
|
|
|
|
description = "field description",
|
|
|
|
)]
|
|
|
|
fn internal_name() -> bool { true }
|
|
|
|
|
|
|
|
// Fields can be deprecated too.
|
|
|
|
#[graphql(
|
|
|
|
deprecated = "deprecatin info...",
|
|
|
|
// Note: just "deprecated," without a description works too.
|
|
|
|
)]
|
|
|
|
fn deprecated_field_simple() -> bool { true }
|
|
|
|
|
|
|
|
|
|
|
|
// Customizing field arguments is a little awkward right now.
|
|
|
|
// This will improve once [RFC 2564](https://github.com/rust-lang/rust/issues/60406)
|
|
|
|
// is implemented, which will allow attributes on function parameters.
|
|
|
|
|
|
|
|
#[graphql(
|
|
|
|
arguments(
|
|
|
|
arg1(
|
|
|
|
// You can specify default values.
|
|
|
|
// A default can be any valid expression that yields the right type.
|
|
|
|
default = true,
|
|
|
|
description = "Argument description....",
|
|
|
|
),
|
|
|
|
arg2(
|
|
|
|
default = false,
|
|
|
|
description = "arg2 description...",
|
|
|
|
),
|
|
|
|
),
|
|
|
|
)]
|
|
|
|
fn args(arg1: bool, arg2: bool) -> bool {
|
|
|
|
arg1 && arg2
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
## Lifetimes, Generics and custom Scalars
|
|
|
|
|
|
|
|
Lifetimes work just like you'd expect.
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
struct WithLifetime<'a> {
|
|
|
|
value: &'a str,
|
|
|
|
}
|
|
|
|
|
2019-05-13 11:33:45 -05:00
|
|
|
#[juniper::object]
|
2019-05-07 03:52:10 -05:00
|
|
|
impl<'a> WithLifetime<'a> {
|
|
|
|
fn value(&self) -> &str {
|
|
|
|
self.value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
Juniper has support for custom scalars.
|
|
|
|
Mostly you will only need the default scalar type juniper::DefaultScalarValue.
|
|
|
|
|
|
|
|
You can easily specify a custom scalar though.
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
# type MyCustomScalar = juniper::DefaultScalarValue;
|
|
|
|
|
|
|
|
struct Query;
|
|
|
|
|
2019-05-13 11:33:45 -05:00
|
|
|
#[juniper::object(
|
2019-05-07 03:52:10 -05:00
|
|
|
Scalar = MyCustomScalar,
|
|
|
|
)]
|
|
|
|
impl Query {
|
|
|
|
// ...
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
*/
|
|
|
|
#[proc_macro_attribute]
|
2019-05-13 11:33:45 -05:00
|
|
|
pub fn object(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
|
|
let gen = impl_object::build_object(args, input, false);
|
2019-05-07 03:52:10 -05:00
|
|
|
gen.into()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A proc macro for defining a GraphQL object.
|
|
|
|
#[doc(hidden)]
|
|
|
|
#[proc_macro_attribute]
|
2019-05-13 11:33:45 -05:00
|
|
|
pub fn object_internal(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
|
|
let gen = impl_object::build_object(args, input, true);
|
2019-05-07 03:52:10 -05:00
|
|
|
gen.into()
|
|
|
|
}
|