diff --git a/server/cli/src/main.rs b/server/cli/src/main.rs index 5016e23..6f29ff9 100644 --- a/server/cli/src/main.rs +++ b/server/cli/src/main.rs @@ -4,21 +4,44 @@ #[macro_use] extern crate rocket_okapi; use schemars::JsonSchema; -use rocket_okapi::swagger_ui::*; -use rocket::{ - State, - response::status +use rocket_okapi::{ + response::OpenApiResponder, + gen::OpenApiGenerator, + swagger_ui::*, }; -use rocket_contrib::json::Json; +use rocket::{ + http::{ + hyper::header::Location, + Status + }, + State, + Response, + response::status, + request::Request, + response::Responder +}; +use okapi::openapi3::Responses; +use rocket_contrib::json::{Json}; use std::collections::hash_map::DefaultHasher; use std::hash::{ Hash, Hasher }; - // podman create --name test -p 3000:3000 -v $PWD:/nixide -w /nixide docker.io/nixos/nix nix-shell --pure start-ide.nix --run run_ide.sh + #[derive(Serialize, Deserialize, Hash, JsonSchema)] + pub enum IdeState + { + UNKOWN, + OPENING, + OPENED, + CLOSING, + CLOSED, + DELETING, + DELETED + } + #[derive(Serialize, Deserialize, Hash, JsonSchema)] pub struct OpenGitParam { @@ -28,22 +51,15 @@ pub struct OpenGitParam } #[derive(Serialize, Deserialize, Hash, JsonSchema)] -pub struct IdeState +pub struct IdeStateResponse { ide_id: String, - state: String + state: IdeState } -struct DummyEngine{} - pub trait NixIdeManageServiceEngine { - fn info(&self) -> String; -} - -impl NixIdeManageServiceEngine for DummyEngine { - fn info(&self) -> String { - "infoC".to_owned() - } + fn fetch_current_ide_state(&self, ide_id : &str) -> Result; + fn start_open(&self, ide_id : &str, param : &OpenGitParam) -> Result; } pub struct NixIdeManageService { @@ -53,12 +69,30 @@ pub struct NixIdeManageService { unsafe impl Send for NixIdeManageService {} unsafe impl Sync for NixIdeManageService {} -impl NixIdeManageService { - fn info(&self) -> String { - self.eng.info() +struct DummyEngine{} + +impl NixIdeManageServiceEngine for DummyEngine { + fn fetch_current_ide_state(&self, _ide_id : &str) -> Result { + Ok(IdeState::OPENING) + } + + fn start_open(&self, _ide_id : &str, _param : &OpenGitParam) -> Result + { + Ok(IdeState::OPENING) } } +struct PodmanEngine{} + +impl NixIdeManageServiceEngine for PodmanEngine { + fn fetch_current_ide_state(&self, _ide_id : &str) -> Result { + Ok(IdeState::OPENING) + } + + fn start_open(&self, _ide_id : &str, _param : &OpenGitParam) -> Result{ + Ok(IdeState::OPENING) + } +} #[derive(Serialize, Deserialize, Hash)] pub struct NixIdeServerParam { @@ -94,9 +128,56 @@ fn default_working_folder() -> String { "$PWD".to_owned() } +pub struct LocationHeader(pub Option, pub Location); + +/// Sets the status code of the response to 202 Accepted. If the responder is +/// `Some`, it is used to finalize the response. +impl<'r, R: Responder<'r>> Responder<'r> for LocationHeader { + fn respond_to(self, req: &Request) -> Result, Status> { + let mut build = Response::build(); + if let Some(responder) = self.0 { + build.merge(responder.respond_to(req)?); + } + + build.header(self.1).ok() + } +} + +pub type Map = schemars::Map; +type Object = Map; + +impl<'r, T: OpenApiResponder<'r>> OpenApiResponder<'r> for LocationHeader { + fn responses(gen: &mut OpenApiGenerator) -> rocket_okapi::Result { + let mut responses = T::responses(gen)?; + let mut rep = okapi::openapi3::Response::default(); + let header = okapi::openapi3::Header{ + description: Some("foo".to_owned()), + required: true, + deprecated: false, + allow_empty_value: false, + value: okapi::openapi3::ParameterValue::Schema { + style: None, + explode: None, + allow_reserved: false, + schema: schemars::schema::SchemaObject::default(), + example: None, + examples: None, + }, + extensions: Object::default(), + }; + rep.headers.insert("Location".to_owned(), okapi::openapi3::RefOr::Object(header)); + responses.responses.insert(String::new(), okapi::openapi3::RefOr::Object(rep)); + Ok(responses) + } +} + +#[derive(Debug)] +struct Error {} + + #[openapi] #[get("/open//git?&")] -fn v1_open_inquirer_git(inquirer: String, clone_url: String, ref_name: String) -> status::Accepted> { +fn v1_open_inquirer_git(inquirer: String, clone_url: String, ref_name: String, srv : State) -> Result>, Error> { let param = OpenGitParam { inquirer, clone_url, @@ -120,32 +201,38 @@ fn v1_open_inquirer_git(inquirer: String, clone_url: String, ref_name: String) - // .expect("create container"); // String::from_utf8(out.stderr).unwrap() - status::Accepted( - Some( - Json( - IdeState { - ide_id :format!("{:x}", hash), - state : "opening".to_owned() - } - ) + let ide_id = format!("{:x}", hash); + srv.eng.start_open(&ide_id, ¶m).map_err(|_| {Error {}}).and_then(|starting_result| { + Ok( + status::Accepted ( + Some( + Json( + IdeStateResponse { + ide_id : ide_id, + state : starting_result + } + ) + ) + ) ) - ) + }) + } #[openapi] #[get("/state/")] -fn v1_ide_state(ide_ide: String, c : State) -> status::Accepted> +fn v1_ide_state(ide_ide: String, srv : State) -> Json { - status::Accepted( - Some( + srv.eng.fetch_current_ide_state(&ide_ide).and_then(|ide_state| { + Ok( Json( - IdeState{ + IdeStateResponse{ ide_id: ide_ide, - state : c.info() + state : ide_state } ) ) - ) + }).unwrap() } #[openapi]