Skip to main content

fraiseql_cli/commands/
cost.rs

1//! Cost command - lightweight complexity scoring for queries
2//!
3//! Usage: fraiseql cost `<query>` `[--json]`
4
5use anyhow::Result;
6use fraiseql_core::graphql::{complexity::RequestValidator, parse_query};
7use serde::Serialize;
8
9use crate::output::CommandResult;
10
11/// Response with cost estimation
12#[derive(Debug, Serialize)]
13pub struct CostResponse {
14    /// The GraphQL query being analyzed
15    pub query:            String,
16    /// Complexity score based on query depth and breadth (pagination-aware)
17    pub complexity_score: usize,
18    /// Estimated execution cost
19    pub estimated_cost:   usize,
20    /// Maximum query depth
21    pub depth:            usize,
22    /// Number of aliased fields
23    pub alias_count:      usize,
24}
25
26/// Run cost command (minimal complexity analysis)
27///
28/// # Errors
29///
30/// Returns an error if the query cannot be parsed or if complexity analysis
31/// fails. Also propagates errors from JSON serialization of the response.
32pub fn run(query: &str) -> Result<CommandResult> {
33    // Validate query syntax
34    let _parsed = parse_query(query)?;
35
36    // AST-based complexity analysis
37    let validator = RequestValidator::default();
38    let metrics = validator.analyze(query)?;
39
40    let response = CostResponse {
41        query:            query.to_string(),
42        complexity_score: metrics.complexity,
43        estimated_cost:   metrics.depth * 25, // Rough cost estimation
44        depth:            metrics.depth,
45        alias_count:      metrics.alias_count,
46    };
47
48    Ok(CommandResult::success("cost", serde_json::to_value(&response)?))
49}