Skip to main content
Glama
common.rs3.9 kB
//! Common types and utilities for the v1 API use axum::{ http::StatusCode, response::{ IntoResponse, Response, }, }; use serde::{ Deserialize, Serialize, }; use telemetry::prelude::*; use thiserror::Error; use utoipa::ToSchema; /// Standard success response format for v1 API #[derive(Serialize, Debug, ToSchema)] #[serde(rename_all = "camelCase")] pub struct ApiSuccess<T> { pub data: T, } /// Standard error response format for v1 API #[derive(Serialize, Debug, ToSchema)] #[serde(rename_all = "camelCase")] #[schema(example = json!({ "message": "Invalid request data", "statusCode": 422, "code": 4001 }))] pub struct ApiError { #[schema(example = "Invalid request data")] pub message: String, #[schema(example = 422)] pub status_code: u16, #[schema(example = 4001)] pub code: Option<i32>, } impl ApiError { /// Create a new API error pub fn new(status: StatusCode, message: String) -> Self { Self { message, status_code: status.as_u16(), code: None, } } /// Create a new API error with a code pub fn with_code(status: StatusCode, message: String, code: i32) -> Self { Self { message, status_code: status.as_u16(), code: Some(code), } } } impl IntoResponse for ApiError { fn into_response(self) -> Response { let status = StatusCode::from_u16(self.status_code).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR); // Store message before moving self let message = self.message.clone(); if status.is_client_error() { warn!(err=?self, si.error.message = %message ); } else if status.is_server_error() { error!(err=?self, si.error.message = %message ); } let body = axum::Json(self); (status, body).into_response() } } /// Common error types that can be reused across v1 API modules #[remain::sorted] #[derive(Debug, Error)] pub enum CommonError { #[error("change set error: {0}")] ChangeSet(#[from] dal::ChangeSetError), #[error("component error: {0}")] Component(#[from] dal::ComponentError), #[error("transaction error: {0}")] Transaction(#[from] dal::TransactionsError), #[error("workspace error: {0}")] Workspace(#[from] dal::WorkspaceError), #[error("ws event error: {0}")] WsEvent(#[from] dal::WsEventError), } /// Helper trait for converting errors to responses pub trait ErrorIntoResponse: std::error::Error { /// Convert an error to a status code and message fn status_and_message(&self) -> (StatusCode, String); /// Convert an error to an API response fn to_api_response(&self) -> Response { let (status, message) = self.status_and_message(); ApiError::new(status, message).into_response() } } /// Common path parameters used in multiple endpoints #[derive(Deserialize, ToSchema)] pub struct WorkspaceIdParam { #[schema(value_type = String)] pub workspace_id: dal::WorkspacePk, } /// Common path parameters used in multiple endpoints #[derive(Deserialize, ToSchema)] pub struct ChangeSetIdParam { #[schema(value_type = String)] pub change_set_id: dal::ChangeSetId, } /// Common path parameters used in multiple endpoints #[derive(Deserialize, ToSchema)] pub struct ComponentIdParam { #[schema(value_type = String)] pub component_id: dal::ComponentId, } #[derive(Debug, Deserialize, ToSchema)] #[serde(rename_all = "camelCase")] pub struct PaginationParams { #[schema(example = "50", nullable = true, value_type = Option<u32>)] pub limit: Option<u32>, #[schema(example = "01H9ZQD35JPMBGHH69BT0Q79VY", nullable = true, value_type = Option<String>)] pub cursor: Option<String>, #[schema(value_type = Option<bool>)] pub include_codegen: Option<bool>, }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server