Skip to content

Commit 7a6e885

Browse files
committed
feat: add experimental method to separate files
1 parent 9eb9a6c commit 7a6e885

File tree

3 files changed

+172
-0
lines changed

3 files changed

+172
-0
lines changed

rust/cli/src/commands.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,23 @@ pub enum Commands {
5555
about = "Returns a project file with all sources in a database"
5656
)]
5757
GenerateSources(GenerateSourcesArgs),
58+
#[command(name = "experimental", about = "Experimental commands")]
59+
Experimental(ExternalCommands),
60+
}
61+
62+
#[derive(Debug, Args)]
63+
pub struct ExternalCommands {
64+
#[command(subcommand)]
65+
pub(crate) command: ExperimentalCommands,
66+
}
67+
68+
#[derive(Debug, Subcommand)]
69+
pub enum ExperimentalCommands {
70+
#[command(
71+
name = "separate-project-files",
72+
about = "Seperates the project file into multiple files for each individual model"
73+
)]
74+
SeperateProjectFiles,
5875
}
5976

6077
#[derive(Args, Debug)]

rust/cli/src/commands_experimental.rs

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
#![allow(unwrap_used)]
2+
use crate::commands::ExperimentalCommands;
3+
use crate::commands::ExternalCommands;
4+
use crate::{get_config_file, parse_project};
5+
use quary_core::project::parse_project_files;
6+
use quary_databases::databases_connection::database_from_config;
7+
use quary_proto::ProjectFile;
8+
use std::collections::{BTreeMap, HashMap};
9+
use std::path::{Path, PathBuf};
10+
11+
pub(crate) async fn experimental_commands(
12+
args: &ExternalCommands,
13+
project_file: &str,
14+
) -> Result<(), String> {
15+
match args.command {
16+
ExperimentalCommands::SeperateProjectFiles => {
17+
let config = get_config_file(project_file)?;
18+
let database = database_from_config(&config).await?;
19+
let query_generator = database.query_generator();
20+
let (project, file_system) = parse_project(&query_generator).await?;
21+
22+
let project_files = parse_project_files(&file_system, "", &query_generator).await?;
23+
24+
// delete all the files
25+
project_files
26+
.iter()
27+
.map(|(path, _)| std::fs::remove_file(path))
28+
.collect::<Result<Vec<_>, _>>()
29+
.map_err(|e| e.to_string())?;
30+
31+
// sources go into a _sources.yaml file
32+
let grouped_by_folder = project_files
33+
.iter()
34+
.fold(
35+
HashMap::<String, Vec<ProjectFile>>::new(),
36+
|mut acc: HashMap<String, Vec<ProjectFile>>, (path, file)| {
37+
let (folder, _) = path.rsplit_once("/").unwrap();
38+
let entry = acc.entry(folder.to_string()).or_insert(vec![]);
39+
entry.push(file.clone());
40+
acc
41+
},
42+
)
43+
.into_iter()
44+
.filter_map(|(folder, files)| {
45+
let folder = Path::new(&folder);
46+
let project_root = Path::new("");
47+
let file = "_sources.yaml";
48+
let file_path = project_root.join(folder).join(file);
49+
50+
let sources = files
51+
.iter()
52+
.flat_map(|file| {
53+
file.sources
54+
.iter()
55+
.map(|source| (source.name.clone(), source.clone()))
56+
})
57+
.collect::<BTreeMap<_, _>>();
58+
let project_file = ProjectFile {
59+
sources: sources.iter().map(|(_, source)| source.clone()).collect(),
60+
..Default::default()
61+
};
62+
if project_file.sources.is_empty() {
63+
return None;
64+
}
65+
Some((file_path, project_file))
66+
})
67+
.collect::<Vec<_>>();
68+
69+
grouped_by_folder.iter().for_each(|(path, project_file)| {
70+
let file = std::fs::File::create(path).unwrap();
71+
serde_yaml::to_writer(file, &project_file).unwrap();
72+
});
73+
74+
// models go into individually named model files
75+
let model_files = project
76+
.models
77+
.iter()
78+
.filter_map(|model| {
79+
let found_project_file_entry = project_files
80+
.iter()
81+
.find(|(_, file)| file.models.iter().any(|m| m.name == *model.0));
82+
if let Some((_, project_file)) = found_project_file_entry {
83+
let project_file_model = project_file
84+
.models
85+
.iter()
86+
.find(|m| m.name == *model.0)
87+
.unwrap();
88+
let file_name = model.1.file_path.clone();
89+
let file_path = Path::new("").join(file_name);
90+
let file_path = file_path.with_extension("yaml");
91+
let project_file = ProjectFile {
92+
models: vec![project_file_model.clone()],
93+
..Default::default()
94+
};
95+
Some((file_path, project_file))
96+
} else {
97+
None
98+
}
99+
})
100+
.collect::<Vec<(PathBuf, ProjectFile)>>();
101+
model_files.iter().for_each(|(path, project_file)| {
102+
let file = std::fs::File::create(path).unwrap();
103+
serde_yaml::to_writer(file, &project_file).unwrap();
104+
});
105+
106+
// snapshots go into individually named snapshots
107+
let snapshot_files = project
108+
.snapshots
109+
.iter()
110+
.filter(|snapshot| {
111+
let found_project_file_entry = project_files
112+
.iter()
113+
.find(|(_, file)| file.snapshots.iter().any(|s| s.name == *snapshot.0));
114+
found_project_file_entry.is_some()
115+
})
116+
.map(|snapshot| {
117+
let found_project_file_entry = project_files
118+
.iter()
119+
.find(|(_, file)| file.snapshots.iter().any(|s| s.name == *snapshot.0))
120+
.unwrap();
121+
let project_file_snapshot = found_project_file_entry
122+
.1
123+
.snapshots
124+
.iter()
125+
.find(|s| s.name == *snapshot.0)
126+
.unwrap();
127+
let file_name = snapshot.1.file_path.clone();
128+
let file_path = Path::new("").join(file_name);
129+
let file_path = file_path.with_extension("snapshot.yaml");
130+
let project_file = ProjectFile {
131+
snapshots: vec![project_file_snapshot.clone()],
132+
..Default::default()
133+
};
134+
Ok((file_path, project_file))
135+
})
136+
.collect::<Result<Vec<(PathBuf, ProjectFile)>, String>>()?;
137+
138+
snapshot_files.iter().for_each(|(path, project_file)| {
139+
let file = std::fs::File::create(path).unwrap();
140+
serde_yaml::to_writer(file, &project_file).unwrap();
141+
});
142+
143+
println!("Seperated project files into individual files.");
144+
Ok(())
145+
}
146+
}
147+
}

rust/cli/src/main.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ use std::sync::Arc;
4242
use std::time::Instant;
4343

4444
mod commands;
45+
mod commands_experimental;
4546
mod file_system;
4647
mod rpc_functions;
4748
mod rpc_scaffolding;
@@ -551,6 +552,13 @@ async fn main_wrapped() -> Result<(), String> {
551552
Ok(())
552553
}
553554
}
555+
Commands::Experimental(experimental_args) => {
556+
crate::commands_experimental::experimental_commands(
557+
experimental_args,
558+
&args.project_file,
559+
)
560+
.await
561+
}
554562
}
555563
}
556564

0 commit comments

Comments
 (0)