use darling::ast::{Data, Fields}; use darling::util::Ignored; use darling::{FromDeriveInput, FromField, FromMeta, FromVariant}; use inflector::Inflector; use syn::{Attribute, Generics, Ident, Lit, LitBool, LitStr, Meta, Type, Visibility}; #[derive(FromMeta)] #[darling(default)] pub struct CacheControl { public: bool, private: bool, pub max_age: usize, } impl Default for CacheControl { fn default() -> Self { Self { public: true, private: false, max_age: 0, } } } impl CacheControl { pub fn is_public(&self) -> bool { !self.private && self.public } } #[derive(Debug)] pub enum DefaultValue { Default, Value(Lit), } impl FromMeta for DefaultValue { fn from_word() -> darling::Result { Ok(DefaultValue::Default) } fn from_value(value: &Lit) -> darling::Result { Ok(DefaultValue::Value(value.clone())) } } #[derive(Debug)] pub enum Visible { None, HiddenAlways, FnName(String), } impl FromMeta for Visible { fn from_value(value: &Lit) -> darling::Result { match value { Lit::Bool(LitBool { value: true, .. }) => Ok(Visible::None), Lit::Bool(LitBool { value: false, .. }) => Ok(Visible::HiddenAlways), Lit::Str(str) => Ok(Visible::FnName(str.value())), _ => Err(darling::Error::unexpected_lit_type(value)), } } } #[derive(FromField)] #[darling(attributes(graphql), forward_attrs(doc))] pub struct SimpleObjectField { pub ident: Option, pub ty: Type, pub vis: Visibility, pub attrs: Vec, #[darling(default)] pub skip: bool, #[darling(default)] pub name: Option, #[darling(default)] pub deprecation: Option, #[darling(default)] pub owned: bool, #[darling(default)] pub cache_control: CacheControl, #[darling(default)] pub external: bool, #[darling(default)] pub provides: Option, #[darling(default)] pub requires: Option, #[darling(default)] pub guard: Option, #[darling(default)] pub visible: Option, } #[derive(FromDeriveInput)] #[darling(attributes(graphql), forward_attrs(doc))] pub struct SimpleObject { pub ident: Ident, pub generics: Generics, pub attrs: Vec, pub data: Data, #[darling(default)] pub internal: bool, #[darling(default)] pub dummy: bool, #[darling(default)] pub name: Option, #[darling(default)] pub rename_fields: Option, #[darling(default)] pub rename_args: Option, #[darling(default)] pub cache_control: CacheControl, #[darling(default)] pub extends: bool, #[darling(default)] pub visible: Option, } #[derive(FromMeta, Default)] #[darling(default)] pub struct Argument { pub name: Option, pub desc: Option, pub default: Option, pub default_with: Option, pub validator: Option, pub key: bool, // for entity pub visible: Option, } #[derive(FromMeta, Default)] #[darling(default)] pub struct Object { pub internal: bool, pub name: Option, pub rename_fields: Option, pub rename_args: Option, pub cache_control: CacheControl, pub extends: bool, pub use_type_description: bool, pub visible: Option, } #[derive(FromMeta, Default)] #[darling(default)] pub struct ObjectField { pub skip: bool, pub entity: bool, pub name: Option, pub deprecation: Option, pub cache_control: CacheControl, pub external: bool, pub provides: Option, pub requires: Option, pub guard: Option, pub visible: Option, } #[derive(FromDeriveInput)] #[darling(attributes(graphql), forward_attrs(doc))] pub struct Enum { pub ident: Ident, pub generics: Generics, pub attrs: Vec, pub data: Data, #[darling(default)] pub internal: bool, #[darling(default)] pub name: Option, #[darling(default)] pub rename_items: Option, #[darling(default)] pub remote: Option, #[darling(default)] pub visible: Option, } #[derive(FromVariant)] #[darling(attributes(graphql), forward_attrs(doc))] pub struct EnumItem { pub ident: Ident, pub attrs: Vec, pub fields: Fields, #[darling(default)] pub name: Option, #[darling(default)] pub deprecation: Option, #[darling(default)] pub visible: Option, } #[derive(FromDeriveInput)] #[darling(attributes(graphql), forward_attrs(doc))] pub struct Union { pub ident: Ident, pub generics: Generics, pub attrs: Vec, pub data: Data, #[darling(default)] pub internal: bool, #[darling(default)] pub name: Option, #[darling(default)] pub visible: Option, } #[derive(FromVariant)] #[darling(attributes(graphql))] pub struct UnionItem { pub ident: Ident, pub fields: Fields, #[darling(default)] pub flatten: bool, } #[derive(FromField)] #[darling(attributes(graphql), forward_attrs(doc))] pub struct InputObjectField { pub ident: Option, pub ty: Type, pub vis: Visibility, pub attrs: Vec, #[darling(default)] pub name: Option, #[darling(default)] pub default: Option, #[darling(default)] pub default_with: Option, #[darling(default)] pub validator: Option, #[darling(default)] pub flatten: bool, #[darling(default)] pub visible: Option, } #[derive(FromDeriveInput)] #[darling(attributes(graphql), forward_attrs(doc))] pub struct InputObject { pub ident: Ident, pub generics: Generics, pub attrs: Vec, pub data: Data, #[darling(default)] pub internal: bool, #[darling(default)] pub name: Option, #[darling(default)] pub rename_fields: Option, #[darling(default)] pub visible: Option, } #[derive(FromMeta)] pub struct InterfaceFieldArgument { pub name: String, #[darling(default)] pub desc: Option, #[darling(rename = "type")] pub ty: LitStr, #[darling(default)] pub default: Option, #[darling(default)] pub default_with: Option, #[darling(default)] pub visible: Option, } #[derive(FromMeta)] pub struct InterfaceField { pub name: String, #[darling(rename = "type")] pub ty: LitStr, #[darling(default)] pub method: Option, #[darling(default)] pub desc: Option, #[darling(default, multiple, rename = "arg")] pub args: Vec, #[darling(default)] pub deprecation: Option, #[darling(default)] pub external: bool, #[darling(default)] pub provides: Option, #[darling(default)] pub requires: Option, #[darling(default)] pub visible: Option, } #[derive(FromVariant)] pub struct InterfaceMember { pub ident: Ident, pub fields: Fields, } #[derive(FromDeriveInput)] #[darling(attributes(graphql), forward_attrs(doc))] pub struct Interface { pub ident: Ident, pub generics: Generics, pub attrs: Vec, pub data: Data, #[darling(default)] pub internal: bool, #[darling(default)] pub name: Option, #[darling(default)] pub rename_fields: Option, #[darling(default)] pub rename_args: Option, #[darling(default, multiple, rename = "field")] pub fields: Vec, #[darling(default)] pub extends: bool, #[darling(default)] pub visible: Option, } #[derive(FromMeta, Default)] #[darling(default)] pub struct Scalar { pub internal: bool, pub name: Option, pub use_type_description: bool, pub visible: Option, } #[derive(FromMeta, Default)] #[darling(default)] pub struct Subscription { pub internal: bool, pub name: Option, pub rename_fields: Option, pub rename_args: Option, pub use_type_description: bool, } #[derive(FromMeta, Default)] #[darling(default)] pub struct SubscriptionFieldArgument { pub name: Option, pub desc: Option, pub default: Option, pub default_with: Option, pub validator: Option, pub visible: Option, } #[derive(FromMeta, Default)] #[darling(default)] pub struct SubscriptionField { pub skip: bool, pub name: Option, pub deprecation: Option, pub guard: Option, pub visible: Option, } #[derive(FromField)] pub struct MergedObjectField { pub ident: Option, pub ty: Type, } #[derive(FromDeriveInput)] #[darling(attributes(graphql), forward_attrs(doc))] pub struct MergedObject { pub ident: Ident, pub generics: Generics, pub attrs: Vec, pub data: Data, #[darling(default)] pub internal: bool, #[darling(default)] pub name: Option, #[darling(default)] pub cache_control: CacheControl, #[darling(default)] pub extends: bool, #[darling(default)] pub visible: Option, } #[derive(FromField)] pub struct MergedSubscriptionField { pub ident: Option, pub ty: Type, } #[derive(FromDeriveInput)] #[darling(attributes(graphql), forward_attrs(doc))] pub struct MergedSubscription { pub ident: Ident, pub generics: Generics, pub attrs: Vec, pub data: Data, #[darling(default)] pub internal: bool, #[darling(default)] pub name: Option, #[darling(default)] pub visible: Option, } #[derive(Debug, Copy, Clone, FromMeta)] pub enum RenameRule { #[darling(rename = "lowercase")] Lower, #[darling(rename = "UPPERCASE")] Upper, #[darling(rename = "PascalCase")] Pascal, #[darling(rename = "camelCase")] Camel, #[darling(rename = "snake_case")] Snake, #[darling(rename = "SCREAMING_SNAKE_CASE")] ScreamingSnake, } impl RenameRule { fn rename(&self, name: impl AsRef) -> String { match self { Self::Lower => name.as_ref().to_lowercase(), Self::Upper => name.as_ref().to_uppercase(), Self::Pascal => name.as_ref().to_pascal_case(), Self::Camel => name.as_ref().to_camel_case(), Self::Snake => name.as_ref().to_snake_case(), Self::ScreamingSnake => name.as_ref().to_screaming_snake_case(), } } } #[derive(Debug, Copy, Clone)] pub enum RenameTarget { Type, EnumItem, Field, Argument, } impl RenameTarget { fn rule(&self) -> RenameRule { match self { RenameTarget::Type => RenameRule::Pascal, RenameTarget::EnumItem => RenameRule::ScreamingSnake, RenameTarget::Field => RenameRule::Camel, RenameTarget::Argument => RenameRule::Camel, } } pub fn rename(&self, name: impl AsRef) -> String { self.rule().rename(name) } } pub trait RenameRuleExt { fn rename(&self, name: impl AsRef, target: RenameTarget) -> String; } impl RenameRuleExt for Option { fn rename(&self, name: impl AsRef, target: RenameTarget) -> String { self.unwrap_or(target.rule()).rename(name) } } #[derive(FromDeriveInput)] #[darling(forward_attrs(doc))] pub struct Description { pub ident: Ident, pub generics: Generics, pub attrs: Vec, #[darling(default)] pub internal: bool, }