10 个版本
0.0.11 | 2024年6月12日 |
---|---|
0.0.10 | 2024年6月11日 |
0.0.8 | 2024年5月5日 |
0.0.7 | 2024年4月28日 |
0.0.1 | 2024年3月30日 |
#208 在 HTTP服务器
883 每月下载量
用于 nidrs-diesel
66KB
1K SLoC
Nidrs
借鉴 NestJS 框架,Nidrs 是一个基于 Rust 的企业级模块化开发框架,在 Axum 上开发和设计,同时受到了 NestJS 思想的启发。
Nidrs 提供了一种即插即用的应用程序架构,使开发者和团队能够轻松地创建高度可测试、可扩展、松耦合且易于维护的应用程序。
NestJS 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的框架。它使用渐进式 JavaScript,由 TypeScript 构建,并完全支持 TypeScript(但仍允许开发者使用纯 JavaScript 编写代码),并结合了 OOP(面向对象编程)、FP(函数式编程)和 FRP(函数式响应式编程)的元素。
重点
- 模块封装 v0.0.1
- 静态模块注册 v0.0.1
- 可配置模块注册 v0.0.2
- 依赖自动注入
- 服务自动注入 v0.0.1
- 动态服务注入 v0.0.3
- 服务作用域(全局)v0.0.1
- 服务作用域(模块)v0.0.6
- 服务实例作用域(单例)v0.0.1
- 服务实例作用域(请求级别)
- 服务实例作用域(注入级别)
- 分层架构
- 控制器层 v0.0.1
- 支持读取路由方法的元数据 v0.0.6
- 服务层 v0.0.1
- 模型层
- 控制器层 v0.0.1
- 模块生命周期钩子
- on_module_init v0.0.2
- on_module_destroy v0.0.5
- on_application_bootstrap(待定)
- on_application_shutdown(待定)
- 请求响应拦截器
- 控制器作用域 v0.0.4
- 全局作用域 v0.0.6
- 请求参数验证
- 基于请求参数验证的模拟服务
- 统一返回类型 v0.0.4
- 错误封装和处理 v0.0.4
- 统一添加路由前缀 v0.0.5
- app.default_prefix
- #[meta(disable_default_prefix)]
- 接口版本控制 v0.0.5
- app.default_version
- #[version("v1")]
- 与 tower 中间件兼容
- 自动 OpenAPI 文档
- API 调用接口生成
- 模块测试
- 支持在 wasm 环境中运行
- CLI 命令
- 完整的文档和示例
示例
example/src/app/controller.rs
use std::{collections::HashMap, sync::Arc};
use axum::{extract::{Query, State}, http::{version, StatusCode}, Json};
use nidrs::{throw, version, Exception, Inject, StateCtx};
use nidrs_macro::{controller, get, meta, post, uses};
use crate::{shared::fn_test::fn_test, AppError, AppResult};
use super::{dto::{Status}, service::AppService};
// #[uses(LogInterceptor)]
#[version("v1")]
#[meta(role = "admin", auth = "true")]
#[meta(test = true)]
#[controller("/app")]
#[derive(Debug, Default)]
pub struct AppController {
app_service: Inject<AppService>,
}
impl AppController {
#[meta(arr = ["user"])]
// #[uses(LogInterceptor)]
#[version("v2")]
#[get("/hello")]
pub async fn get_hello_world(&self, Query(q): Query<HashMap<String, String>>) -> AppResult<Status> {
println!("Query {:?}", q);
// fn_test()?;
Ok(Status { db: "ok".to_string(), redis: "ok".to_string() })
}
// #[uses(LogInterceptor)]
#[get("/hello2")]
pub async fn get_hello_world2(&self, Query(q): Query<HashMap<String, String>>) -> AppResult<String> {
println!("Query {:?}", q);
Ok(self.app_service.get_hello_world())
}
#[uses(LogInterceptor)]
#[post("/hello")]
pub async fn post_hello_world(&self, Query(q): Query<HashMap<String, String>>, Json(j): Json<serde_json::Value>) -> AppResult<String> {
println!("Query {:?}", q);
println!("Json {:?}", j);
Ok("Hello, World2!".to_string())
}
}
example/src/app/service.rs
use nidrs::Inject;
use nidrs_macro::{injectable, on_module_init};
use crate::user::service::UserService;
#[injectable()]
#[derive(Clone, Debug, Default)]
pub struct AppService{
user_service: Inject<UserService>
}
impl AppService {
pub fn get_hello_world(&self) -> String {
self.user_service.extract().get_hello_world()
}
pub fn get_hello_world2(&self) -> String {
"Hello, nidrs2xx333!".to_string()
}
}
example/src/app/mod.rs
use nidrs::default_uses;
use nidrs_macro::module;
pub mod controller;
pub mod dto;
pub mod exception;
pub mod service;
use crate::modules::conf::ConfModule;
use crate::modules::conf::ConfOptions;
use crate::modules::log::LogModule;
use crate::modules::user::UserModule;
use controller::AppController;
use service::AppService;
#[default_uses(LogInterceptor)]
#[module({
imports: [
ConfModule::for_root(ConfOptions{
log_level: "info".to_string(),
}),
LogModule,
UserModule,
],
controllers: [AppController],
services: [AppService],
exports: [AppService],
})]
#[derive(Clone, Debug, Default)]
pub struct AppModule;
example/src/main.rs
mod app;
mod conf;
mod user;
mod log;
mod shared;
pub use nidrs::AppResult;
pub use nidrs::AppError;
#[nidrs::main]
fn main() {
let app = nidrs::NidrsFactory::create(app::AppModule);
let app = app.default_prefix("/api/{version}");
let app = app.default_version("v1");
app.listen(3000).block();
}
运行示例
git clone https://github.com/nidrs/nidrs.git
cd nidrs/example
cargo run
启动日志
[nidrs] Registering module AppModule.
[nidrs] Registering interceptor LogInterceptor.
[nidrs] Registering controller AppController.
[nidrs] Registering router 'GET /api/v1/app/hello2'.
[nidrs] Registering router 'POST /api/v1/app/hello'.
[nidrs] Registering router 'GET /api/v2/app/hello'.
[nidrs] Registering service AppService.
[nidrs] Registering dyn service ConfOptions.
[nidrs] Registering module ConfModule.
[nidrs] Registering service ConfService.
[nidrs] Injecting ConfService.
[nidrs] Triggering event on_module_init for ConfService.
ConfService initialized with log_level: ConfOptions { log_level: "info" }
[nidrs] Registering module LogModule.
[nidrs] Registering service LogService.
[nidrs] Injecting LogService.
[nidrs] Registering module UserModule.
[nidrs] Registering controller UserController.
[nidrs] Registering router 'GET /api/v1/user/hello'.
[nidrs] Registering service UserService.
[nidrs] Injecting UserService.
[nidrs] Injecting UserController.
[nidrs] Injecting AppService.
[nidrs] Injecting AppController.
[nidrs] Injecting LogInterceptor.
[nidrs] Listening on 0.0.0.0:3000
赞助商
开源不容易,赞助也不容易。两者都需要勇气。我相信,那些给予爱的人将会得到爱的回报。愿你的好运从这次贡献开始~
关于
整个框架目前处于早期阶段,0.x.x版本的框架正在测试中。稳定版本从1.0开始。然而,如果你只是需要一个类似于Axum的高级框架,而不需要后面提到的附加功能,你仍然可以尝试一下。
最后,如果有任何有兴趣的个人想要贡献和开发,他们欢迎加入下面的Discord服务器,为Rust社区做出贡献。
依赖项
~13–24MB
~338K SLoC