1use axum::{routing::{delete, get, post, put}, Router
2};
3use tower_http::compression::CompressionLayer;
4use tower_http::trace::TraceLayer;
5use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
6
7use crate::handlers::projects;
8use crate::handlers::{environments, features, variants};
9
10mod api;
11mod errors;
12mod extractors;
13mod handlers;
14
15pub fn init_tracing() {
16 tracing_subscriber::registry()
17 .with(
18 tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| {
19 "flagrant_api=debug,flagrant=debug,tower_http=debug,axum::rejection=trace".into()
22 }),
23 )
24 .with(tracing_subscriber::fmt::layer())
25 .init();
26}
27
28pub async fn start_api_server() -> anyhow::Result<()> {
29 let pool = flagrant::init().await?;
30 let app = Router::new()
31 .route("/projects/:project_id", get(projects::fetch))
33
34 .route("/projects/:project_id/envs", get(environments::list))
36 .route("/projects/:project_id/envs", post(environments::create))
37 .route("/projects/:project_id/envs/:env_id", get(environments::fetch))
38
39 .route("/envs/:environment_id/features", get(features::list))
41 .route("/envs/:environment_id/features", post(features::create))
42 .route("/envs/:environment_id/features/:feature_id", get(features::fetch))
43 .route("/envs/:environment_id/features/:feature_id", put(features::update))
44 .route("/envs/:environment_id/features/:feature_id", delete(features::delete))
45
46 .route("/envs/:environment_id/features/:feature_id/variants", get(variants::list))
48 .route("/envs/:environment_id/features/:feature_id/variants", post(variants::create))
49 .route("/envs/:environment_id/variants/:variant_id", get(variants::fetch))
50 .route("/envs/:environment_id/variants/:variant_id", put(variants::update))
51 .route("/envs/:environment_id/variants/:variant_id", delete(variants::delete))
52
53 .nest("/api/v1",
55 Router::new()
56 .route("/envs/:environment_id/ident/:ident/features/:feature_name", get(api::get_feature)))
57
58 .with_state(pool)
59 .layer(CompressionLayer::new())
60 .layer(TraceLayer::new_for_http());
61
62
63 let listener = tokio::net::TcpListener::bind("127.0.0.1:3030")
64 .await
65 .unwrap();
66
67 tracing::info!("listening on {}", listener.local_addr().unwrap());
68 axum::serve(listener, app).await.unwrap();
69
70 Ok(())
71}