byteorm_lib/rustgen/
mod.rs1use std::collections::HashMap;
2use std::fs;
3use quote::quote;
4use crate::Schema;
5
6pub mod client;
7pub mod jsonb;
8pub mod model;
9pub mod query;
10pub mod update;
11pub mod upsert;
12pub mod utils;
13
14pub use client::*;
15pub use jsonb::*;
16pub use model::*;
17pub use query::*;
18pub use update::*;
19pub use upsert::*;
20pub use utils::*;
21
22pub fn generate_rust_code(schema: &Schema) -> String {
23 let mut jsonb_defaults = HashMap::new();
24 for model in &schema.models {
25 for field in &model.fields {
26 if let Some(path) = field.get_jsonb_default_path() {
27 match fs::read_to_string(&path) {
28 Ok(content) => {
29 jsonb_defaults.insert((model.name.clone(), field.name.clone()), content);
30 }
31 Err(e) => {
32 eprintln!("Warning: Could not read default file '{}': {}", path, e);
33 }
34 }
35 }
36 }
37 }
38
39 let structs_and_impls = schema.models.iter().map(|model| {
40 generate_model_with_query_builder(model)
41 });
42
43 let client_struct = generate_client_struct(schema, &jsonb_defaults);
44 let jsonb_ext = generate_jsonb_ext();
45
46 let code = quote! {
47 use serde::{Deserialize, Serialize};
48 use chrono::{DateTime, Utc};
49 use tokio_postgres::{Client as PgClient, NoTls, Error};
50 use std::sync::Arc;
51 use once_cell::sync::Lazy;
52 use std::collections::HashMap;
53 pub fn expect_keys<T: Copy>(
54 map: &std::collections::HashMap<String, T>,
55 keys: &[&str]
56 ) -> Result<Vec<T>, &'static str> {
57 keys.iter()
58 .map(|k| map.get(*k).copied().ok_or("missing key"))
59 .collect()
60 }
61
62 fn calculate_json_diff(before: &serde_json::Value, after: &serde_json::Value) -> serde_json::Value {
63 let mut diff = serde_json::Map::new();
64 if let (Some(before_obj), Some(after_obj)) = (before.as_object(), after.as_object()) {
65 for (key, after_val) in after_obj {
66 if let Some(before_val) = before_obj.get(key) {
67 if before_val != after_val {
68 diff.insert(key.clone(), serde_json::json!({ "from": before_val, "to": after_val }));
69 }
70 } else {
71 diff.insert(key.clone(), serde_json::json!({ "added": after_val }));
72 }
73 }
74 for (key, before_val) in before_obj {
75 if !after_obj.contains_key(key) {
76 diff.insert(key.clone(), serde_json::json!({ "removed": before_val }));
77 }
78 }
79 }
80 serde_json::Value::Object(diff)
81 }
82
83 #jsonb_ext
84 #client_struct
85 #(#structs_and_impls)*
86 };
87
88 let file: syn::File = syn::parse2(code).unwrap();
89 prettyplease::unparse(&file)
90}