Skip to main content

nexus_memory_web/api/
namespaces.rs

1//! Namespace API endpoints
2
3use axum::{
4    extract::{Path, State},
5    http::StatusCode,
6    Json,
7};
8use std::sync::Arc;
9use tokio::sync::RwLock;
10use tracing::info;
11
12use crate::{
13    error::{Result, WebError},
14    models::{CreateNamespaceRequest, NamespaceListResponse, NamespaceResponse},
15    state::AppState,
16};
17
18/// List all namespaces
19pub async fn list_namespaces(
20    State(state): State<Arc<RwLock<AppState>>>,
21) -> Result<Json<NamespaceListResponse>> {
22    let state = state.read().await;
23
24    let namespaces = state.namespace_repo.list_all().await?;
25
26    let namespaces: Vec<NamespaceResponse> = namespaces
27        .into_iter()
28        .map(NamespaceResponse::from)
29        .collect();
30
31    let total = namespaces.len();
32
33    Ok(Json(NamespaceListResponse {
34        success: true,
35        namespaces,
36        total,
37    }))
38}
39
40/// Get a specific namespace by ID
41pub async fn get_namespace(
42    State(state): State<Arc<RwLock<AppState>>>,
43    Path(id): Path<String>,
44) -> Result<Json<NamespaceResponse>> {
45    let state = state.read().await;
46
47    // Try to parse as i64 first, otherwise treat as name
48    let namespace = if let Ok(id_num) = id.parse::<i64>() {
49        // Search by ID - we need to list all and find by ID
50        let all = state.namespace_repo.list_all().await?;
51        all.into_iter().find(|n| n.id == id_num)
52    } else {
53        // Search by name
54        state.namespace_repo.get_by_name(&id).await?
55    };
56
57    let namespace =
58        namespace.ok_or_else(|| WebError::NotFound(format!("Namespace '{}' not found", id)))?;
59
60    Ok(Json(NamespaceResponse::from(namespace)))
61}
62
63/// Create a new namespace
64pub async fn create_namespace(
65    State(state): State<Arc<RwLock<AppState>>>,
66    Json(request): Json<CreateNamespaceRequest>,
67) -> Result<(StatusCode, Json<NamespaceResponse>)> {
68    let state = state.read().await;
69
70    // Validate name
71    if request.name.trim().is_empty() {
72        return Err(WebError::InvalidRequest(
73            "Namespace name cannot be empty".to_string(),
74        ));
75    }
76
77    // Check if namespace already exists
78    if let Some(existing) = state.namespace_repo.get_by_name(&request.name).await? {
79        return Ok((StatusCode::OK, Json(NamespaceResponse::from(existing))));
80    }
81
82    // Create namespace
83    let namespace = state
84        .namespace_repo
85        .get_or_create(&request.name, &request.agent_type)
86        .await?;
87
88    info!(
89        "Namespace created: id={}, name={}",
90        namespace.id, namespace.name
91    );
92
93    Ok((
94        StatusCode::CREATED,
95        Json(NamespaceResponse::from(namespace)),
96    ))
97}