Skip to main content

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