refactor: remove item latest and get handlers

Co-authored-by: aider (openai/andrew/openrouter/qwen/qwen3-coder) <aider@aider.chat>
This commit is contained in:
Andrew Phillips
2025-08-25 18:09:46 -03:00
parent b3a21d1f7c
commit 5db2e9c063

View File

@@ -133,135 +133,6 @@ pub async fn handle_post_item(
}
#[utoipa::path(
get,
path = "/api/item/latest",
operation_id = "get_item_latest",
summary = "Get latest item with content",
description = "Retrieve the most recently stored item including its content and metadata. If tags are specified, returns the latest item that matches ALL the given tags. For text content, the actual content is included in the response. For binary content, only metadata is returned unless allow_binary is true.",
responses(
(status = 200, description = "Successfully retrieved latest item with content and metadata. Content is included if item is text-based or allow_binary is true.", body = ItemContentInfoResponse),
(status = 401, description = "Unauthorized - Invalid or missing authentication credentials"),
(status = 404, description = "Item not found - No items exist in the database or no items match the specified tag criteria"),
(status = 500, description = "Internal server error - Failed to retrieve item content due to decompression or database error")
),
params(
("tags" = Option<String>, Query, description = "Comma-separated list of tags to filter by (e.g., 'important,work'). If specified, returns the latest item that has ALL the specified tags."),
("allow_binary" = Option<bool>, Query, description = "Whether to include raw content for binary files (default: false). When false, binary files return only metadata. When true, binary content is included as a string.")
),
security(
("bearerAuth" = [])
),
tag = "item"
)]
pub async fn handle_get_item_latest(
State(state): State<AppState>,
Query(params): Query<TagsQuery>,
) -> Result<Json<ApiResponse<ItemContentInfo>>, StatusCode> {
let tags: Vec<String> = params
.tags
.as_ref()
.map(|s| s.split(',').map(|t| t.trim().to_string()).collect())
.unwrap_or_default();
let item_service = AsyncItemService::new(state.data_dir.clone(), state.db.clone());
let item_with_meta = item_service
.find_item(vec![], tags, HashMap::new())
.await;
match item_with_meta {
Ok(item) => {
let item_id = item.item.id.unwrap();
match get_item_content_info(&item_service, item_id, params.allow_binary).await {
Ok(content_info) => {
let response = ApiResponse {
success: true,
data: Some(content_info),
error: None,
};
Ok(Json(response))
}
Err(e) => {
warn!("Failed to get content for item {}: {}", item_id, e);
let response = ApiResponse::<ItemContentInfo> {
success: false,
data: None,
error: Some(format!("Failed to retrieve content: {}", e)),
};
Ok(Json(response))
}
}
}
Err(CoreError::ItemNotFoundGeneric) => Err(StatusCode::NOT_FOUND),
Err(e) => {
warn!("Failed to find latest item: {}", e);
Err(StatusCode::INTERNAL_SERVER_ERROR)
}
}
}
#[utoipa::path(
get,
path = "/api/item/{item_id}",
operation_id = "get_item",
summary = "Get item with content",
description = "Retrieve a specific item by its ID including both content and metadata. The content is automatically decompressed and returned as a string for text files. Binary files return only metadata unless allow_binary is explicitly set to true.",
responses(
(status = 200, description = "Successfully retrieved item with content and metadata. Content is included if item is text-based or allow_binary is true.", body = ItemContentInfoResponse),
(status = 400, description = "Bad request - Invalid item ID (must be a positive integer)"),
(status = 401, description = "Unauthorized - Invalid or missing authentication credentials"),
(status = 404, description = "Item not found - No item exists with the specified ID"),
(status = 500, description = "Internal server error - Failed to retrieve item content due to decompression or database error")
),
params(
("item_id" = i64, Path, description = "Unique identifier of the item to retrieve (must be a positive integer)"),
("allow_binary" = Option<bool>, Query, description = "Whether to include raw content for binary files (default: false). When false, binary files return only metadata. When true, binary content is included as a string.")
),
security(
("bearerAuth" = [])
),
tag = "item"
)]
pub async fn handle_get_item(
State(state): State<AppState>,
Path(item_id): Path<i64>,
Query(params): Query<ItemQuery>,
) -> Result<Json<ApiResponse<ItemContentInfo>>, StatusCode> {
// Validate that item ID is positive to prevent path traversal issues
if item_id <= 0 {
return Err(StatusCode::BAD_REQUEST);
}
let item_service = AsyncItemService::new(state.data_dir.clone(), state.db.clone());
match get_item_content_info(&item_service, item_id, params.allow_binary).await {
Ok(content_info) => {
let response = ApiResponse {
success: true,
data: Some(content_info),
error: None,
};
Ok(Json(response))
}
Err(e) => {
warn!("Failed to get content for item {}: {}", item_id, e);
// Check if the error is ItemNotFound to return 404
if let Some(core_err) = e.downcast_ref::<CoreError>() {
if matches!(core_err, CoreError::ItemNotFound(_)) {
return Err(StatusCode::NOT_FOUND);
}
}
let response = ApiResponse::<ItemContentInfo> {
success: false,
data: None,
error: Some(format!("Failed to retrieve content: {}", e)),
};
Ok(Json(response))
}
}
}
#[utoipa::path(
get,
path = "/api/item/latest/content",