DeriveRelatedEntity use async-graphql re-exported by seaography (#2469)

* DeriveRelatedEntity use `async-graphql` re-exported by `seaography`

* Optionally compile related_entity

* Update mod.rs

* private

---------

Co-authored-by: Chris Tsang <chris.2y3@outlook.com>
This commit is contained in:
Billy Chan 2025-01-10 23:15:18 +08:00 committed by GitHub
parent 1c0bf231af
commit 4376a29918
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 136 additions and 111 deletions

View File

@ -23,6 +23,7 @@ syn = { version = "2", default-features = false, features = ["parsing", "proc-ma
quote = { version = "1", default-features = false } quote = { version = "1", default-features = false }
heck = { version = "0.4", default-features = false } heck = { version = "0.4", default-features = false }
proc-macro2 = { version = "1", default-features = false } proc-macro2 = { version = "1", default-features = false }
proc-macro-crate = { version = "3.2.0", optional = true }
unicode-ident = { version = "1" } unicode-ident = { version = "1" }
[dev-dependencies] [dev-dependencies]
@ -34,4 +35,4 @@ default = ["derive"]
postgres-array = [] postgres-array = []
derive = ["bae"] derive = ["bae"]
strum = [] strum = []
seaography = [] seaography = ["proc-macro-crate"]

View File

@ -38,6 +38,7 @@ pub mod field_attr {
} }
} }
#[cfg(feature = "seaography")]
pub mod related_attr { pub mod related_attr {
use bae::FromAttributes; use bae::FromAttributes;

View File

@ -1,22 +1,25 @@
use heck::ToLowerCamelCase; #[cfg(feature = "seaography")]
use proc_macro2::TokenStream; mod private {
use quote::{quote, quote_spanned}; use heck::ToLowerCamelCase;
use proc_macro2::{Ident, Span, TokenStream};
use proc_macro_crate::{crate_name, FoundCrate};
use quote::{quote, quote_spanned};
use crate::derives::attributes::related_attr; use crate::derives::attributes::related_attr;
enum Error { enum Error {
InputNotEnum, InputNotEnum,
InvalidEntityPath, InvalidEntityPath,
Syn(syn::Error), Syn(syn::Error),
} }
struct DeriveRelatedEntity { struct DeriveRelatedEntity {
entity_ident: TokenStream, entity_ident: TokenStream,
ident: syn::Ident, ident: syn::Ident,
variants: syn::punctuated::Punctuated<syn::Variant, syn::token::Comma>, variants: syn::punctuated::Punctuated<syn::Variant, syn::token::Comma>,
} }
impl DeriveRelatedEntity { impl DeriveRelatedEntity {
fn new(input: syn::DeriveInput) -> Result<Self, Error> { fn new(input: syn::DeriveInput) -> Result<Self, Error> {
let sea_attr = related_attr::SeaOrm::try_from_attributes(&input.attrs) let sea_attr = related_attr::SeaOrm::try_from_attributes(&input.attrs)
.map_err(Error::Syn)? .map_err(Error::Syn)?
@ -82,9 +85,21 @@ impl DeriveRelatedEntity {
}) })
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
// Get the path of the `async-graphql` on the application's Cargo.toml
let async_graphql_crate = match crate_name("async-graphql") {
// if found, use application's `async-graphql`
Ok(FoundCrate::Name(name)) => {
let ident = Ident::new(&name, Span::call_site());
quote! { #ident }
}
Ok(FoundCrate::Itself) => quote! { async_graphql },
// if not, then use the `async-graphql` re-exported by `seaography`
Err(_) => quote! { seaography::async_graphql },
};
Ok(quote! { Ok(quote! {
impl seaography::RelationBuilder for #ident { impl seaography::RelationBuilder for #ident {
fn get_relation(&self, context: & 'static seaography::BuilderContext) -> async_graphql::dynamic::Field { fn get_relation(&self, context: & 'static seaography::BuilderContext) -> #async_graphql_crate::dynamic::Field {
let builder = seaography::EntityObjectRelationBuilder { context }; let builder = seaography::EntityObjectRelationBuilder { context };
let via_builder = seaography::EntityObjectViaRelationBuilder { context }; let via_builder = seaography::EntityObjectViaRelationBuilder { context };
match self { match self {
@ -106,10 +121,10 @@ impl DeriveRelatedEntity {
_ => Err(syn::Error::new_spanned(lit, "attribute must be a string")), _ => Err(syn::Error::new_spanned(lit, "attribute must be a string")),
} }
} }
} }
/// Method to derive a Related enumeration /// Method to derive a Related enumeration
pub fn expand_derive_related_entity(input: syn::DeriveInput) -> syn::Result<TokenStream> { pub fn expand_derive_related_entity(input: syn::DeriveInput) -> syn::Result<TokenStream> {
let ident_span = input.ident.span(); let ident_span = input.ident.span();
match DeriveRelatedEntity::new(input) { match DeriveRelatedEntity::new(input) {
@ -122,4 +137,16 @@ pub fn expand_derive_related_entity(input: syn::DeriveInput) -> syn::Result<Toke
}), }),
Err(Error::Syn(err)) => Err(err), Err(Error::Syn(err)) => Err(err),
} }
}
} }
#[cfg(not(feature = "seaography"))]
mod private {
use proc_macro2::TokenStream;
pub fn expand_derive_related_entity(_: syn::DeriveInput) -> syn::Result<TokenStream> {
Ok(TokenStream::new())
}
}
pub use private::*;

View File

@ -675,13 +675,9 @@ pub fn derive_relation(input: TokenStream) -> TokenStream {
#[proc_macro_derive(DeriveRelatedEntity, attributes(sea_orm))] #[proc_macro_derive(DeriveRelatedEntity, attributes(sea_orm))]
pub fn derive_related_entity(input: TokenStream) -> TokenStream { pub fn derive_related_entity(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput); let input = parse_macro_input!(input as DeriveInput);
if cfg!(feature = "seaography") {
derives::expand_derive_related_entity(input) derives::expand_derive_related_entity(input)
.unwrap_or_else(Error::into_compile_error) .unwrap_or_else(Error::into_compile_error)
.into() .into()
} else {
TokenStream::new()
}
} }
/// The DeriveMigrationName derive macro will implement `sea_orm_migration::MigrationName` for a migration. /// The DeriveMigrationName derive macro will implement `sea_orm_migration::MigrationName` for a migration.