199 lines
5.5 KiB
Markdown
199 lines
5.5 KiB
Markdown
Here's an updated full project specification including:
|
|
1. ✅ Unified builder for both creation and filtering
|
|
2. ✅ with_...() methods used for both creation and filtering
|
|
3. ✅ Auto-generated CRUD + list + filter + find methods
|
|
4. ✅ Database interface for persistence operations
|
|
5. ✅ Auto-generated registration code
|
|
6. ✅ 📜 Example Rhai script
|
|
7. ✅ 🔍 build.rs should output to src/gen/meeting_builder.rs
|
|
|
|
⸻
|
|
|
|
🧾 Project Spec: Rust → Rhai Builder Code Generator
|
|
|
|
🎯 Goal
|
|
|
|
Build a build.rs script that parses Rust structs annotated with #[builder] and generates Rhai-compatible unified builders with with_...() methods that populate a single field map used for both creation and filtering. Also generate CRUD operations that use a database interface.
|
|
|
|
⸻
|
|
|
|
📥 Input Example: src/models.rs
|
|
|
|
#[derive(Debug)]
|
|
pub struct Meeting {
|
|
pub id: String,
|
|
pub title: String,
|
|
pub description: String,
|
|
pub participants: Vec<String>,
|
|
pub start: String,
|
|
}
|
|
|
|
⸻
|
|
|
|
📤 Generated Code: src/gen/meeting_builder.rs
|
|
|
|
✅ 1. MeetingBuilder Struct
|
|
|
|
#[derive(Clone)]
|
|
pub struct MeetingBuilder {
|
|
pub fields: std::collections::HashMap<String, rhai::Dynamic>,
|
|
}
|
|
|
|
✅ 2. with_...() Methods (for each field)
|
|
|
|
impl MeetingBuilder {
|
|
pub fn with_title(mut self, value: &str) -> Self {
|
|
self.fields.insert("title".into(), value.into());
|
|
self
|
|
}
|
|
|
|
pub fn with_participants(mut self, value: Vec<rhai::Dynamic>) -> Self {
|
|
self.fields.insert("participants".into(), value.into());
|
|
self
|
|
}
|
|
|
|
pub fn get_fields(&mut self) -> rhai::Map {
|
|
self.fields.clone()
|
|
}
|
|
|
|
// CRUD operations
|
|
pub fn create(&mut self, db: &dyn Database) -> rhai::Dynamic {
|
|
db.create("meetings", self.get_fields())
|
|
}
|
|
|
|
pub fn find_by_id(&mut self, db: &dyn Database, id: &str) -> rhai::Dynamic {
|
|
db.find_by_id("meetings", id)
|
|
}
|
|
|
|
pub fn update(&mut self, db: &dyn Database, id: &str) -> rhai::Dynamic {
|
|
db.update("meetings", id, self.get_fields())
|
|
}
|
|
|
|
pub fn delete(&mut self, db: &dyn Database, id: &str) -> rhai::Dynamic {
|
|
db.delete("meetings", id)
|
|
}
|
|
|
|
pub fn list(&mut self, db: &dyn Database) -> rhai::Dynamic {
|
|
db.list("meetings")
|
|
}
|
|
|
|
pub fn filter(&mut self, db: &dyn Database) -> rhai::Dynamic {
|
|
db.filter("meetings", self.get_fields())
|
|
}
|
|
|
|
pub fn find(&mut self, db: &dyn Database) -> rhai::Dynamic {
|
|
db.find("meetings", self.get_fields())
|
|
}
|
|
}
|
|
|
|
✅ 3. Database Interface
|
|
|
|
pub trait Database {
|
|
fn create(&self, collection: &str, fields: rhai::Map) -> rhai::Dynamic;
|
|
fn find_by_id(&self, collection: &str, id: &str) -> rhai::Dynamic;
|
|
fn update(&self, collection: &str, id: &str, fields: rhai::Map) -> rhai::Dynamic;
|
|
fn delete(&self, collection: &str, id: &str) -> rhai::Dynamic;
|
|
fn list(&self, collection: &str) -> rhai::Dynamic;
|
|
fn filter(&self, collection: &str, query: rhai::Map) -> rhai::Dynamic;
|
|
fn find(&self, collection: &str, query: rhai::Map) -> rhai::Dynamic;
|
|
}
|
|
|
|
✅ 4. Rhai Registration
|
|
|
|
pub fn register_meeting_module(engine: &mut rhai::Engine) {
|
|
engine.register_type::<MeetingBuilder>();
|
|
engine.register_fn("meeting", MeetingBuilder::new);
|
|
|
|
engine.register_fn("with_title", MeetingBuilder::with_title);
|
|
engine.register_fn("with_participants", MeetingBuilder::with_participants);
|
|
engine.register_fn("get_fields", MeetingBuilder::get_fields);
|
|
|
|
// Register CRUD operations
|
|
engine.register_fn("create", MeetingBuilder::create);
|
|
engine.register_fn("find_by_id", MeetingBuilder::find_by_id);
|
|
engine.register_fn("update", MeetingBuilder::update);
|
|
engine.register_fn("delete", MeetingBuilder::delete);
|
|
engine.register_fn("list", MeetingBuilder::list);
|
|
engine.register_fn("filter", MeetingBuilder::filter);
|
|
engine.register_fn("find", MeetingBuilder::find);
|
|
}
|
|
|
|
⸻
|
|
|
|
✅ Example Rhai Script
|
|
|
|
// Create a meeting
|
|
let meeting_id = meeting()
|
|
.with_title("Project Sync")
|
|
.with_description("Check in with the team")
|
|
.with_participants(["timur", "eda"])
|
|
.with_start("2024-06-01T10:00")
|
|
.create(db);
|
|
|
|
// Find a meeting by ID
|
|
let meeting = meeting().find_by_id(db, meeting_id);
|
|
|
|
// Update a meeting
|
|
meeting()
|
|
.with_description("Updated description")
|
|
.update(db, meeting_id);
|
|
|
|
// Delete a meeting
|
|
meeting().delete(db, meeting_id);
|
|
|
|
// List all meetings
|
|
let all_meetings = meeting().list(db);
|
|
|
|
// Filter meetings by description
|
|
let filtered_meetings = meeting()
|
|
.with_description("Project Sync")
|
|
.filter(db);
|
|
|
|
// Find a specific meeting
|
|
let found_meeting = meeting()
|
|
.with_title("Project Sync")
|
|
.with_start("2024-06-01T10:00")
|
|
.find(db);
|
|
|
|
This script uses the same builder for all operations.
|
|
|
|
⸻
|
|
|
|
📂 Output File
|
|
|
|
Write generated code to:
|
|
|
|
src/gen/meeting_builder.rs
|
|
|
|
And include it in main.rs:
|
|
|
|
#[path = "gen/meeting_builder.rs"]
|
|
mod meeting_builder;
|
|
|
|
⸻
|
|
|
|
🔨 build.rs Responsibilities
|
|
• Use syn to parse src/models.rs
|
|
• Extract structs and fields
|
|
• Generate:
|
|
• MeetingBuilder struct with fields map
|
|
• All with_...() methods for Rhai
|
|
• get_fields() method
|
|
• CRUD + list + filter + find methods
|
|
• Database trait
|
|
• register_meeting_module(engine: &mut Engine) function
|
|
|
|
Output to src/gen/meeting_builder.rs.
|
|
|
|
⸻
|
|
|
|
✅ Success Criteria
|
|
• No duplication between filter/create logic
|
|
• Fluent API in Rhai
|
|
• Generated code compiles and integrates
|
|
• build.rs works as part of standard Rust build pipeline
|
|
• Easy to extend to more models (e.g., User, Task)
|
|
• Complete CRUD operations available
|
|
• Database abstraction for persistence
|
|
|
|
⸻ |