allow a feature gate option in codegen for use in frontend environments #648
Madoshakalaka
started this conversation in
Ideas
Replies: 3 comments
-
In the meantime, I crafted this super useful build.rs script. It's meant to be used in a frontend crate. It:
// build.rs
use convert_case::{Case, Casing};
use quote::quote;
use std::fs;
use syn::__private::Span;
use syn::{
AttrStyle, Attribute, Field, Fields, FieldsNamed, Ident, Item, ItemStruct, Path, PathSegment,
};
use syn::{VisPublic, Visibility};
struct TableFile {
file_name: String,
content: Vec<Item>,
}
impl TableFile {
fn transform_and_write(self) {
std::fs::create_dir("src/models").ok();
let Self {
content,
file_name: name,
} = self;
content
.into_iter()
.filter_map(|i| match i {
Item::Struct(i) => Some(i),
_ => None,
})
.filter_map(|i| match i.ident.to_string().as_str() {
"Model" => Some(transform_struct(i)),
_ => None,
})
.map(|s| {
let f: ::syn::File = ::syn::parse_quote!(
//! generated by custom build script
use serde::Deserialize;
#s
);
prettyplease::unparse(&f)
})
.for_each(|file| std::fs::write(format!("src/models/{name}"), file).unwrap());
}
}
fn transform_struct(i: ItemStruct) -> ItemStruct {
ItemStruct {
attrs: vec![Attribute {
pound_token: Default::default(),
style: AttrStyle::Outer,
bracket_token: Default::default(),
path: Path {
leading_colon: None,
segments: std::iter::once(PathSegment::from(Ident::new(
"derive",
Span::call_site(),
)))
.collect(),
},
tokens: quote! {(Deserialize)},
}],
vis: Visibility::Public(VisPublic {
pub_token: Default::default(),
}),
struct_token: i.struct_token,
ident: i.ident,
generics: i.generics,
fields: Fields::Named(FieldsNamed {
brace_token: Default::default(),
named: i
.fields
.into_iter()
.map(|f| Field {
attrs: vec![],
vis: Visibility::Public(VisPublic {
pub_token: Default::default(),
}),
ident: f.ident,
colon_token: f.colon_token,
ty: f.ty,
})
.collect(),
}),
semi_token: i.semi_token,
}
}
fn main() {
let entities_dir = "../backend/src/entities/";
println!("cargo:rerun-if-changed={entities_dir}");
let files = std::fs::read_dir(entities_dir).unwrap();
let (mod_uses, prelude_uses): (Vec<_>, Vec<_>) = files
.filter_map(|file| file.ok())
.filter_map(|e| {
let name = e.file_name();
(name != "mod.rs" && name != "prelude.rs").then(|| name.into_string().unwrap())
})
.map(|file_name| {
let name = format!("{entities_dir}{file_name}");
let mod_name = file_name.strip_suffix(".rs").unwrap().to_string();
let struct_name = mod_name.to_case(Case::Pascal);
let table = std::fs::read_to_string(&name).unwrap();
let content = syn::parse_file(&table).unwrap().items;
let table_file = TableFile { file_name, content };
table_file.transform_and_write();
let mod_name = Ident::new(&mod_name, Span::call_site());
let mod_name_ = mod_name.clone();
let struct_name = Ident::new(&struct_name, Span::call_site());
(
quote! {pub mod #mod_name;},
quote! {pub use super::#mod_name_::Model as #struct_name;},
)
})
.unzip();
let mod_file = syn::parse_quote! {
//! generated by custom build script
pub mod prelude;
#(#mod_uses)*
};
let prelude_file = syn::parse_quote! {
//! generated by custom build script
#(#prelude_uses)*
};
fs::write("src/models/mod.rs", prettyplease::unparse(&mod_file)).unwrap();
fs::write(
"src/models/prelude.rs",
prettyplease::unparse(&prelude_file),
)
.unwrap();
} # frontend/Cargo.toml
[build-dependencies]
syn = {version = "1.0", features = ["full"]}
quote = "1.0"
convert_case = "0.5"
prettyplease = "0.1" The expected directory structure:
|
Beta Was this translation helpful? Give feedback.
0 replies
-
Out of curiousity, what will SeaORM do at the frontend? |
Beta Was this translation helpful? Give feedback.
0 replies
-
The model structs generated by sea-orm help deserialize fetched data in the frontend |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
When the entities are shared between a backend and web frontend (like one built with yew), it's undesirable (and impossible maybe) to pack sqlx+sea-orm into the frontend, where the data are meant to be fetched by HTTP requests. The frontend does benefit from the structs and the serde traits though.
For this reason it might be desirable to allow a feature gate flag in
sea-orm-cli
, and it generates something like this when the flag is supplied:Beta Was this translation helpful? Give feedback.
All reactions