use flow::FlowInfo; use json_store::JSONStore; use location::Location; use rocket::routes as route; use rocket::{http::Method, launch}; use tokio::sync::OnceCell; mod config; mod db; mod flow; mod integrity; mod item; mod json_store; mod location; mod routes; mod transaction; mod variant; pub static PG: OnceCell = OnceCell::const_new(); #[macro_export] macro_rules! get_pg { () => { if let Some(client) = $crate::PG.get() { client } else { let client = sqlx::postgres::PgPoolOptions::new() .max_connections(5) .connect(&std::env::var("DATABASE_URL").unwrap()) .await .unwrap(); $crate::PG.set(client).unwrap(); $crate::PG.get().unwrap() } }; } pub static ITEMDB: OnceCell = OnceCell::const_new(); #[macro_export] macro_rules! get_itemdb { () => { if let Some(client) = $crate::ITEMDB.get() { client } else { let itemdb = $crate::db::ItemDB::new("./itemdb").await; $crate::ITEMDB.set(itemdb).unwrap(); $crate::ITEMDB.get().unwrap() } }; } pub static LOCATIONS: OnceCell> = OnceCell::const_new(); #[macro_export] macro_rules! get_locations { () => { if let Some(client) = $crate::LOCATIONS.get() { client } else { let mut locations: $crate::json_store::JSONStore<$crate::location::Location> = $crate::JSONStore::new("./locations"); let loc_keys: Vec<_> = locations.keys().cloned().collect(); for loc in loc_keys { let location = locations.get_mut(&loc).unwrap(); location.id = loc.clone(); } $crate::LOCATIONS.set(locations).unwrap(); $crate::LOCATIONS.get().unwrap() } }; } // ░░░░░░░░░░▀▀▀██████▄▄▄░░░░░░░░░░ // ░░░░░░░░░░░░░░░░░▀▀▀████▄░░░░░░░ // ░░░░░░░░░░▄███████▀░░░▀███▄░░░░░ // ░░░░░░░░▄███████▀░░░░░░░▀███▄░░░ // ░░░░░░▄████████░░░░░░░░░░░███▄░░ // ░░░░░██████████▄░░░░░░░░░░░███▌░ ▒█▀▀█ █▀▀█ █▀▄▀█ █▀▄▀█ ▒█▀▀▄ ▒█▀▀█ // ░░░░░▀█████▀░▀███▄░░░░░░░░░▐███░ ▒█░░░ █░░█ █░▀░█ █░▀░█ ▒█░▒█ ▒█▀▀▄ // ░░░░░░░▀█▀░░░░░▀███▄░░░░░░░▐███░ ▒█▄▄█ ▀▀▀▀ ▀░░░▀ ▀░░░▀ ▒█▄▄▀ ▒█▄▄█ // ░░░░░░░░░░░░░░░░░▀███▄░░░░░███▌░ // ░░░░▄██▄░░░░░░░░░░░▀███▄░░▐███░░ // ░░▄██████▄░░░░░░░░░░░▀███▄███░░░ // ░█████▀▀████▄▄░░░░░░░░▄█████░░░░ // ░████▀░░░▀▀█████▄▄▄▄█████████▄░░ // ░░▀▀░░░░░░░░░▀▀██████▀▀░░░▀▀██░░ #[launch] async fn rocket() -> _ { env_logger::init(); let cors = rocket_cors::CorsOptions { allowed_origins: rocket_cors::AllowedOrigins::all(), allowed_methods: vec![Method::Get, Method::Post, Method::Options] .into_iter() .map(From::from) .collect(), allowed_headers: rocket_cors::AllowedHeaders::all(), allow_credentials: true, ..Default::default() } .to_cors() .expect("error creating CORS options"); let pg = get_pg!(); sqlx::migrate!("./migrations").run(pg).await.unwrap(); let config = config::get_config(); let itemdb = get_itemdb!().clone(); let locations = get_locations!().clone(); let flows: JSONStore = JSONStore::new("./flows"); integrity::verify_integrity(&config, &flows, &locations, &itemdb).await; rocket::build() .mount( "/", route![ routes::item::get_items_route, routes::item::item_route, routes::item::item_variants_page, routes::item::supply_log_route, routes::item::demand_log_route, routes::item::supply_route, routes::item::demand_route, routes::item::transaction_route, routes::item::inventory_route, routes::item::inventory_route_variant, routes::item::variant_stat_route, routes::item::unique_field_route, routes::item::location_info, routes::item::locations_info, routes::item::locations_list, routes::item::location_inventory, routes::flow::flow_info, routes::flow::flows_list, routes::item::expired_items_route, routes::item::min_items_route, routes::item::variant_price_history_by_origin, routes::flow::end_flow_route, routes::flow::continue_flow_route, routes::flow::create_flow_route, routes::item::move_transaction_route, routes::item::variant_price_latest_by_origin, routes::item::item_stat_route, routes::flow::active_flows_route, routes::flow::flow_api_route, routes::flow::create_flow_note_route, routes::flow::flow_notes_route ], ) .manage(itemdb) .manage(locations) .manage(flows) .manage(config) .attach(cors) }