use proc_macro2::TokenStream;
use quote::quote;
use syn::Ident;
pub enum RelationKindTokens {
BelongsTo,
HasMany,
HasOne,
}
pub struct RelationSpec<'a> {
pub field_name: &'a Ident,
pub owner: &'a Ident,
pub target: &'a Ident,
pub kind: RelationKindTokens,
pub local_key: &'a str,
pub foreign_key: &'a str,
}
pub fn emit(spec: RelationSpec<'_>) -> TokenStream {
let field_mod = spec.field_name;
let field_name_str = spec.field_name.to_string();
let owner = spec.owner;
let target = spec.target;
let local = spec.local_key;
let foreign = spec.foreign_key;
let kind = match spec.kind {
RelationKindTokens::BelongsTo => {
quote! { ::prax_query::relations::RelationKind::BelongsTo }
}
RelationKindTokens::HasMany => {
quote! { ::prax_query::relations::RelationKind::HasMany }
}
RelationKindTokens::HasOne => {
quote! { ::prax_query::relations::RelationKind::HasOne }
}
};
quote! {
pub mod #field_mod {
pub fn fetch() -> ::prax_query::relations::IncludeSpec {
::prax_query::relations::IncludeSpec::new(#field_name_str)
}
pub fn connect(
pk: impl Into<::prax_query::filter::FilterValue>,
) -> ::prax_query::nested::NestedWriteOp {
::prax_query::nested::NestedWriteOp::Connect {
relation: #field_name_str.into(),
pk: pk.into(),
}
}
pub fn create(
children: ::std::vec::Vec<
::std::vec::Vec<(
::std::string::String,
::prax_query::filter::FilterValue,
)>,
>,
) -> ::prax_query::nested::NestedWriteOp {
::prax_query::nested::NestedWriteOp::Create {
relation: #field_name_str.into(),
target_table: <super::super::#target
as ::prax_query::traits::Model>::TABLE_NAME
.into(),
foreign_key: #foreign.into(),
payload: children,
}
}
pub struct Relation;
impl ::prax_query::relations::RelationMeta for Relation {
type Owner = super::super::#owner;
type Target = super::super::#target;
const NAME: &'static str = #field_name_str;
const KIND: ::prax_query::relations::RelationKind = #kind;
const LOCAL_KEY: &'static str = #local;
const FOREIGN_KEY: &'static str = #foreign;
}
}
}
}