rustapi_rs/lib.rs
1//! # RustAPI
2//!
3//! A FastAPI-like web framework for Rust.
4//!
5//! RustAPI combines Rust's performance and safety with FastAPI's "just write business logic"
6//! approach. It provides automatic OpenAPI documentation, declarative validation, and
7//! a developer-friendly experience.
8//!
9//! ## Quick Start
10//!
11//! ```rust,ignore
12//! use rustapi_rs::prelude::*;
13//!
14//! #[derive(Serialize, Schema)]
15//! struct Hello {
16//! message: String,
17//! }
18//!
19//! async fn hello() -> Json<Hello> {
20//! Json(Hello {
21//! message: "Hello, World!".to_string(),
22//! })
23//! }
24//!
25//! #[tokio::main]
26//! async fn main() -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
27//! RustApi::new()
28//! .route("/", get(hello))
29//! .run("127.0.0.1:8080")
30//! .await
31//! }
32//! ```
33//!
34//! ## Features
35//!
36//! - **DX-First**: Minimal boilerplate, intuitive API
37//! - **Type-Safe**: Compile-time route and schema validation
38//! - **Auto Documentation**: OpenAPI + Swagger UI out of the box
39//! - **Declarative Validation**: Pydantic-style validation on structs
40//! - **Batteries Included**: JWT, CORS, rate limiting (optional features)
41//!
42//! ## Optional Features
43//!
44//! Enable these features in your `Cargo.toml`:
45//!
46//! - `jwt` - JWT authentication middleware and `AuthUser<T>` extractor
47//! - `cors` - CORS middleware with builder pattern configuration
48//! - `rate-limit` - IP-based rate limiting middleware
49//! - `config` - Configuration management with `.env` file support
50//! - `cookies` - Cookie parsing extractor
51//! - `sqlx` - SQLx database error conversion to ApiError
52//! - `legacy-validator` - Compatibility mode for `validator::Validate`
53//! - `extras` - Meta feature enabling jwt, cors, and rate-limit
54//! - `full` - All optional features enabled
55//!
56//! ```toml
57//! [dependencies]
58//! rustapi-rs = { version = "0.1.300", features = ["jwt", "cors"] }
59//! ```
60
61// Re-export core functionality
62pub use rustapi_core::*;
63
64// Re-export macros
65pub use rustapi_macros::*;
66
67// Re-export extras (feature-gated)
68#[cfg(feature = "jwt")]
69pub use rustapi_extras::jwt;
70#[cfg(feature = "jwt")]
71pub use rustapi_extras::{
72 create_token, AuthUser, JwtError, JwtLayer, JwtValidation, ValidatedClaims,
73};
74
75#[cfg(feature = "cors")]
76pub use rustapi_extras::cors;
77#[cfg(feature = "cors")]
78pub use rustapi_extras::{AllowedOrigins, CorsLayer};
79
80#[cfg(feature = "rate-limit")]
81pub use rustapi_extras::rate_limit;
82#[cfg(feature = "rate-limit")]
83pub use rustapi_extras::RateLimitLayer;
84
85#[cfg(feature = "config")]
86pub use rustapi_extras::config;
87#[cfg(feature = "config")]
88pub use rustapi_extras::{
89 env_or, env_parse, load_dotenv, load_dotenv_from, require_env, Config, ConfigError, Environment,
90};
91
92#[cfg(feature = "sqlx")]
93pub use rustapi_extras::{convert_sqlx_error, SqlxErrorExt};
94
95// Re-export Phase 11 & Observability Features
96#[cfg(feature = "timeout")]
97pub use rustapi_extras::timeout;
98
99#[cfg(feature = "guard")]
100pub use rustapi_extras::guard;
101
102#[cfg(feature = "logging")]
103pub use rustapi_extras::logging;
104
105#[cfg(feature = "circuit-breaker")]
106pub use rustapi_extras::circuit_breaker;
107
108#[cfg(feature = "retry")]
109pub use rustapi_extras::retry;
110
111#[cfg(feature = "security-headers")]
112pub use rustapi_extras::security_headers;
113
114#[cfg(feature = "api-key")]
115pub use rustapi_extras::api_key;
116
117#[cfg(feature = "cache")]
118pub use rustapi_extras::cache;
119
120#[cfg(feature = "dedup")]
121pub use rustapi_extras::dedup;
122
123#[cfg(feature = "sanitization")]
124pub use rustapi_extras::sanitization;
125
126#[cfg(feature = "otel")]
127pub use rustapi_extras::otel;
128
129#[cfg(feature = "structured-logging")]
130pub use rustapi_extras::structured_logging;
131
132// Replay (time-travel debugging)
133#[cfg(feature = "replay")]
134pub use rustapi_extras::replay;
135
136// Re-export TOON (feature-gated)
137#[cfg(feature = "toon")]
138pub mod toon {
139 //! TOON (Token-Oriented Object Notation) support
140 //!
141 //! TOON is a compact format for LLM communication that reduces token usage by 20-40%.
142 //!
143 //! # Example
144 //!
145 //! ```rust,ignore
146 //! use rustapi_rs::toon::{Toon, Negotiate, AcceptHeader};
147 //!
148 //! // As extractor
149 //! async fn handler(Toon(data): Toon<MyType>) -> impl IntoResponse { ... }
150 //!
151 //! // As response
152 //! async fn handler() -> Toon<MyType> { Toon(my_data) }
153 //!
154 //! // Content negotiation (returns JSON or TOON based on Accept header)
155 //! async fn handler(accept: AcceptHeader) -> Negotiate<MyType> {
156 //! Negotiate::new(my_data, accept.preferred)
157 //! }
158 //! ```
159 pub use rustapi_toon::*;
160}
161
162// Re-export WebSocket support (feature-gated)
163#[cfg(feature = "ws")]
164pub mod ws {
165 //! WebSocket support for real-time bidirectional communication
166 //!
167 //! This module provides WebSocket functionality through the `WebSocket` extractor,
168 //! enabling real-time communication patterns like chat, live updates, and streaming.
169 //!
170 //! # Example
171 //!
172 //! ```rust,ignore
173 //! use rustapi_rs::ws::{WebSocket, Message};
174 //!
175 //! async fn websocket_handler(ws: WebSocket) -> impl IntoResponse {
176 //! ws.on_upgrade(|mut socket| async move {
177 //! while let Some(Ok(msg)) = socket.recv().await {
178 //! if let Message::Text(text) = msg {
179 //! socket.send(Message::Text(format!("Echo: {}", text))).await.ok();
180 //! }
181 //! }
182 //! })
183 //! }
184 //! ```
185 pub use rustapi_ws::*;
186}
187
188// Re-export View/Template support (feature-gated)
189#[cfg(feature = "view")]
190pub mod view {
191 //! Template engine support for server-side rendering
192 //!
193 //! This module provides Tera-based templating with the `View<T>` response type,
194 //! enabling server-side HTML rendering with template inheritance and context.
195 //!
196 //! # Example
197 //!
198 //! ```rust,ignore
199 //! use rustapi_rs::view::{Templates, View, ContextBuilder};
200 //!
201 //! #[derive(Clone)]
202 //! struct AppState {
203 //! templates: Templates,
204 //! }
205 //!
206 //! async fn index(State(state): State<AppState>) -> View<()> {
207 //! View::new(&state.templates, "index.html")
208 //! .with("title", "Home")
209 //! .with("message", "Welcome!")
210 //! }
211 //! ```
212 pub use rustapi_view::*;
213}
214
215/// Prelude module - import everything you need with `use rustapi_rs::prelude::*`
216pub mod prelude {
217 // Core types
218 pub use rustapi_core::validation::Validatable;
219 pub use rustapi_core::{
220 delete,
221 delete_route,
222 get,
223 get_route,
224 patch,
225 patch_route,
226 post,
227 post_route,
228 put,
229 put_route,
230 serve_dir,
231 sse_response,
232 // Error handling
233 ApiError,
234 AsyncValidatedJson,
235 Body,
236 ClientIp,
237 Created,
238 Extension,
239 HeaderValue,
240 Headers,
241 Html,
242 // Response types
243 IntoResponse,
244 // Extractors
245 Json,
246 KeepAlive,
247 // Multipart
248 Multipart,
249 MultipartConfig,
250 MultipartField,
251 NoContent,
252 Path,
253 Query,
254 Redirect,
255 // Request context
256 Request,
257 // Middleware
258 RequestId,
259 RequestIdLayer,
260 Response,
261 Result,
262 // Route type for macro-based routing
263 Route,
264 // Router
265 Router,
266 // App builder
267 RustApi,
268 RustApiConfig,
269 // Streaming responses
270 Sse,
271 SseEvent,
272 State,
273 // Static files
274 StaticFile,
275 StaticFileConfig,
276 StatusCode,
277 StreamBody,
278 TracingLayer,
279 Typed,
280 TypedPath,
281 UploadedFile,
282 ValidatedJson,
283 WithStatus,
284 };
285
286 // Compression middleware (feature-gated in core)
287 #[cfg(feature = "compression")]
288 pub use rustapi_core::middleware::{CompressionAlgorithm, CompressionConfig};
289 #[cfg(feature = "compression")]
290 pub use rustapi_core::CompressionLayer;
291
292 // Cookies extractor (feature-gated in core)
293 #[cfg(feature = "cookies")]
294 pub use rustapi_core::Cookies;
295
296 // Re-export the route! macro
297 pub use rustapi_core::route;
298
299 // Re-export TypedPath derive macro
300 pub use rustapi_macros::ApiError;
301 pub use rustapi_macros::TypedPath;
302
303 // Re-export validation - use validator derive macro directly
304 pub use rustapi_validate::v2::AsyncValidate;
305 pub use rustapi_validate::v2::Validate as V2Validate;
306 #[cfg(feature = "legacy-validator")]
307 pub use validator::Validate;
308
309 // Re-export OpenAPI schema derive
310 pub use rustapi_openapi::Schema;
311
312 // Re-export crates needed by Schema derive macro
313 // These are required for the macro-generated code to compile
314 pub use rustapi_openapi;
315 pub use serde_json;
316
317 // Re-export commonly used external types
318 pub use serde::{Deserialize, Serialize};
319 pub use tracing::{debug, error, info, trace, warn};
320
321 // JWT types (feature-gated)
322 #[cfg(feature = "jwt")]
323 pub use rustapi_extras::{
324 create_token, AuthUser, JwtError, JwtLayer, JwtValidation, ValidatedClaims,
325 };
326
327 // CORS types (feature-gated)
328 #[cfg(feature = "cors")]
329 pub use rustapi_extras::{AllowedOrigins, CorsLayer};
330
331 // Rate limiting types (feature-gated)
332 #[cfg(feature = "rate-limit")]
333 pub use rustapi_extras::RateLimitLayer;
334
335 // Configuration types (feature-gated)
336 #[cfg(feature = "config")]
337 pub use rustapi_extras::{
338 env_or, env_parse, load_dotenv, load_dotenv_from, require_env, Config, ConfigError,
339 Environment,
340 };
341
342 // SQLx types (feature-gated)
343 #[cfg(feature = "sqlx")]
344 pub use rustapi_extras::{convert_sqlx_error, SqlxErrorExt};
345
346 // TOON types (feature-gated)
347 #[cfg(feature = "toon")]
348 pub use rustapi_toon::{AcceptHeader, LlmResponse, Negotiate, OutputFormat, Toon};
349
350 // WebSocket types (feature-gated)
351 #[cfg(feature = "ws")]
352 pub use rustapi_ws::{Broadcast, Message, WebSocket, WebSocketStream};
353
354 // View/Template types (feature-gated)
355 #[cfg(feature = "view")]
356 pub use rustapi_view::{ContextBuilder, Templates, TemplatesConfig, View};
357}
358
359#[cfg(test)]
360mod tests {
361 use super::prelude::*;
362
363 #[test]
364 fn prelude_imports_work() {
365 // This test ensures prelude exports compile correctly
366 let _: fn() -> Result<()> = || Ok(());
367 }
368}