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//! - `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}