huskies: merge 606_story_extract_project_service
This commit is contained in:
+24
-10
@@ -1,6 +1,7 @@
|
||||
//! HTTP project endpoints — REST API for project initialization and context management.
|
||||
use crate::http::context::{AppContext, OpenApiResult, bad_request};
|
||||
use crate::io::fs;
|
||||
//! HTTP project endpoints — thin adapters over `service::project`.
|
||||
use crate::http::context::{AppContext, OpenApiResult, bad_request, not_found};
|
||||
use crate::service::project::{self as svc, Error as ProjectError};
|
||||
use poem::http::StatusCode;
|
||||
use poem_openapi::{Object, OpenApi, Tags, payload::Json};
|
||||
use serde::Deserialize;
|
||||
use std::sync::Arc;
|
||||
@@ -15,6 +16,17 @@ struct PathPayload {
|
||||
path: String,
|
||||
}
|
||||
|
||||
/// Map a typed [`ProjectError`] to a `poem::Error` with the appropriate HTTP status.
|
||||
fn map_project_error(e: ProjectError) -> poem::Error {
|
||||
match e {
|
||||
ProjectError::PathNotFound(msg) => not_found(msg),
|
||||
ProjectError::NotADirectory(msg) => bad_request(msg),
|
||||
ProjectError::Internal(msg) => {
|
||||
poem::Error::from_string(msg, StatusCode::INTERNAL_SERVER_ERROR)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ProjectApi {
|
||||
pub ctx: Arc<AppContext>,
|
||||
}
|
||||
@@ -26,8 +38,8 @@ impl ProjectApi {
|
||||
/// Returns null when no project is open.
|
||||
#[oai(path = "/project", method = "get")]
|
||||
async fn get_current_project(&self) -> OpenApiResult<Json<Option<String>>> {
|
||||
let result = fs::get_current_project(&self.ctx.state, self.ctx.store.as_ref())
|
||||
.map_err(bad_request)?;
|
||||
let result = svc::get_current_project(&self.ctx.state, self.ctx.store.as_ref())
|
||||
.map_err(map_project_error)?;
|
||||
Ok(Json(result))
|
||||
}
|
||||
|
||||
@@ -36,14 +48,14 @@ impl ProjectApi {
|
||||
/// Persists the selected path for later sessions.
|
||||
#[oai(path = "/project", method = "post")]
|
||||
async fn open_project(&self, payload: Json<PathPayload>) -> OpenApiResult<Json<String>> {
|
||||
let confirmed = fs::open_project(
|
||||
let confirmed = svc::open_project(
|
||||
payload.0.path,
|
||||
&self.ctx.state,
|
||||
self.ctx.store.as_ref(),
|
||||
self.ctx.agents.port(),
|
||||
)
|
||||
.await
|
||||
.map_err(bad_request)?;
|
||||
.map_err(map_project_error)?;
|
||||
Ok(Json(confirmed))
|
||||
}
|
||||
|
||||
@@ -55,21 +67,23 @@ impl ProjectApi {
|
||||
"[MERGE-DEBUG] DELETE /project called! \
|
||||
Backtrace: this is the only code path that clears project_root."
|
||||
);
|
||||
fs::close_project(&self.ctx.state, self.ctx.store.as_ref()).map_err(bad_request)?;
|
||||
svc::close_project(&self.ctx.state, self.ctx.store.as_ref()).map_err(map_project_error)?;
|
||||
Ok(Json(true))
|
||||
}
|
||||
|
||||
/// List known projects from the store.
|
||||
#[oai(path = "/projects", method = "get")]
|
||||
async fn list_known_projects(&self) -> OpenApiResult<Json<Vec<String>>> {
|
||||
let projects = fs::get_known_projects(self.ctx.store.as_ref()).map_err(bad_request)?;
|
||||
let projects =
|
||||
svc::get_known_projects(self.ctx.store.as_ref()).map_err(map_project_error)?;
|
||||
Ok(Json(projects))
|
||||
}
|
||||
|
||||
/// Forget a known project path.
|
||||
#[oai(path = "/projects/forget", method = "post")]
|
||||
async fn forget_known_project(&self, payload: Json<PathPayload>) -> OpenApiResult<Json<bool>> {
|
||||
fs::forget_known_project(payload.0.path, self.ctx.store.as_ref()).map_err(bad_request)?;
|
||||
svc::forget_known_project(payload.0.path, self.ctx.store.as_ref())
|
||||
.map_err(map_project_error)?;
|
||||
Ok(Json(true))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user