1pub mod cache;
60#[cfg(feature = "cli")]
61pub mod cli;
62pub mod config;
63pub mod constant;
64pub mod controller;
65pub mod entity;
66pub mod eps;
67pub mod error;
68pub mod event;
69pub mod middleware;
70pub mod module;
71pub mod service;
72pub mod tag;
73pub mod util;
74
75pub mod prelude {
77 #![allow(ambiguous_glob_reexports)]
78 pub use crate::cache::{CacheFactory, CacheStore, MemoryCache, RedisCache};
80
81 pub use crate::config::*;
83
84 pub use crate::constant::*;
86
87 pub use crate::controller::{BaseController, ControllerOption, CrudApi};
89
90 pub use crate::entity::*;
92
93 pub use crate::error::{CoolError, CoolResponse, CoolResult, PageResult, Pagination};
95
96 pub use crate::event::{global_event_manager, EventManager};
98
99 pub use crate::middleware::{
101 authority, exception_filter, request_log, AdminInfo, AppUserInfo, AuthorityConfig,
102 DepotAppUserExt, DepotExt, ExceptionFilter, JwtClaims,
103 };
104
105 pub use crate::module::{global_module_registry, Module, ModuleInfo, ModuleRegistry};
107
108 pub use crate::service::{BaseService, ModifyType, SimpleService};
110
111 pub use crate::eps::{
113 global_eps_registry, ColumnInfo as EpsColumnInfo, ControllerEps, EpsRegistry, EpsScope,
114 ModuleInfo as EpsModuleInfo, QueryOpInfo as EpsQueryOpInfo, RouteInfo as EpsRouteInfo,
115 };
116 pub use crate::tag::{global_url_tag_store, TagType, UrlTagStore};
117
118 pub use crate::util;
120
121 #[cfg(feature = "cli")]
123 pub use crate::cli::{check, clear_entities_file, generate_entities_file};
124
125 pub use async_trait::async_trait;
127 pub use salvo::prelude::*;
128 pub use sea_orm::{
129 entity::prelude::*, ActiveModelTrait, ColumnTrait, ConnectionTrait, DatabaseConnection,
130 EntityTrait, IntoActiveModel, ModelTrait, PaginatorTrait, QueryFilter, QueryOrder,
131 QuerySelect,
132 };
133 pub use serde::{Deserialize, Serialize};
134 pub use serde_json::{json, Value};
135 pub use validator::Validate;
136}
137
138pub const VERSION: &str = env!("CARGO_PKG_VERSION");
140
141pub fn init_logger() {
143 use tracing_subscriber::{fmt, prelude::*, EnvFilter};
144
145 tracing_subscriber::registry()
146 .with(fmt::layer())
147 .with(EnvFilter::from_default_env().add_directive("cool_core=info".parse().unwrap()))
148 .init();
149}
150
151pub struct CoolApp {
153 pub config: config::CoolConfig,
155 pub db: Option<sea_orm::DatabaseConnection>,
157 pub modules: module::ModuleRegistry,
159 pub events: event::EventManager,
161}
162
163impl CoolApp {
164 pub fn new(config: config::CoolConfig) -> Self {
166 Self {
167 config,
168 db: None,
169 modules: module::ModuleRegistry::new(),
170 events: event::EventManager::new(),
171 }
172 }
173
174 pub fn database(mut self, db: sea_orm::DatabaseConnection) -> Self {
176 self.db = Some(db);
177 self
178 }
179
180 pub fn register<M: module::Module + 'static>(self, module: M) -> Self {
182 self.modules.register(module);
183 self
184 }
185
186 pub fn build_router(&self, prefix: &str) -> salvo::Router {
188 self.modules.build_router(prefix)
189 }
190
191 pub async fn run(self, addr: impl Into<String>) -> std::io::Result<()> {
193 use salvo::prelude::*;
194 let addr = addr.into();
195 if let Err(e) = self.modules.init_all() {
197 tracing::error!("模块初始化失败: {}", e);
198 return Err(std::io::Error::other(e));
199 }
200
201 let router = self.build_router("/");
203 let doc = OpenApi::new("openapi", "0.0.1").merge_router(&router);
204 let router = router
205 .unshift(doc.into_router("/api-doc/openapi.json"))
206 .unshift(SwaggerUi::new("/api-doc/openapi.json").into_router("/swagger-ui"));
207 let listener = TcpListener::new(addr.clone()).bind().await;
209
210 tracing::info!("🚀 服务已启动: http://{}", addr);
211
212 self.events
214 .emit(
215 event::events::SERVER_READY,
216 event::ServerReadyEvent {
217 address: addr.to_string(),
218 port: 0,
219 },
220 )
221 .await;
222
223 Server::new(listener).serve(router).await;
225
226 Ok(())
227 }
228}
229
230impl Default for CoolApp {
231 fn default() -> Self {
232 Self::new(config::CoolConfig::default())
233 }
234}