#api #yaml #generator #dsl #glue #business #open-api

nightly app cronus_cli

cronus API规范的命令行界面

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服务器

MIT 许可证

125KB
3K SLoC

Cronus

Crates.io

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包含一系列代码生成器,这些生成器受清洁架构的启发,为RustTypescriptOpenAPI等提供。

根据一个或多个配置文件(可以是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