Fill up missing docs for #[graphql_interface] macro (#682)
This commit is contained in:
parent
b1a0366112
commit
6d4a0a8709
3 changed files with 390 additions and 24 deletions
|
@ -235,7 +235,7 @@ trait Character {
|
|||
|
||||
### Custom context
|
||||
|
||||
If a context is required in a trait method to resolve a [GraphQL interface][1] field, specify it as an argument.
|
||||
If a [`Context`][6] is required in a trait method to resolve a [GraphQL interface][1] field, specify it as an argument.
|
||||
|
||||
```rust
|
||||
# extern crate juniper;
|
||||
|
@ -288,7 +288,7 @@ impl Character for Human {
|
|||
|
||||
### Using executor and explicit generic scalar
|
||||
|
||||
If an executor is required in a trait method to resolve a [GraphQL interface][1] field, specify it as an argument.
|
||||
If an [`Executor`][4] is required in a trait method to resolve a [GraphQL interface][1] field, specify it as an argument.
|
||||
|
||||
This requires to explicitly parametrize over [`ScalarValue`][3], as [`Executor`][4] does so.
|
||||
|
||||
|
@ -296,14 +296,13 @@ This requires to explicitly parametrize over [`ScalarValue`][3], as [`Executor`]
|
|||
# extern crate juniper;
|
||||
use juniper::{graphql_interface, Executor, GraphQLObject, LookAheadMethods as _, ScalarValue};
|
||||
|
||||
#[graphql_interface(for = Human, Scalar = S)] // notice specifying scalar as existing type parameter
|
||||
#[graphql_interface(for = Human, Scalar = S)] // notice specifying `ScalarValue` as existing type parameter
|
||||
trait Character<S: ScalarValue> {
|
||||
// If a field argument is named `executor`, it's automatically assumed
|
||||
// as an executor argument.
|
||||
async fn id<'a>(&self, executor: &'a Executor<'_, '_, (), S>) -> &'a str
|
||||
where
|
||||
S: Send + Sync; // required by `#[async_trait]` transformation ¯\_(ツ)_/¯
|
||||
|
||||
|
||||
// Otherwise, you may mark it explicitly as an executor argument.
|
||||
async fn name<'b>(
|
||||
|
@ -343,7 +342,7 @@ impl<S: ScalarValue> Character<S> for Human {
|
|||
|
||||
### Downcasting
|
||||
|
||||
By default, the [GraphQL interface][1] value is downcast to one of its implementer types via matching the enum variant or downcasting the trait object (if `dyn` is used).
|
||||
By default, the [GraphQL interface][1] value is downcast to one of its implementer types via matching the enum variant or downcasting the trait object (if `dyn` macro argument is used).
|
||||
|
||||
However, if some custom logic is needed to downcast a [GraphQL interface][1] implementer, you may specify either an external function or a trait method to do so.
|
||||
|
||||
|
@ -406,6 +405,8 @@ fn get_droid<'db>(ch: &CharacterValue, db: &'db Database) -> Option<&'db Droid>
|
|||
# fn main() {}
|
||||
```
|
||||
|
||||
The attribute syntax `#[graphql_interface(on ImplementerType = resolver_fn)]` follows the [GraphQL syntax for downcasting interface implementer](https://spec.graphql.org/June2018/#example-5cc55).
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -424,7 +425,7 @@ trait Character {
|
|||
}
|
||||
|
||||
#[derive(GraphQLObject)]
|
||||
#[graphql(Scalar = DefaultScalarValue)]
|
||||
#[graphql(impl = CharacterValue, Scalar = DefaultScalarValue)]
|
||||
struct Human {
|
||||
id: String,
|
||||
home_planet: String,
|
||||
|
@ -437,6 +438,7 @@ impl Character for Human {
|
|||
}
|
||||
|
||||
#[derive(GraphQLObject)]
|
||||
#[graphql(impl = CharacterValue, Scalar = DefaultScalarValue)]
|
||||
struct Droid {
|
||||
id: String,
|
||||
primary_function: String,
|
||||
|
@ -460,3 +462,4 @@ impl Character for Droid {
|
|||
[3]: https://docs.rs/juniper/latest/juniper/trait.ScalarValue.html
|
||||
[4]: https://docs.rs/juniper/latest/juniper/struct.Executor.html
|
||||
[5]: https://spec.graphql.org/June2018/#sec-Objects
|
||||
[6]: https://docs.rs/juniper/0.14.2/juniper/trait.Context.html
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
Unions
|
||||
======
|
||||
|
||||
From the server's point of view, [GraphQL unions][1] are similar to interfaces - the only exception is that they don't contain fields on their own.
|
||||
From the server's point of view, [GraphQL unions][1] are somewhat similar to [interfaces][5] - the main difference is that they don't contain fields on their own.
|
||||
|
||||
For implementing [GraphQL unions][1] Juniper provides:
|
||||
The most obvious and straightforward way to represent a [GraphQL union][1] in Rust is enum. However, we also can do so either with trait or a regular struct. That's why, for implementing [GraphQL unions][1] Juniper provides:
|
||||
- `#[derive(GraphQLUnion)]` macro for enums and structs.
|
||||
- `#[graphql_union]` for traits.
|
||||
|
||||
|
@ -288,7 +288,7 @@ impl Character for Droid {
|
|||
|
||||
### Custom context
|
||||
|
||||
If a context is required in a trait method to resolve a [GraphQL union][1] variant, specify it as an argument.
|
||||
If a [`Context`][6] is required in a trait method to resolve a [GraphQL union][1] variant, specify it as an argument.
|
||||
|
||||
```rust
|
||||
# #![allow(unused_variables)]
|
||||
|
@ -487,3 +487,5 @@ enum Character {
|
|||
|
||||
[1]: https://spec.graphql.org/June2018/#sec-Unions
|
||||
[2]: https://docs.rs/juniper/latest/juniper/trait.ScalarValue.html
|
||||
[5]: https://spec.graphql.org/June2018/#sec-Interfaces
|
||||
[6]: https://docs.rs/juniper/0.14.2/juniper/trait.Context.html
|
||||
|
|
|
@ -550,6 +550,363 @@ pub fn graphql_subscription(args: TokenStream, input: TokenStream) -> TokenStrea
|
|||
))
|
||||
}
|
||||
|
||||
/// `#[graphql_interface]` macro for generating a [GraphQL interface][1] implementation for traits
|
||||
/// and its implementers.
|
||||
///
|
||||
/// Specifying multiple `#[graphql_interface]` attributes on the same definition is totally okay.
|
||||
/// They all will be treated as a single attribute.
|
||||
///
|
||||
/// The main difference between [GraphQL interface][1] type and Rust trait is that the former serves
|
||||
/// both as an _abstraction_ and a _value downcastable to concrete implementers_, while in Rust, a
|
||||
/// trait is an _abstraction only_ and you need a separate type to downcast into a concrete
|
||||
/// implementer, like enum or [trait object][3], because trait doesn't represent a type itself.
|
||||
/// Macro uses Rust enum to represent a value type of [GraphQL interface][1] by default, however
|
||||
/// [trait object][3] may be used too (use `dyn` attribute argument for that).
|
||||
///
|
||||
/// A __trait has to be [object safe][2]__ if its values are represented by [trait object][3],
|
||||
/// because schema resolvers will need to return that [trait object][3]. The [trait object][3] has
|
||||
/// to be [`Send`] and [`Sync`], and the macro automatically generate a convenien type alias for
|
||||
/// such [trait object][3].
|
||||
///
|
||||
/// ```
|
||||
/// use juniper::{graphql_interface, GraphQLObject};
|
||||
///
|
||||
/// // NOTICE: By default a `CharacterValue` enum is generated by macro to represent values of this
|
||||
/// // GraphQL interface.
|
||||
/// #[graphql_interface(for = [Human, Droid])] // enumerating all implementers is mandatory
|
||||
/// trait Character {
|
||||
/// fn id(&self) -> &str;
|
||||
/// }
|
||||
///
|
||||
/// // NOTICE: `dyn` attribute argument enables trait object usage to represent values of this
|
||||
/// // GraphQL interface. Also, for trait objects a trait is slightly modified
|
||||
/// // under-the-hood by adding a `ScalarValue` type parameter.
|
||||
/// #[graphql_interface(dyn = DynSerial, for = Droid)]
|
||||
/// trait Serial {
|
||||
/// fn number(&self) -> i32;
|
||||
/// }
|
||||
///
|
||||
/// #[derive(GraphQLObject)]
|
||||
/// #[graphql(impl = CharacterValue)] // notice the enum type name, not trait name
|
||||
/// struct Human {
|
||||
/// id: String,
|
||||
/// home_planet: String,
|
||||
/// }
|
||||
/// #[graphql_interface]
|
||||
/// impl Character for Human {
|
||||
/// fn id(&self) -> &str {
|
||||
/// &self.id
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// #[derive(GraphQLObject)]
|
||||
/// #[graphql(impl = [CharacterValue, DynSerial<__S>])] // notice the trait object referred by alias
|
||||
/// struct Droid { // and its parametrization by generic
|
||||
/// id: String, // `ScalarValue`
|
||||
/// primary_function: String,
|
||||
/// }
|
||||
/// #[graphql_interface]
|
||||
/// impl Character for Droid {
|
||||
/// fn id(&self) -> &str {
|
||||
/// &self.id
|
||||
/// }
|
||||
/// }
|
||||
/// #[graphql_interface(dyn)] // implementing requires to know about dynamic dispatch too
|
||||
/// impl Serial for Droid {
|
||||
/// fn number(&self) -> i32 {
|
||||
/// 78953
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Custom name, description, deprecation and argument defaults
|
||||
///
|
||||
/// The name of [GraphQL interface][1], its field, or a field argument may be overriden with a
|
||||
/// `name` attribute's argument. By default, a type name is used or `camelCased` method/argument
|
||||
/// name.
|
||||
///
|
||||
/// The description of [GraphQL interface][1], its field, or a field argument may be specified
|
||||
/// either with a `description`/`desc` attribute's argument, or with a regular Rust doc comment.
|
||||
///
|
||||
/// A field of [GraphQL interface][1] may be deprecated by specifying a `deprecated` attribute's
|
||||
/// argument, or with regulat Rust `#[deprecated]` attribute.
|
||||
///
|
||||
/// The default value of a field argument may be specified with a `default` attribute argument (if
|
||||
/// no exact value is specified then [`Default::default`] is used).
|
||||
///
|
||||
/// ```
|
||||
/// # #![allow(deprecated)]
|
||||
/// # use juniper::graphql_interface;
|
||||
/// #
|
||||
/// #[graphql_interface(name = "Character", desc = "Possible episode characters.")]
|
||||
/// trait Chrctr {
|
||||
/// #[graphql_interface(name = "id", desc = "ID of the character.")]
|
||||
/// #[graphql_interface(deprecated = "Don't use it")]
|
||||
/// fn some_id(
|
||||
/// &self,
|
||||
/// #[graphql_interface(name = "number", desc = "Arbitrary number.")]
|
||||
/// #[graphql_interface(default = 5)]
|
||||
/// num: i32,
|
||||
/// ) -> &str;
|
||||
/// }
|
||||
///
|
||||
/// // NOTICE: Rust docs are used as GraphQL description.
|
||||
/// /// Possible episode characters.
|
||||
/// #[graphql_interface]
|
||||
/// trait CharacterWithDocs {
|
||||
/// /// ID of the character.
|
||||
/// #[deprecated]
|
||||
/// fn id(&self, #[graphql_interface(default)] num: i32) -> &str;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Custom context
|
||||
///
|
||||
/// By default, the generated implementation tries to infer [`Context`] type from signatures of
|
||||
/// trait methods, and uses [unit type `()`][4] if signatures contains no [`Context`] arguments.
|
||||
///
|
||||
/// If [`Context`] type cannot be inferred or is inferred incorrectly, then specify it explicitly
|
||||
/// with `context`/`Context` attribute's argument.
|
||||
///
|
||||
/// If trait method represents a [GraphQL interface][1] field and its argument is named as `context`
|
||||
/// or `ctx` then this argument is assumed as [`Context`] and will be omited in GraphQL schema.
|
||||
/// Additionally, any argument may be marked as [`Context`] with a `context` attribute's argument.
|
||||
///
|
||||
/// ```
|
||||
/// # use std::collections::HashMap;
|
||||
/// # use juniper::{graphql_interface, GraphQLObject};
|
||||
/// #
|
||||
/// struct Database {
|
||||
/// humans: HashMap<String, Human>,
|
||||
/// droids: HashMap<String, Droid>,
|
||||
/// }
|
||||
/// impl juniper::Context for Database {}
|
||||
///
|
||||
/// #[graphql_interface(for = [Human, Droid], Context = Database)]
|
||||
/// trait Character {
|
||||
/// fn id<'db>(&self, ctx: &'db Database) -> Option<&'db str>;
|
||||
/// fn info<'db>(&self, #[graphql_interface(context)] db: &'db Database) -> Option<&'db str>;
|
||||
/// }
|
||||
///
|
||||
/// #[derive(GraphQLObject)]
|
||||
/// #[graphql(impl = CharacterValue, Context = Database)]
|
||||
/// struct Human {
|
||||
/// id: String,
|
||||
/// home_planet: String,
|
||||
/// }
|
||||
/// #[graphql_interface]
|
||||
/// impl Character for Human {
|
||||
/// fn id<'db>(&self, db: &'db Database) -> Option<&'db str> {
|
||||
/// db.humans.get(&self.id).map(|h| h.id.as_str())
|
||||
/// }
|
||||
/// fn info<'db>(&self, db: &'db Database) -> Option<&'db str> {
|
||||
/// db.humans.get(&self.id).map(|h| h.home_planet.as_str())
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// #[derive(GraphQLObject)]
|
||||
/// #[graphql(impl = CharacterValue, Context = Database)]
|
||||
/// struct Droid {
|
||||
/// id: String,
|
||||
/// primary_function: String,
|
||||
/// }
|
||||
/// #[graphql_interface]
|
||||
/// impl Character for Droid {
|
||||
/// fn id<'db>(&self, db: &'db Database) -> Option<&'db str> {
|
||||
/// db.droids.get(&self.id).map(|h| h.id.as_str())
|
||||
/// }
|
||||
/// fn info<'db>(&self, db: &'db Database) -> Option<&'db str> {
|
||||
/// db.droids.get(&self.id).map(|h| h.primary_function.as_str())
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Using `Executor`
|
||||
///
|
||||
/// If an [`Executor`] is required in a trait method to resolve a [GraphQL interface][1] field,
|
||||
/// specify it as an argument named as `executor` or explicitly marked with an `executor`
|
||||
/// attribute's argument. Such method argument will be omited in GraphQL schema.
|
||||
///
|
||||
/// However, this requires to explicitly parametrize over [`ScalarValue`], as [`Executor`] does so.
|
||||
///
|
||||
/// ```
|
||||
/// # use juniper::{graphql_interface, Executor, GraphQLObject, LookAheadMethods as _, ScalarValue};
|
||||
/// #
|
||||
/// // NOTICE: Specifying `ScalarValue` as existing type parameter.
|
||||
/// #[graphql_interface(for = Human, Scalar = S)]
|
||||
/// trait Character<S: ScalarValue> {
|
||||
/// async fn id<'a>(&self, executor: &'a Executor<'_, '_, (), S>) -> &'a str
|
||||
/// where
|
||||
/// S: Send + Sync; // required by `#[async_trait]` transformation ¯\_(ツ)_/¯
|
||||
///
|
||||
/// async fn name<'b>(
|
||||
/// &'b self,
|
||||
/// #[graphql_interface(executor)] another: &Executor<'_, '_, (), S>,
|
||||
/// ) -> &'b str
|
||||
/// where
|
||||
/// S: Send + Sync;
|
||||
/// }
|
||||
///
|
||||
/// #[derive(GraphQLObject)]
|
||||
/// #[graphql(impl = CharacterValue<__S>)]
|
||||
/// struct Human {
|
||||
/// id: String,
|
||||
/// name: String,
|
||||
/// }
|
||||
/// #[graphql_interface(Scalar = S)]
|
||||
/// impl<S: ScalarValue> Character<S> for Human {
|
||||
/// async fn id<'a>(&self, executor: &'a Executor<'_, '_, (), S>) -> &'a str
|
||||
/// where
|
||||
/// S: Send + Sync,
|
||||
/// {
|
||||
/// executor.look_ahead().field_name()
|
||||
/// }
|
||||
///
|
||||
/// async fn name<'b>(&'b self, _: &Executor<'_, '_, (), S>) -> &'b str
|
||||
/// where
|
||||
/// S: Send + Sync,
|
||||
/// {
|
||||
/// &self.name
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Custom `ScalarValue`
|
||||
///
|
||||
/// By default, `#[graphql_interface]` macro generates code, which is generic over a [`ScalarValue`]
|
||||
/// type. This may introduce a problem when at least one of [GraphQL interface][1] implementers is
|
||||
/// restricted to a concrete [`ScalarValue`] type in its implementation. To resolve such problem, a
|
||||
/// concrete [`ScalarValue`] type should be specified with a `scalar`/`Scalar`/`ScalarValue`
|
||||
/// attribute's argument.
|
||||
///
|
||||
/// ```
|
||||
/// # use juniper::{graphql_interface, DefaultScalarValue, GraphQLObject};
|
||||
/// #
|
||||
/// // NOTICE: Removing `Scalar` argument will fail compilation.
|
||||
/// #[graphql_interface(for = [Human, Droid], Scalar = DefaultScalarValue)]
|
||||
/// trait Character {
|
||||
/// fn id(&self) -> &str;
|
||||
/// }
|
||||
///
|
||||
/// #[derive(GraphQLObject)]
|
||||
/// #[graphql(impl = CharacterValue, Scalar = DefaultScalarValue)]
|
||||
/// struct Human {
|
||||
/// id: String,
|
||||
/// home_planet: String,
|
||||
/// }
|
||||
/// #[graphql_interface(Scalar = DefaultScalarValue)]
|
||||
/// impl Character for Human {
|
||||
/// fn id(&self) -> &str{
|
||||
/// &self.id
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// #[derive(GraphQLObject)]
|
||||
/// #[graphql(impl = CharacterValue, Scalar = DefaultScalarValue)]
|
||||
/// struct Droid {
|
||||
/// id: String,
|
||||
/// primary_function: String,
|
||||
/// }
|
||||
/// #[graphql_interface(Scalar = DefaultScalarValue)]
|
||||
/// impl Character for Droid {
|
||||
/// fn id(&self) -> &str {
|
||||
/// &self.id
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Ignoring trait methods
|
||||
///
|
||||
/// To omit some trait method to be assumed as a [GraphQL interface][1] field and ignore it, use an
|
||||
/// `ignore`/`skip` attribute's argument directly on that method.
|
||||
///
|
||||
/// ```
|
||||
/// # use juniper::graphql_interface;
|
||||
/// #
|
||||
/// #[graphql_interface]
|
||||
/// trait Character {
|
||||
/// fn id(&self) -> &str;
|
||||
///
|
||||
/// #[graphql_interface(ignore)] // or `#[graphql_interface(skip)]`, your choice
|
||||
/// fn kaboom(&mut self);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Downcasting
|
||||
///
|
||||
/// By default, the [GraphQL interface][1] value is downcast to one of its implementer types via
|
||||
/// matching the enum variant or downcasting the trait object (if `dyn` attribute's argument is
|
||||
/// used).
|
||||
///
|
||||
/// To use a custom logic for downcasting a [GraphQL interface][1] into its implementer, there may
|
||||
/// be specified:
|
||||
/// - either a `downcast` attribute's argument directly on a trait method;
|
||||
/// - or an `on` attribute's argument on aa trait definition referring an exteranl function.
|
||||
///
|
||||
/// ```
|
||||
/// # use std::collections::HashMap;
|
||||
/// # use juniper::{graphql_interface, GraphQLObject};
|
||||
/// #
|
||||
/// struct Database {
|
||||
/// humans: HashMap<String, Human>,
|
||||
/// droids: HashMap<String, Droid>,
|
||||
/// }
|
||||
/// impl juniper::Context for Database {}
|
||||
///
|
||||
/// #[graphql_interface(for = [Human, Droid], Context = Database)]
|
||||
/// #[graphql_interface(on Droid = get_droid)] // enables downcasting `Droid` via `get_droid()`
|
||||
/// trait Character {
|
||||
/// fn id(&self) -> &str;
|
||||
///
|
||||
/// #[graphql_interface(downcast)] // makes method a downcast to `Human`, not a field
|
||||
/// // NOTICE: The method signature may optionally contain `&Database` context argument.
|
||||
/// fn as_human(&self) -> Option<&Human> {
|
||||
/// None
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// #[derive(GraphQLObject)]
|
||||
/// #[graphql(impl = CharacterValue, Context = Database)]
|
||||
/// struct Human {
|
||||
/// id: String,
|
||||
/// }
|
||||
/// #[graphql_interface]
|
||||
/// impl Character for Human {
|
||||
/// fn id(&self) -> &str {
|
||||
/// &self.id
|
||||
/// }
|
||||
///
|
||||
/// fn as_human(&self) -> Option<&Self> {
|
||||
/// Some(self)
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// #[derive(GraphQLObject)]
|
||||
/// #[graphql(impl = CharacterValue, Context = Database)]
|
||||
/// struct Droid {
|
||||
/// id: String,
|
||||
/// }
|
||||
/// #[graphql_interface]
|
||||
/// impl Character for Droid {
|
||||
/// fn id(&self) -> &str {
|
||||
/// &self.id
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // External downcast function doesn't have to be a method of a type.
|
||||
/// // It's only a matter of the function signature to match the requirements.
|
||||
/// fn get_droid<'db>(ch: &CharacterValue, db: &'db Database) -> Option<&'db Droid> {
|
||||
/// db.droids.get(ch.id())
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`Context`]: juniper::Context
|
||||
/// [`Executor`]: juniper::Executor
|
||||
/// [`ScalarValue`]: juniper::ScalarValue
|
||||
/// [1]: https://spec.graphql.org/June2018/#sec-Interfaces
|
||||
/// [2]: https://doc.rust-lang.org/stable/reference/items/traits.html#object-safety
|
||||
/// [3]: https://doc.rust-lang.org/stable/reference/types/trait-object.html
|
||||
/// [4]: https://doc.rust-lang.org/stable/std/primitive.unit.html
|
||||
#[proc_macro_error]
|
||||
#[proc_macro_attribute]
|
||||
pub fn graphql_interface(attr: TokenStream, body: TokenStream) -> TokenStream {
|
||||
|
@ -638,9 +995,9 @@ pub fn graphql_interface(attr: TokenStream, body: TokenStream) -> TokenStream {
|
|||
///
|
||||
/// # Custom context
|
||||
///
|
||||
/// By default, the generated implementation uses [unit type `()`][4] as context. To use a custom
|
||||
/// context type for [GraphQL union][1] variants types or external resolver functions, specify it
|
||||
/// with `context`/`Context` attribute's argument.
|
||||
/// By default, the generated implementation uses [unit type `()`][4] as [`Context`]. To use a
|
||||
/// custom [`Context`] type for [GraphQL union][1] variants types or external resolver functions,
|
||||
/// specify it with `context`/`Context` attribute's argument.
|
||||
///
|
||||
/// ```
|
||||
/// # use juniper::{GraphQLObject, GraphQLUnion};
|
||||
|
@ -672,10 +1029,10 @@ pub fn graphql_interface(attr: TokenStream, body: TokenStream) -> TokenStream {
|
|||
///
|
||||
/// # Custom `ScalarValue`
|
||||
///
|
||||
/// By default, this macro generates code, which is generic over a `ScalarValue` type.
|
||||
/// By default, this macro generates code, which is generic over a [`ScalarValue`] type.
|
||||
/// This may introduce a problem when at least one of [GraphQL union][1] variants is restricted to a
|
||||
/// concrete `ScalarValue` type in its implementation. To resolve such problem, a concrete
|
||||
/// `ScalarValue` type should be specified with a `scalar`/`Scalar`/`ScalarValue` attribute's
|
||||
/// concrete [`ScalarValue`] type in its implementation. To resolve such problem, a concrete
|
||||
/// [`ScalarValue`] type should be specified with a `scalar`/`Scalar`/`ScalarValue` attribute's
|
||||
/// argument.
|
||||
///
|
||||
/// ```
|
||||
|
@ -854,6 +1211,8 @@ pub fn graphql_interface(attr: TokenStream, body: TokenStream) -> TokenStream {
|
|||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`Context`]: juniper::Context
|
||||
/// [`ScalarValue`]: juniper::ScalarValue
|
||||
/// [1]: https://spec.graphql.org/June2018/#sec-Unions
|
||||
/// [4]: https://doc.rust-lang.org/stable/std/primitive.unit.html
|
||||
#[proc_macro_error]
|
||||
|
@ -958,11 +1317,11 @@ pub fn derive_union(input: TokenStream) -> TokenStream {
|
|||
///
|
||||
/// # Custom context
|
||||
///
|
||||
/// By default, the generated implementation tries to infer `juniper::Context` type from signatures
|
||||
/// of trait methods, and uses [unit type `()`][4] if signatures contains no context arguments.
|
||||
/// By default, the generated implementation tries to infer [`Context`] type from signatures of
|
||||
/// trait methods, and uses [unit type `()`][4] if signatures contains no [`Context`] arguments.
|
||||
///
|
||||
/// If `juniper::Context` type cannot be inferred or is inferred incorrectly, then specify it
|
||||
/// explicitly with `context`/`Context` attribute's argument.
|
||||
/// If [`Context`] type cannot be inferred or is inferred incorrectly, then specify it explicitly
|
||||
/// with `context`/`Context` attribute's argument.
|
||||
///
|
||||
/// ```
|
||||
/// # use std::collections::HashMap;
|
||||
|
@ -1009,11 +1368,11 @@ pub fn derive_union(input: TokenStream) -> TokenStream {
|
|||
///
|
||||
/// # Custom `ScalarValue`
|
||||
///
|
||||
/// By default, `#[graphql_union]` macro generates code, which is generic over a `ScalarValue` type.
|
||||
/// This may introduce a problem when at least one of [GraphQL union][1] variants is restricted to a
|
||||
/// concrete `ScalarValue` type in its implementation. To resolve such problem, a concrete
|
||||
/// `ScalarValue` type should be specified with a `scalar`/`Scalar`/`ScalarValue` attribute's
|
||||
/// argument.
|
||||
/// By default, `#[graphql_union]` macro generates code, which is generic over a [`ScalarValue`]
|
||||
/// type. This may introduce a problem when at least one of [GraphQL union][1] variants is
|
||||
/// restricted to a concrete [`ScalarValue`] type in its implementation. To resolve such problem, a
|
||||
/// concrete [`ScalarValue`] type should be specified with a `scalar`/`Scalar`/`ScalarValue`
|
||||
/// attribute's argument.
|
||||
///
|
||||
/// ```
|
||||
/// # use juniper::{graphql_union, DefaultScalarValue, GraphQLObject};
|
||||
|
@ -1142,6 +1501,8 @@ pub fn derive_union(input: TokenStream) -> TokenStream {
|
|||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`Context`]: juniper::Context
|
||||
/// [`ScalarValue`]: juniper::ScalarValue
|
||||
/// [1]: https://spec.graphql.org/June2018/#sec-Unions
|
||||
/// [2]: https://doc.rust-lang.org/stable/reference/items/traits.html#object-safety
|
||||
/// [3]: https://doc.rust-lang.org/stable/reference/types/trait-object.html
|
||||
|
|
Loading…
Reference in a new issue