Specified By - [GraphQL - October 2021] #677
This commit is contained in:
parent
7a4b0c0aa3
commit
91bb9e81fb
|
@ -446,6 +446,7 @@ pub struct Scalar {
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub use_type_description: bool,
|
pub use_type_description: bool,
|
||||||
pub visible: Option<Visible>,
|
pub visible: Option<Visible>,
|
||||||
|
pub specified_by_url: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromMeta, Default)]
|
#[derive(FromMeta, Default)]
|
||||||
|
@ -652,6 +653,8 @@ pub struct NewType {
|
||||||
pub name: NewTypeName,
|
pub name: NewTypeName,
|
||||||
#[darling(default)]
|
#[darling(default)]
|
||||||
pub visible: Option<Visible>,
|
pub visible: Option<Visible>,
|
||||||
|
#[darling(default)]
|
||||||
|
pub specified_by_url: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromMeta, Default)]
|
#[derive(FromMeta, Default)]
|
||||||
|
|
|
@ -38,12 +38,18 @@ pub fn generate(newtype_args: &args::NewType) -> GeneratorResult<TokenStream> {
|
||||||
None => quote! { <#inner_ty as #crate_name::Type>::type_name() },
|
None => quote! { <#inner_ty as #crate_name::Type>::type_name() },
|
||||||
};
|
};
|
||||||
let create_type_info = if let Some(name) = &gql_typename {
|
let create_type_info = if let Some(name) = &gql_typename {
|
||||||
|
let specified_by_url = match &newtype_args.specified_by_url {
|
||||||
|
Some(specified_by_url) => quote! { ::std::option::Option::Some(#specified_by_url) },
|
||||||
|
None => quote! { ::std::option::Option::None },
|
||||||
|
};
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
registry.create_type::<#ident, _>(|_| #crate_name::registry::MetaType::Scalar {
|
registry.create_type::<#ident, _>(|_| #crate_name::registry::MetaType::Scalar {
|
||||||
name: ::std::borrow::ToOwned::to_owned(#name),
|
name: ::std::borrow::ToOwned::to_owned(#name),
|
||||||
description: #desc,
|
description: #desc,
|
||||||
is_valid: |value| <#ident as #crate_name::ScalarType>::is_valid(value),
|
is_valid: |value| <#ident as #crate_name::ScalarType>::is_valid(value),
|
||||||
visible: #visible,
|
visible: #visible,
|
||||||
|
specified_by_url: #specified_by_url,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -30,6 +30,11 @@ pub fn generate(
|
||||||
let generic = &item_impl.generics;
|
let generic = &item_impl.generics;
|
||||||
let where_clause = &item_impl.generics.where_clause;
|
let where_clause = &item_impl.generics.where_clause;
|
||||||
let visible = visible_fn(&scalar_args.visible);
|
let visible = visible_fn(&scalar_args.visible);
|
||||||
|
let specified_by_url = match &scalar_args.specified_by_url {
|
||||||
|
Some(specified_by_url) => quote! { ::std::option::Option::Some(#specified_by_url) },
|
||||||
|
None => quote! { ::std::option::Option::None },
|
||||||
|
};
|
||||||
|
|
||||||
let expanded = quote! {
|
let expanded = quote! {
|
||||||
#item_impl
|
#item_impl
|
||||||
|
|
||||||
|
@ -45,6 +50,7 @@ pub fn generate(
|
||||||
description: #desc,
|
description: #desc,
|
||||||
is_valid: |value| <#self_ty as #crate_name::ScalarType>::is_valid(value),
|
is_valid: |value| <#self_ty as #crate_name::ScalarType>::is_valid(value),
|
||||||
visible: #visible,
|
visible: #visible,
|
||||||
|
specified_by_url: #specified_by_url,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -987,6 +987,7 @@ pub use async_graphql_derive::Subscription;
|
||||||
/// | Attribute | description | Type | Optional |
|
/// | Attribute | description | Type | Optional |
|
||||||
/// |-------------|---------------------------|----------|----------|
|
/// |-------------|---------------------------|----------|----------|
|
||||||
/// | name | Scalar name | string | Y |
|
/// | name | Scalar name | string | Y |
|
||||||
|
/// | specified_by_url | Provide a specification URL for this scalar type, it must link to a human-readable specification of the data format, serialization and coercion rules for this scalar. | string | Y |
|
||||||
///
|
///
|
||||||
pub use async_graphql_derive::Scalar;
|
pub use async_graphql_derive::Scalar;
|
||||||
|
|
||||||
|
@ -1000,8 +1001,9 @@ pub use async_graphql_derive::Scalar;
|
||||||
/// |-------------|---------------------------|----------|----------|
|
/// |-------------|---------------------------|----------|----------|
|
||||||
/// | name | If this attribute is provided then define a new scalar, otherwise it is just a transparent proxy for the internal scalar. | string | Y |
|
/// | name | If this attribute is provided then define a new scalar, otherwise it is just a transparent proxy for the internal scalar. | string | Y |
|
||||||
/// | name | If this attribute is provided then define a new scalar, otherwise it is just a transparent proxy for the internal scalar. | bool | Y |
|
/// | name | If this attribute is provided then define a new scalar, otherwise it is just a transparent proxy for the internal scalar. | bool | Y |
|
||||||
/// | visible(Only valid for new scalars.) | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
|
/// | visible(Only valid for new scalars) | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
|
||||||
/// | visible(Only valid for new scalars.) | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
|
/// | visible(Only valid for new scalars) | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
|
||||||
|
/// | specified_by_url(Only valid for new scalars) | Provide a specification URL for this scalar type, it must link to a human-readable specification of the data format, serialization and coercion rules for this scalar. | string | Y |
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
|
|
@ -218,4 +218,16 @@ impl<'a> __Type<'a> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[graphql(name = "specifiedByURL")]
|
||||||
|
async fn specified_by_url(&self) -> Option<&'a str> {
|
||||||
|
if let TypeDetail::Named(registry::MetaType::Scalar {
|
||||||
|
specified_by_url, ..
|
||||||
|
}) = &self.detail
|
||||||
|
{
|
||||||
|
*specified_by_url
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,6 +189,7 @@ pub enum MetaType {
|
||||||
description: Option<&'static str>,
|
description: Option<&'static str>,
|
||||||
is_valid: fn(value: &Value) -> bool,
|
is_valid: fn(value: &Value) -> bool,
|
||||||
visible: Option<MetaVisibleFn>,
|
visible: Option<MetaVisibleFn>,
|
||||||
|
specified_by_url: Option<&'static str>,
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
name: String,
|
name: String,
|
||||||
|
|
|
@ -68,6 +68,9 @@ pub trait ScalarType: Sized + Send {
|
||||||
/// // Rename to `MV` and add description.
|
/// // Rename to `MV` and add description.
|
||||||
/// // scalar!(MyValue, "MV", "This is my value");
|
/// // scalar!(MyValue, "MV", "This is my value");
|
||||||
///
|
///
|
||||||
|
/// // Rename to `MV`, add description and specifiedByURL.
|
||||||
|
/// // scalar!(MyValue, "MV", "This is my value", "https://tools.ietf.org/html/rfc4122");
|
||||||
|
///
|
||||||
/// struct Query;
|
/// struct Query;
|
||||||
///
|
///
|
||||||
/// #[Object]
|
/// #[Object]
|
||||||
|
@ -92,23 +95,47 @@ pub trait ScalarType: Sized + Send {
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! scalar {
|
macro_rules! scalar {
|
||||||
|
($ty:ty, $name:literal, $desc:literal, $specified_by_url:literal) => {
|
||||||
|
$crate::scalar_internal!(
|
||||||
|
$ty,
|
||||||
|
$name,
|
||||||
|
::std::option::Option::Some($desc),
|
||||||
|
::std::option::Option::Some($specified_by_url)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
($ty:ty, $name:literal, $desc:literal) => {
|
($ty:ty, $name:literal, $desc:literal) => {
|
||||||
$crate::scalar_internal!($ty, $name, ::std::option::Option::Some($desc));
|
$crate::scalar_internal!(
|
||||||
|
$ty,
|
||||||
|
$name,
|
||||||
|
::std::option::Option::Some($desc),
|
||||||
|
::std::option::Option::None
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
($ty:ty, $name:literal) => {
|
($ty:ty, $name:literal) => {
|
||||||
$crate::scalar_internal!($ty, $name, ::std::option::Option::None);
|
$crate::scalar_internal!(
|
||||||
|
$ty,
|
||||||
|
$name,
|
||||||
|
::std::option::Option::None,
|
||||||
|
::std::option::Option::None
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
($ty:ty) => {
|
($ty:ty) => {
|
||||||
$crate::scalar_internal!($ty, ::std::stringify!($ty), ::std::option::Option::None);
|
$crate::scalar_internal!(
|
||||||
|
$ty,
|
||||||
|
::std::stringify!($ty),
|
||||||
|
::std::option::Option::None,
|
||||||
|
::std::option::Option::None
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
macro_rules! scalar_internal {
|
macro_rules! scalar_internal {
|
||||||
($ty:ty, $name:expr, $desc:expr) => {
|
($ty:ty, $name:expr, $desc:expr, $specified_by_url:expr) => {
|
||||||
impl $crate::Type for $ty {
|
impl $crate::Type for $ty {
|
||||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||||
::std::borrow::Cow::Borrowed($name)
|
::std::borrow::Cow::Borrowed($name)
|
||||||
|
@ -122,6 +149,7 @@ macro_rules! scalar_internal {
|
||||||
description: $desc,
|
description: $desc,
|
||||||
is_valid: |value| <$ty as $crate::ScalarType>::is_valid(value),
|
is_valid: |value| <$ty as $crate::ScalarType>::is_valid(value),
|
||||||
visible: ::std::option::Option::None,
|
visible: ::std::option::Option::None,
|
||||||
|
specified_by_url: $specified_by_url,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@ impl<T> Type for OutputJson<T> {
|
||||||
description: None,
|
description: None,
|
||||||
is_valid: |_| true,
|
is_valid: |_| true,
|
||||||
visible: None,
|
visible: None,
|
||||||
|
specified_by_url: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,6 +111,7 @@ impl Type for Upload {
|
||||||
description: None,
|
description: None,
|
||||||
is_valid: |value| matches!(value, Value::String(_)),
|
is_valid: |value| matches!(value, Value::String(_)),
|
||||||
visible: None,
|
visible: None,
|
||||||
|
specified_by_url: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,12 @@ mod test_mod {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
pub async fn test_scalar_macro() {
|
pub async fn test_scalar_macro() {
|
||||||
scalar!(test_mod::MyValue, "MV", "DESC");
|
scalar!(
|
||||||
|
test_mod::MyValue,
|
||||||
|
"MV",
|
||||||
|
"DESC",
|
||||||
|
"https://tools.ietf.org/html/rfc4122"
|
||||||
|
);
|
||||||
|
|
||||||
struct Query;
|
struct Query;
|
||||||
|
|
||||||
|
@ -26,7 +31,7 @@ pub async fn test_scalar_macro() {
|
||||||
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
|
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
schema
|
schema
|
||||||
.execute(r#"{ __type(name:"MV") { name description } }"#)
|
.execute(r#"{ __type(name:"MV") { name description specifiedByURL } }"#)
|
||||||
.await
|
.await
|
||||||
.into_result()
|
.into_result()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -35,6 +40,7 @@ pub async fn test_scalar_macro() {
|
||||||
"__type": {
|
"__type": {
|
||||||
"name": "MV",
|
"name": "MV",
|
||||||
"description": "DESC",
|
"description": "DESC",
|
||||||
|
"specifiedByURL": "https://tools.ietf.org/html/rfc4122",
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user