/ src / app.rs
app.rs
  1  use async_trait::async_trait;
  2  use loco_openapi::prelude::*;
  3  use loco_rs::{
  4      Result,
  5      app::{AppContext, Hooks, Initializer},
  6      bgworker::{BackgroundWorker, Queue},
  7      boot::{BootResult, StartMode, create_app},
  8      config::Config,
  9      controller::AppRoutes,
 10      db::{self, truncate_table},
 11      environment::Environment,
 12      task::Tasks,
 13  };
 14  use migration::Migrator;
 15  use std::path::Path;
 16  
 17  #[allow(unused_imports)]
 18  use crate::{
 19      controllers, initializers, models::_entities::users, tasks, workers::downloader::DownloadWorker,
 20  };
 21  
 22  pub struct App;
 23  #[async_trait]
 24  impl Hooks for App {
 25      fn app_name() -> &'static str {
 26          env!("CARGO_CRATE_NAME")
 27      }
 28  
 29      fn app_version() -> String {
 30          format!(
 31              "{} ({})",
 32              env!("CARGO_PKG_VERSION"),
 33              option_env!("BUILD_SHA")
 34                  .or(option_env!("GITHUB_SHA"))
 35                  .unwrap_or("dev")
 36          )
 37      }
 38  
 39      async fn boot(
 40          mode: StartMode,
 41          environment: &Environment,
 42          config: Config,
 43      ) -> Result<BootResult> {
 44          create_app::<Self, Migrator>(mode, environment, config).await
 45      }
 46  
 47      async fn initializers(_ctx: &AppContext) -> Result<Vec<Box<dyn Initializer>>> {
 48          Ok(vec![
 49              Box::new(initializers::view_engine::ViewEngineInitializer),
 50              Box::new(loco_openapi::OpenapiInitializerWithSetup::new(
 51                  |_ctx| {
 52                      #[derive(OpenApi)]
 53                      #[openapi(
 54                      modifiers(&SecurityAddon),
 55                      info(
 56                          title = "🧩 Microvisor Systems OpenAPI Spec 🧩",
 57                          description = "Beep Boop 🤖"
 58                      )
 59                  )]
 60                      struct ApiDoc;
 61                      ApiDoc::openapi()
 62                  },
 63                  None, // When using automatic schema collection only
 64                        // When using manual schema collection
 65                        // Manual schema collection can also be used at the same time as automatic schema collection
 66                        // Some(vec![controllers::album::api_routes()]),
 67              )),
 68          ])
 69      }
 70  
 71      fn routes(_ctx: &AppContext) -> AppRoutes {
 72          AppRoutes::with_default_routes() // controller routes below
 73              .add_route(controllers::auth::routes())
 74      }
 75  
 76      async fn after_routes(router: axum::Router, _ctx: &AppContext) -> Result<axum::Router> {
 77          async fn scalar_ui() -> axum::response::Html<String> {
 78              let cfg = serde_json::json!({
 79                "isLoading": true,
 80                "theme": "deepSpace",
 81                "hideClientButton": true,
 82                "defaultOpenAllTags": true,
 83                "expandAllResponses": true,
 84                "favicon": "/nix-mfarabi.svg" ,
 85                "expandAllModelSections": true,
 86                "url": "/api-docs/openapi.json",
 87              });
 88  
 89              axum::response::Html(scalar_api_reference::scalar_html_default(&cfg))
 90          }
 91  
 92          Ok(router.route("/scalar", axum::routing::get(scalar_ui)))
 93      }
 94  
 95      async fn connect_workers(ctx: &AppContext, queue: &Queue) -> Result<()> {
 96          queue.register(DownloadWorker::build(ctx)).await?;
 97          Ok(())
 98      }
 99  
100      #[allow(unused_variables)]
101      fn register_tasks(tasks: &mut Tasks) {
102          tasks.register(tasks::upload::Upload);
103          tasks.register(tasks::ve_direct::VeDirect);
104      }
105      async fn truncate(ctx: &AppContext) -> Result<()> {
106          truncate_table(&ctx.db, users::Entity).await?;
107          Ok(())
108      }
109      async fn seed(ctx: &AppContext, base: &Path) -> Result<()> {
110          db::seed::<users::ActiveModel>(&ctx.db, &base.join("users.yaml").display().to_string())
111              .await?;
112          Ok(())
113      }
114  }