11 releases
0.2.8 | Apr 28, 2024 |
---|---|
0.2.7 | Mar 25, 2024 |
0.2.1 | Feb 29, 2024 |
0.1.1 | Feb 27, 2024 |
#712 in HTTP server
125KB
3K
SLoC
Cronus
Cronus aims to help you focusing on business logic code only instead of the other glue code.
Online playground is here. Documentation is here.
Usage
$ cargo install cronus_cli
And it can be used like:
$ cronus_cli <your api file>
And it can be further integrated into the building process:
// build.rs
fn main() {
let dir: String = env::var("CARGO_MANIFEST_DIR").unwrap();
// Suppose your api file named "main.api" is located at
// same directory with the Cargo.toml.
//
// If your api file does not have the name "main.api",
// the path should point to the that file instead of
// a simple directory.
std::process::Command::new("cronus_cli")
.arg(&dir)
.output()
.expect("failed to generate API");
}
Introduction
Cronus contains a list of code generators, which insipred by the Clean Architecture, for Rust, Typescript, OpenAPI, and more.
According to one or more configuration files( can be either in YAML (.yml or .yaml) or our DSL(.api) ), Cronus can generate nice and clean business logic related code and glue code for a bunch of different controller layers(HTTP, GraphQL, etc.) powered by different libraries or frameworks.
Cronus
# More fine-grained configuration can be found at documentation
# For 'rust' generator
global [generator.rust.file = "src/generated.rs"]
global [generator.rust.async]
global [generator.rust.async_trait]
# For 'rust_axum' generator
global [generator.rust_axum.file = "src/generated.rs"]
struct Todo {
id: string
content: string
}
usecase Todo {
createTodo {
in {
content: string
}
out {
todo: Todo
}
}
}
Cronus can be used to generate the following Business Logic interface code:
Generated Rust
use serde::{Deserialize, Serialize};
use async_trait::async_trait;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Todo {
pub id: String,
pub content: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct CreateTodoRequest {
pub content: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct CreateTodoResponse {
pub todo: Todo,
}
#[async_trait]
pub trait TodoUsecase {
async fn create_todo(&self, request: CreateTodoRequest) -> Result<CreateTodoResponse, Box<dyn std::error::Error>>;
}
Cronus can even step further to generate the following Controller glue code:
Generated Rust (Axum)
use axum::{
extract::State,
http::{header, Response, StatusCode},
response::IntoResponse,
Extension, Json,
Router
};
pub async fn create_todo(State(state): State<std::sync::Arc<Usecases>>, Json(request): Json<CreateTodoRequest>) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
match state.todo.create_todo(request).await {
Ok(res) => {
Ok(Json(res))
},
Err(err) => {
let mut err_obj = serde_json::Map::new();
err_obj.insert("message".to_owned(), serde_json::Value::from(err.to_string()));
Err((StatusCode::BAD_REQUEST, Json(serde_json::Value::Object(err_obj))))
},
}
}
#[derive(Clone)]
pub struct Usecases {
pub todo: std::sync::Arc<dyn TodoUsecase + Send + Sync>,
}
pub fn router_init(usecases: std::sync::Arc<Usecases>) -> Router {
Router::new()
.route("", axum::routing::post(create_todo))
.with_state(usecases)
}
Usecase Layer Generators
- Rust
- Typescript
Transportation Layer Generator
- Axum(Rust)
- OpenAPI v3
- Tauri (work in progress)
Dev
Common
# Run the generators by the given API spec
$ cargo run -- examples/todo/main.api
Docs
Dev
$ pip install mkdocs-material
$ mkdocs serve -f mkdocs.yaml
Publish
$ mkdocs gh-deploy
Dependencies
~8MB
~146K SLoC