(* Main entry point for website monitor application *) open Dream open Lwt.Infix let () = (* Create database pool *) ignore (Database.create_pool ()); (* Initialize database schema *) Lwt.catch (fun () -> Database.init_schema ()) (fun _exn -> Lwt.return_unit) (* Continue even if init fails *) (* CORS middleware *) let cors = Dream.middleware @@ fun next req -> let origin = Dream.header "Origin" req |> Option.value ~default:"*" in Dream.respond_with_headers [ ("Access-Control-Allow-Origin", origin); ("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); ("Access-Control-Allow-Headers", "Content-Type, Authorization"); ("Access-Control-Allow-Credentials", "true"); ] @@ fun res -> next req res in (* Logging middleware *) let logger = Dream.middleware @@ fun next req -> Lwt.finalize (fun () -> Logs.app (fun m -> m "%s %s" (Dream.method_str req) (Dream.target req)); next req) (fun () -> Lwt.return_unit) in (* Routes *) let router = Dream.group [ (* Health check *) Dream.get "/health" @@ fun _ -> Lwt.return @@ Dream.json `Ok (Yojson.Basic.(assoc ["status", `String "healthy"])); (* API routes *) Dream.scope "/api" (Dream.group [ (* Website monitoring endpoints *) Dream.get "/websites" Website_monitor_api.list_websites; Dream.post "/websites" Website_monitor_api.create_website; Dream.get "/websites/:id" Website_monitor_api.get_website; Dream.put "/websites/:id" Website_monitor_api.update_website; Dream.delete "/websites/:id" Website_monitor_api.delete_website; Dream.post "/websites/:id/check" Website_monitor_api.check_website_now; Dream.get "/websites/:id/history" Website_monitor_api.get_website_history; Dream.get "/websites/:id/status" Website_monitor_api.get_website_status; (* Alert configuration endpoints *) Dream.get "/alerts" Website_monitor_api.list_alerts; Dream.post "/alerts" Website_monitor_api.create_alert; Dream.get "/alerts/:id" Website_monitor_api.get_alert; Dream.put "/alerts/:id" Website_monitor_api.update_alert; Dream.delete "/alerts/:id" Website_monitor_api.delete_alert; (* Stats endpoints *) Dream.get "/stats/summary" Website_monitor_api.get_stats_summary; ]); (* Admin dashboard routes *) Dream.get "/" Website_monitor_ui.serve_dashboard; Dream.get "/dashboard" Website_monitor_ui.serve_dashboard; Dream.get "/dashboard/websites" Website_monitor_ui.serve_websites_page; Dream.get "/dashboard/alerts" Website_monitor_ui.serve_alerts_page; Dream.get "/dashboard/settings" Website_monitor_ui.serve_settings_page; (* Static assets *) Dream.get "/static/*" (Dream.static ~loader:(Dream.filesystem "") ""); ] in (* Start monitoring scheduler *) Website_monitor_scheduler.start (); (* Run the server *) Dream.run ~interface:"0.0.0.0" ~port:8080 @@ Dream.logger ~level:`Debug @@ cors @@ logger @@ router