fraiseql_cli/commands/
serve.rs1use std::{path::Path, sync::mpsc::channel, time::Duration};
6
7use anyhow::{Context, Result};
8use notify::{Config, Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher};
9use tracing::{error, info};
10
11#[allow(clippy::cognitive_complexity)] pub async fn run(schema: &str, port: u16) -> Result<()> {
35 info!("Starting development server");
36 println!("🚀 FraiseQL Dev Server");
37 println!(" Schema: {schema}");
38 println!(" Port: {port} (GraphQL server integration coming soon)");
39 println!(" Watching for changes...\n");
40
41 let schema_path = Path::new(schema);
43 if !schema_path.exists() {
44 anyhow::bail!("Schema file not found: {schema}");
45 }
46
47 println!("Initial compilation:");
49 match compile_schema(schema).await {
50 Ok(()) => println!(" ✓ Schema compiled successfully\n"),
51 Err(e) => {
52 error!("Initial compilation failed: {e}");
53 println!(" err: Compilation failed: {e}\n");
54 println!(" Fix errors and save to retry...\n");
55 },
56 }
57
58 let (tx, rx) = channel();
60
61 let mut watcher = RecommendedWatcher::new(
62 move |res: Result<Event, notify::Error>| {
63 if let Ok(event) = res {
64 let _ = tx.send(event);
65 }
66 },
67 Config::default(),
68 )
69 .context("Failed to create file watcher")?;
70
71 watcher
73 .watch(schema_path, RecursiveMode::NonRecursive)
74 .context("Failed to watch schema file")?;
75
76 loop {
78 match rx.recv() {
79 Ok(event) => {
80 if matches!(event.kind, EventKind::Modify(_)) {
82 info!("Schema file modified, recompiling...");
83 println!("Schema changed, recompiling...");
84
85 tokio::time::sleep(Duration::from_millis(100)).await;
87
88 match compile_schema(schema).await {
89 Ok(()) => {
90 info!("Recompilation successful");
91 println!(" ✓ Recompiled successfully\n");
92 },
93 Err(e) => {
94 error!("Recompilation failed: {e}");
95 println!(" err: Compilation failed: {e}\n");
96 },
97 }
98 }
99 },
100 Err(e) => {
101 error!("Watch error: {e}");
102 anyhow::bail!("File watch error: {e}");
103 },
104 }
105 }
106}
107
108async fn compile_schema(input: &str) -> Result<()> {
110 let output = input.replace(".json", ".compiled.json");
111
112 super::compile::run(
114 input,
115 None,
116 None,
117 Vec::new(),
118 Vec::new(),
119 Vec::new(),
120 &output,
121 false,
122 None,
123 None,
124 false,
125 false,
126 )
127 .await
128}