sqlite_graphrag/commands/
namespace_detect.rs1use crate::errors::AppError;
4use crate::namespace;
5use crate::output;
6use serde::Serialize;
7
8#[derive(clap::Args)]
9pub struct NamespaceDetectArgs {
10 #[arg(long)]
11 pub namespace: Option<String>,
12 #[arg(long, env = "SQLITE_GRAPHRAG_DB_PATH")]
14 pub db: Option<String>,
15 #[arg(long, default_value_t = false)]
17 pub json: bool,
18}
19
20#[derive(Serialize)]
21struct NamespaceDetectResponse {
22 namespace: String,
23 source: namespace::NamespaceSource,
24 cwd: String,
25 elapsed_ms: u64,
27}
28
29pub fn run(args: NamespaceDetectArgs) -> Result<(), AppError> {
30 let inicio = std::time::Instant::now();
31 let _ = args.db;
32 let _ = args.json; let resolution = namespace::detect_namespace(args.namespace.as_deref())?;
34 output::emit_json(&NamespaceDetectResponse {
35 namespace: resolution.namespace,
36 source: resolution.source,
37 cwd: resolution.cwd,
38 elapsed_ms: inicio.elapsed().as_millis() as u64,
39 })?;
40 Ok(())
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46 use crate::namespace::NamespaceSource;
47 use clap::Parser;
48 use serial_test::serial;
49
50 #[test]
51 #[serial]
52 fn namespace_detect_default_retorna_global_via_detect() {
53 std::env::remove_var("SQLITE_GRAPHRAG_NAMESPACE");
55 let resolution = namespace::detect_namespace(None).unwrap();
56 assert_eq!(resolution.namespace, "global");
57 assert_eq!(resolution.source, NamespaceSource::Default);
58 }
59
60 #[test]
61 #[serial]
62 fn namespace_detect_explicit_flag_sobrepoe_env() {
63 std::env::set_var("SQLITE_GRAPHRAG_NAMESPACE", "env-namespace");
64 let resolution = namespace::detect_namespace(Some("flag-namespace")).unwrap();
65 assert_eq!(resolution.namespace, "flag-namespace");
66 assert_eq!(resolution.source, NamespaceSource::ExplicitFlag);
67 std::env::remove_var("SQLITE_GRAPHRAG_NAMESPACE");
68 }
69
70 #[test]
71 #[serial]
72 fn namespace_detect_env_var_usada_quando_sem_flag() {
73 std::env::remove_var("SQLITE_GRAPHRAG_NAMESPACE");
74 std::env::set_var("SQLITE_GRAPHRAG_NAMESPACE", "namespace-de-env");
75 let resolution = namespace::detect_namespace(None).unwrap();
76 assert_eq!(resolution.namespace, "namespace-de-env");
77 assert_eq!(resolution.source, NamespaceSource::Environment);
78 std::env::remove_var("SQLITE_GRAPHRAG_NAMESPACE");
79 }
80
81 #[test]
82 fn namespace_detect_response_serializa_todos_campos() {
83 let resp = NamespaceDetectResponse {
84 namespace: "meu-projeto".to_string(),
85 source: NamespaceSource::ExplicitFlag,
86 cwd: "/home/usuario/projeto".to_string(),
87 elapsed_ms: 3,
88 };
89 let json = serde_json::to_value(&resp).unwrap();
90 assert_eq!(json["namespace"], "meu-projeto");
91 assert_eq!(json["source"], "explicit_flag");
92 assert!(json["cwd"].is_string());
93 assert_eq!(json["elapsed_ms"], 3);
94 }
95
96 #[test]
97 fn namespace_source_serializa_em_snake_case() {
98 let casos = vec![
99 (NamespaceSource::ExplicitFlag, "explicit_flag"),
100 (NamespaceSource::Environment, "environment"),
101 (NamespaceSource::Default, "default"),
102 ];
103 for (source, esperado) in casos {
104 let json = serde_json::to_value(source).unwrap();
105 assert_eq!(
106 json, esperado,
107 "NamespaceSource::{source:?} deve serializar como \"{esperado}\""
108 );
109 }
110 }
111
112 #[test]
113 fn namespace_detect_aceita_db_como_noop() {
114 let cli = crate::cli::Cli::try_parse_from([
115 "sqlite-graphrag",
116 "namespace-detect",
117 "--db",
118 "/tmp/graphrag.sqlite",
119 ])
120 .expect("namespace-detect deve aceitar --db como no-op");
121
122 match cli.command {
123 crate::cli::Commands::NamespaceDetect(args) => {
124 assert_eq!(args.db.as_deref(), Some("/tmp/graphrag.sqlite"));
125 }
126 _ => unreachable!("comando incorreto parseado"),
127 }
128 }
129}