use std::fs;
use std::path::Path;
pub fn make_model(name: &str) -> Result<(), Box<dyn std::error::Error>> {
let models_dir = Path::new("src/models");
if !models_dir.exists() {
fs::create_dir_all(models_dir)?;
}
let model_template = format!(r#"use serde::{{Deserialize, Serialize}};
use oxidite_db::{{Model, Connection, Result}};
#[derive(Debug, Serialize, Deserialize)]
pub struct {} {{
pub id: i64,
// Add your fields here
}}
#[async_trait::async_trait]
impl Model for {} {{
fn table_name() -> &'static str {{
"{}"
}}
async fn find(id: i64, conn: &dyn Connection) -> Result<Option<Self>> {{
// TODO: Implement find
todo!()
}}
async fn create(self, conn: &dyn Connection) -> Result<Self> {{
// TODO: Implement create
todo!()
}}
async fn update(&self, conn: &dyn Connection) -> Result<()> {{
// TODO: Implement update
todo!()
}}
async fn delete(&self, conn: &dyn Connection) -> Result<()> {{
// TODO: Implement delete
todo!()
}}
}}
"#, name, name, name.to_lowercase());
let filename = format!("src/models/{}.rs", name.to_lowercase());
fs::write(&filename, model_template)?;
println!("✅ Model created: {}", filename);
Ok(())
}
pub fn make_controller(name: &str) -> Result<(), Box<dyn std::error::Error>> {
let controllers_dir = Path::new("src/controllers");
if !controllers_dir.exists() {
fs::create_dir_all(controllers_dir)?;
}
let controller_template = format!(r#"use oxidite_core::{{Request, Response, Result, Error}};
use serde_json::json;
pub struct {} {{}}
impl {} {{
pub async fn index(_req: Request) -> Result<Response, Error> {{
Ok(Response::json(json!({{
"message": "List endpoint"
}})))
}}
pub async fn show(_req: Request) -> Result<Response, Error> {{
// TODO: Implement show
Ok(Response::json(json!({{
"message": "Show endpoint"
}})))
}}
pub async fn create(_req: Request) -> Result<Response, Error> {{
// TODO: Implement create
Ok(Response::json(json!({{
"message": "Create endpoint"
}})))
}}
pub async fn update(_req: Request) -> Result<Response, Error> {{
// TODO: Implement update
Ok(Response::json(json!({{
"message": "Update endpoint"
}})))
}}
pub async fn destroy(_req: Request) -> Result<Response, Error> {{
// TODO: Implement destroy
Ok(Response::json(json!({{
"message": "Destroy endpoint"
}})))
}}
}}
"#, name, name);
let filename = format!("src/controllers/{}.rs", name.to_lowercase());
fs::write(&filename, controller_template)?;
println!("✅ Controller created: {}", filename);
Ok(())
}
pub fn make_middleware(name: &str) -> Result<(), Box<dyn std::error::Error>> {
let middleware_dir = Path::new("src/middleware");
if !middleware_dir.exists() {
fs::create_dir_all(middleware_dir)?;
}
let middleware_template = format!(r#"use oxidite_core::{{Request, Response, Error}};
use tower::{{Service, Layer}};
use std::task::{{Context, Poll}};
use std::future::Future;
use std::pin::Pin;
#[derive(Clone)]
pub struct {}<S> {{
inner: S,
}}
impl<S> {}<S> {{
pub fn new(inner: S) -> Self {{
Self {{ inner }}
}}
}}
impl<S> Service<Request> for {}<S>
where
S: Service<Request, Response = Response, Error = Error> + Clone + Send + 'static,
S::Future: Send + 'static,
{{
type Response = S::Response;
type Error = S::Error;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {{
self.inner.poll_ready(cx)
}}
fn call(&mut self, req: Request) -> Self::Future {{
let mut inner = self.inner.clone();
Box::pin(async move {{
// Pre-processing
println!("Before request");
// Call inner service
let response = inner.call(req).await?;
// Post-processing
println!("After request");
Ok(response)
}})
}}
}}
pub struct {}Layer {{}}
impl {}Layer {{
pub fn new() -> Self {{
Self {{}}
}}
}}
impl<S> Layer<S> for {}Layer {{
type Service = {}<S>;
fn layer(&self, inner: S) -> Self::Service {{
{}<S>::new(inner)
}}
}}
"#, name, name, name, name, name, name, name, name);
let filename = format!("src/middleware/{}.rs", name.to_lowercase());
fs::write(&filename, middleware_template)?;
println!("✅ Middleware created: {}", filename);
Ok(())
}
pub fn make_service(name: &str) -> Result<(), Box<dyn std::error::Error>> {
let services_dir = Path::new("src/services");
if !services_dir.exists() {
fs::create_dir_all(services_dir)?;
}
let service_template = format!(r#"use std::sync::Arc;
use oxidite_db::Connection;
use serde::{{Deserialize, Serialize}};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct {}Input {{
// Add your input fields here
}}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct {}Output {{
// Add your output fields here
}}
#[derive(Clone)]
pub struct {}Service {{
// Add dependencies like database connection pool
// db: Arc<dyn Connection>,
}}
impl {}Service {{
pub fn new(/* db: Arc<dyn Connection> */) -> Self {{
Self {{
// db,
}}
}}
pub async fn execute(&self, input: {}Input) -> Result<{}Output, Box<dyn std::error::Error>> {{
// TODO: Implement business logic
todo!()
}}
}}
"#, name, name, name, name, name, name);
let filename = format!("src/services/{}.rs", name.to_lowercase());
fs::write(&filename, service_template)?;
println!("✅ Service created: {}", filename);
Ok(())
}
pub fn make_validator(name: &str) -> Result<(), Box<dyn std::error::Error>> {
let validators_dir = Path::new("src/validators");
if !validators_dir.exists() {
fs::create_dir_all(validators_dir)?;
}
let validator_template = format!(r#"use serde_json::Value;
use std::collections::HashMap;
pub struct {}Validator;
impl {}Validator {{
pub fn validate(data: &Value) -> Result<(), ValidationError> {{
let mut errors = HashMap::new();
// Add validation rules here
// Example:
// if let Some(field) = data.get("field_name") {{
// if !Self::is_valid_field(field) {{
// errors.insert("field_name".to_string(), "Field is invalid".to_string());
// }}
// }}
if !errors.is_empty() {{
return Err(ValidationError::new(errors));
}}
Ok(())
}}
// Add helper validation methods
// fn is_valid_field(value: &Value) -> bool {{
// // Implement validation logic
// true
// }}
}}
#[derive(Debug)]
pub struct ValidationError {{
pub errors: HashMap<String, String>,
}}
impl ValidationError {{
pub fn new(errors: HashMap<String, String>) -> Self {{
Self {{ errors }}
}}
}}
impl std::fmt::Display for ValidationError {{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {{
write!(f, "Validation failed: {{:?}}", self.errors)
}}
}}
impl std::error::Error for ValidationError {{}}
"#, name, name);
let filename = format!("src/validators/{}.rs", name.to_lowercase());
fs::write(&filename, validator_template)?;
println!("✅ Validator created: {}", filename);
Ok(())
}