use axum::extract::State;
use axum::response::Json;
use mockforge_chaos::failure_designer::{FailureDesignRule, FailureDesigner};
use mockforge_chaos::ChaosScenario;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use std::sync::Arc;
#[derive(Clone)]
pub struct FailureDesignerState {
pub designer: Arc<FailureDesigner>,
}
impl FailureDesignerState {
pub fn new() -> Self {
Self {
designer: Arc::new(FailureDesigner::new()),
}
}
}
impl Default for FailureDesignerState {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Deserialize)]
pub struct ValidateRuleRequest {
pub rule: FailureDesignRule,
}
#[derive(Debug, Deserialize)]
pub struct GenerateScenarioRequest {
pub rule: FailureDesignRule,
}
#[derive(Debug, Serialize)]
pub struct ValidateRuleResponse {
pub success: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}
#[derive(Debug, Serialize)]
pub struct GenerateScenarioResponse {
pub success: bool,
pub scenario: ChaosScenario,
pub route_chaos_config: Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub webhook_hook: Option<Value>,
}
pub async fn validate_rule(
State(state): State<FailureDesignerState>,
Json(request): Json<ValidateRuleRequest>,
) -> Json<Value> {
let designer = &state.designer;
match designer.validate_rule(&request.rule) {
Ok(()) => Json(json!({
"success": true,
})),
Err(e) => Json(json!({
"success": false,
"error": e,
})),
}
}
pub async fn generate_scenario(
State(state): State<FailureDesignerState>,
Json(request): Json<GenerateScenarioRequest>,
) -> Result<Json<Value>, String> {
let designer = &state.designer;
let scenario = designer
.rule_to_scenario(&request.rule)
.map_err(|e| format!("Failed to generate scenario: {}", e))?;
let route_chaos_config = designer
.generate_route_chaos_config(&request.rule)
.map_err(|e| format!("Failed to generate route chaos config: {}", e))?;
let webhook_hook = if matches!(
request.rule.failure_type,
mockforge_chaos::failure_designer::FailureType::WebhookFailure { .. }
) {
Some(
designer
.generate_webhook_hook(&request.rule)
.map_err(|e| format!("Failed to generate webhook hook: {}", e))?,
)
} else {
None
};
Ok(Json(json!({
"success": true,
"scenario": scenario,
"route_chaos_config": route_chaos_config,
"webhook_hook": webhook_hook,
})))
}
pub async fn preview_config(
State(state): State<FailureDesignerState>,
Json(request): Json<GenerateScenarioRequest>,
) -> Result<Json<Value>, String> {
let designer = &state.designer;
designer
.validate_rule(&request.rule)
.map_err(|e| format!("Validation failed: {}", e))?;
let scenario = designer
.rule_to_scenario(&request.rule)
.map_err(|e| format!("Failed to generate scenario: {}", e))?;
let route_chaos_config = designer
.generate_route_chaos_config(&request.rule)
.map_err(|e| format!("Failed to generate route chaos config: {}", e))?;
let webhook_hook = if matches!(
request.rule.failure_type,
mockforge_chaos::failure_designer::FailureType::WebhookFailure { .. }
) {
Some(
designer
.generate_webhook_hook(&request.rule)
.map_err(|e| format!("Failed to generate webhook hook: {}", e))?,
)
} else {
None
};
Ok(Json(json!({
"success": true,
"rule": request.rule,
"scenario": scenario,
"route_chaos_config": route_chaos_config,
"webhook_hook": webhook_hook,
})))
}