Skip to content

Commit

Permalink
docs: add document comment
Browse files Browse the repository at this point in the history
  • Loading branch information
Kilerd committed Dec 31, 2024
1 parent fe42a06 commit 24f0c76
Show file tree
Hide file tree
Showing 6 changed files with 218 additions and 34 deletions.
63 changes: 63 additions & 0 deletions gotcha/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,66 @@
//! # Gotcha
//!
//! Gotcha is an enhanced web framework based on Axum, providing additional features and conveniences
//! for building web applications in Rust.
//!
//! ## Features
//!
//! - Built on top of Axum for high performance and reliability
//! - OpenAPI documentation generation (optional)
//! - Prometheus metrics integration (optional)
//! - CORS support (optional)
//! - Static file serving (optional)
//! - Task scheduling
//! - Configuration management
//! - Message system
//! - State management
//!
//! ## Example
//!
//! ```no_run
//! use gotcha::{async_trait, ConfigWrapper, GotchaApp, GotchaContext, GotchaRouter, Responder, State};
//! use serde::{Deserialize, Serialize};
//!
//! pub async fn hello_world(_state: State<ConfigWrapper<Config>>) -> impl Responder {
//! "hello world"
//! }
//!
//! #[derive(Debug, Deserialize, Serialize, Clone)]
//! pub struct Config {
//! pub name: String,
//! }
//!
//! pub struct App {}
//!
//! #[async_trait]
//! impl GotchaApp for App {
//! type State = ();
//! type Config = Config;
//!
//! fn routes(&self, router: GotchaRouter<GotchaContext<Self::State, Self::Config>>) -> GotchaRouter<GotchaContext<Self::State, Self::Config>> {
//! router.get("/", hello_world)
//! }
//!
//! async fn state(&self, _config: &ConfigWrapper<Self::Config>) -> Result<Self::State, Box<dyn std::error::Error>> {
//! Ok(())
//! }
//! }
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! App {}.run().await?;
//! Ok(())
//! }
//! ```
//!
//! ## Optional Features
//!
//! - `openapi` - Enables OpenAPI documentation generation
//! - `prometheus` - Enables Prometheus metrics
//! - `cors` - Enables CORS support
//! - `static_files` - Enables static file serving capabilities
//!
use std::net::{Ipv4Addr, SocketAddrV4};
use std::str::FromStr;

Expand Down
11 changes: 11 additions & 0 deletions gotcha/src/message.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
//! # Message Module
//!
//! This module provides a message handling system for Gotcha web applications.
//! It allows for the asynchronous handling of messages and the spawning of tasks to handle them.
//!
//! ## Features
//!
//! - Asynchronous message handling
//! - Task spawning for message processing
//! - Type-safe message handling
//!
use std::sync::Arc;

use async_trait::async_trait;
Expand Down
33 changes: 33 additions & 0 deletions gotcha/src/openapi.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,35 @@
//! # OpenAPI Module
//!
//! This module provides OpenAPI documentation generation capabilities for Gotcha web applications.
//! It is enabled by default but can be disabled by opting out of the "openapi" feature.
//!
//! ## Features
//!
//! - Automatic OpenAPI spec generation from route definitions
//! - Support for operation parameters, request bodies, and responses
//! - Built-in Redoc and Scalar UI for API documentation viewing
//! - Grouping operations by tags
//! - Parameter validation and type information
//!
//! ## Example
//!
//! ```rust,no_run
//! use gotcha::{GotchaRouter, Operable};
//!
//! #[openapi(group = "Users")]
//! async fn get_user() -> impl Responder {
//! // Handler implementation
//! }
//!
//! fn routes(router: GotchaRouter) -> GotchaRouter {
//! router.get("/users/:id", get_user)
//! }
//! ```
//!
//! The OpenAPI documentation will be automatically generated and served at `/docs`
//! and `/docs/scalar` endpoints when the feature is enabled.

use std::collections::{BTreeMap, HashMap};

use axum::response::Html;
Expand All @@ -9,6 +41,7 @@ use once_cell::sync::Lazy;

use crate::Responder;


pub(crate) async fn openapi_html() -> impl Responder {
Html(include_str!("../statics/redoc.html"))
}
Expand Down
70 changes: 70 additions & 0 deletions gotcha/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,31 @@ use crate::Operable;

macro_rules! implement_method {
($method:expr, $fn_name: tt ) => {
/// quick way to add a method route to the router
/// # Examples
///
/// ```rust,no_run
/// use gotcha::{GotchaRouter, Responder};
///
/// async fn hello_world() -> impl Responder {
/// "Hello World!"
/// }
///
/// let router = GotchaRouter::default()
/// .$fn_name("/", hello_world);
/// ```
pub fn $fn_name<H: Handler<T, State>, T: 'static>(self, path: &str, handler: H) -> Self {
self.method_route(path, $method, handler)
}
};
}

/// # GotchaRouter
///
/// A router for Gotcha web applications.
pub struct GotchaRouter<State = ()> {
#[cfg(feature = "openapi")]
/// The operations for the router.
pub(crate) operations: HashMap<(String, Method), Operation>,
pub(crate) router: Router<State>,
}
Expand All @@ -43,6 +60,19 @@ impl<State: Clone + Send + Sync + 'static> Default for GotchaRouter<State> {
impl<State: Clone + Send + Sync + 'static> GotchaRouter<State> {


