1use crate::types::Language;
2use anyhow::{Context, Result};
3use serde::{Deserialize, Serialize};
4use std::fs;
5use std::path::Path;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct CodeGraphConfig {
9 pub version: i64,
10 #[serde(rename = "rootDir")]
11 pub root_dir: String,
12 pub include: Vec<String>,
13 pub exclude: Vec<String>,
14 pub languages: Vec<Language>,
15 pub frameworks: Vec<serde_json::Value>,
16 #[serde(rename = "maxFileSize")]
17 pub max_file_size: u64,
18 #[serde(rename = "extractDocstrings")]
19 pub extract_docstrings: bool,
20 #[serde(rename = "trackCallSites")]
21 pub track_call_sites: bool,
22}
23
24impl CodeGraphConfig {
25 pub fn default_for_root(root: impl Into<String>) -> Self {
26 Self {
27 version: 1,
28 root_dir: root.into(),
29 include: vec![
30 "**/*.ts",
31 "**/*.tsx",
32 "**/*.js",
33 "**/*.jsx",
34 "**/*.py",
35 "**/*.go",
36 "**/*.rs",
37 "**/*.java",
38 "**/*.c",
39 "**/*.h",
40 "**/*.cpp",
41 "**/*.hpp",
42 "**/*.cc",
43 "**/*.cxx",
44 "**/*.cs",
45 "**/*.php",
46 "**/*.rb",
47 "**/*.swift",
48 "**/*.kt",
49 "**/*.kts",
50 "**/*.dart",
51 "**/*.svelte",
52 "**/*.vue",
53 "**/*.liquid",
54 "**/*.pas",
55 "**/*.dpr",
56 "**/*.dpk",
57 "**/*.lpr",
58 "**/*.dfm",
59 "**/*.fmx",
60 "**/*.scala",
61 "**/*.sc",
62 "**/*.mbt",
63 "**/*.mbti",
64 "**/*.mbt.md",
65 "**/moon.mod.json",
66 "**/moon.pkg.json",
67 "**/moon.pkg",
68 ]
69 .into_iter()
70 .map(String::from)
71 .collect(),
72 exclude: vec![
73 "**/.git/**",
74 "**/node_modules/**",
75 "**/vendor/**",
76 "**/dist/**",
77 "**/build/**",
78 "**/out/**",
79 "**/target/**",
80 "**/.codegraph/**",
81 "**/.moon/**",
82 "**/.mooncakes/**",
83 ]
84 .into_iter()
85 .map(String::from)
86 .collect(),
87 languages: Vec::new(),
88 frameworks: Vec::new(),
89 max_file_size: 1_048_576,
90 extract_docstrings: true,
91 track_call_sites: true,
92 }
93 }
94}
95
96pub fn config_path(root: &Path) -> std::path::PathBuf {
97 root.join(".codegraph").join("config.json")
98}
99
100pub fn load_config(root: &Path) -> Result<CodeGraphConfig> {
101 let path = config_path(root);
102 let text = fs::read_to_string(&path).with_context(|| format!("reading {}", path.display()))?;
103 let mut cfg: CodeGraphConfig =
104 serde_json::from_str(&text).with_context(|| format!("parsing {}", path.display()))?;
105 if cfg.include.is_empty() {
106 cfg.include = CodeGraphConfig::default_for_root(".").include;
107 }
108 Ok(cfg)
109}
110
111pub fn save_config(root: &Path, config: &CodeGraphConfig) -> Result<()> {
112 let path = config_path(root);
113 if let Some(parent) = path.parent() {
114 fs::create_dir_all(parent)?;
115 }
116 let text = serde_json::to_string_pretty(config)? + "\n";
117 fs::write(&path, text).with_context(|| format!("writing {}", path.display()))
118}