11个版本
0.2.8 | 2024年4月28日 |
---|---|
0.2.7 | 2024年3月25日 |
0.2.1 | 2024年2月29日 |
0.1.1 | 2024年2月27日 |
#129 in HTTP服务器
125KB
3K SLoC
Cronus
Cronus旨在帮助您专注于仅业务逻辑代码,而不是其他胶水代码。
用法
$ cargo install cronus_cli
可以使用如下方式
$ cronus_cli <your api file>
并且可以进一步集成到构建过程中
// 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");
}
简介
Cronus包含一系列代码生成器,这些生成器受清洁架构的启发,为Rust、Typescript、OpenAPI等提供。
根据一个或多个配置文件(可以是YAML(.yml或.yaml)或我们的DSL(.api)),Cronus可以为不同库或框架提供支持的一组不同的控制器层(HTTP、GraphQL等)生成整洁的业务逻辑相关代码和胶水代码。
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可以生成以下业务逻辑接口代码
生成的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甚至可以更进一步生成以下控制器胶水代码
生成的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)
}
用例层生成器
- Rust
- Typescript
传输层生成器
- Axum(Rust)
- OpenAPI v3
- Tauri(进行中)
开发
通用
# Run the generators by the given API spec
$ cargo run -- examples/todo/main.api
文档
开发
$ pip install mkdocs-material
$ mkdocs serve -f mkdocs.yaml
发布
$ mkdocs gh-deploy
依赖
~8MB
~150K SLoC