/// add a route to the router
/// # Examples
///
/// ```rust,no_run
/// use gotcha::{GotchaRouter, Responder};
///
/// async fn hello_world() -> impl Responder {
/// "Hello World!"
/// }
///
/// let router = GotchaRouter::default()
/// .route("/", get(hello_world));
/// ```
pub fn route(self, path: &str, method_router: MethodRouter<State>) -> Self {
Self {
#[cfg(feature = "openapi")]
Expand All @@ -51,6 +81,19 @@ impl<State: Clone + Send + Sync + 'static> GotchaRouter<State> {
}
}

/// add a method route to the router
/// # Examples
///
/// ```rust,no_run
/// use gotcha::{GotchaRouter, Responder};
///
/// async fn hello_world() -> impl Responder {
/// "Hello World!"
/// }
///
/// let router = GotchaRouter::default()
/// .method_route("/", MethodFilter::GET, hello_world);
/// ```
pub fn method_route<H, T>(mut self, path: &str, method: MethodFilter, handler: H) -> Self
where
H: Handler<T, State>,
Expand Down Expand Up @@ -94,6 +137,15 @@ impl<State: Clone + Send + Sync + 'static> GotchaRouter<State> {
implement_method!(MethodFilter::OPTIONS, options);
implement_method!(MethodFilter::TRACE, trace);

/// nest a router inside another router
/// # Examples
///
/// ```rust,no_run
/// use gotcha::{GotchaRouter, Responder};
///
/// let router = GotchaRouter::default()
/// .nest("/users", GotchaRouter::default());
/// ```
pub fn nest(self, path: &str, router: Self) -> Self {
#[cfg(feature = "openapi")]
let operations = router
Expand All @@ -112,6 +164,15 @@ impl<State: Clone + Send + Sync + 'static> GotchaRouter<State> {
}
}

/// merge two routers
/// # Examples
///
/// ```rust,no_run
/// use gotcha::{GotchaRouter};
///
/// let router = GotchaRouter::default()
/// .merge(GotchaRouter::default());
/// ```
pub fn merge(self, other: Self) -> Self {
Self {
#[cfg(feature = "openapi")]
Expand All @@ -120,6 +181,15 @@ impl<State: Clone + Send + Sync + 'static> GotchaRouter<State> {
}
}

/// add a layer to the router
/// # Examples
///
/// ```rust,no_run
/// use gotcha::{GotchaRouter};
///
/// let router = GotchaRouter::default()
/// .layer(MyLayer::default());
/// ```
pub fn layer<L>(self, layer: L) -> Self
where
L: Layer<Route> + Clone + Send + 'static,
Expand Down
34 changes: 0 additions & 34 deletions gotcha/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,34 +0,0 @@
pub trait ExtendableState<NewState> {
type Ret;
fn extend(self, next: NewState) -> Self::Ret;
}

impl<NewState> ExtendableState<NewState> for () {
type Ret = (NewState,);

fn extend(self, next: NewState) -> Self::Ret {
(next,)
}
}

impl<T, NewState> ExtendableState<NewState> for (T,) {
type Ret = (T, NewState);

fn extend(self, next: NewState) -> Self::Ret {
(self.0, next)
}
}

impl<T1, T2, NewState> ExtendableState<NewState> for (T1, T2) {
type Ret = (T1, T2, NewState);
fn extend(self, next: NewState) -> Self::Ret {
(self.0, self.1, next)
}
}

impl<T1, T2, T3, NewState> ExtendableState<NewState> for (T1, T2, T3) {
type Ret = (T1, T2, T3, NewState);
fn extend(self, next: NewState) -> Self::Ret {
(self.0, self.1, self.2, next)
}
}
41 changes: 41 additions & 0 deletions gotcha/src/task.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,44 @@
//! # Task Module
//!
//! This module provides task scheduling capabilities for Gotcha web applications.
//! It supports both cron-based and interval-based task scheduling.
//!
//! ## Features
//!
//! - Cron expression based scheduling
//! - Fixed interval scheduling
//! - Async task execution
//! - Access to application context in tasks
//!
//! ## Examples
//!
//! ```rust,no_run
//! use gotcha::{GotchaContext, TaskScheduler};
//! use std::time::Duration;
//!
//! // Create a task scheduler
//! let scheduler = TaskScheduler::new(context);
//!
//! // Schedule a cron task
//! scheduler.cron("daily-cleanup", "0 0 * * *", |ctx| async move {
//! // Task implementation
//! });
//!
//! // Schedule an interval task
//! scheduler.interval("heartbeat", Duration::from_secs(60), |ctx| async move {
//! // Task implementation
//! });
//! ```
//!
//! Tasks have access to the application context and can be used for:
//! - Periodic cleanup jobs
//! - Data synchronization
//! - Health checks
//! - Background processing
//! - Scheduled notifications
//!

use std::future::Future;
use std::str::FromStr;

Expand Down

0 comments on commit 24f0c76

Please sign in to comment.