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