From 19bbe041b40ab6a9fa9db12c3762068e1698a59b Mon Sep 17 00:00:00 2001 From: clockwork-labs-bot Date: Mon, 29 Jun 2026 14:29:14 -0400 Subject: [PATCH 1/3] Fix dev local config generation --- crates/cli/src/subcommands/dev.rs | 66 ++++++++++++++++++++++++---- crates/cli/src/subcommands/init.rs | 7 +-- templates/chat-console-rs/Cargo.toml | 5 ++- 3 files changed, 65 insertions(+), 13 deletions(-) diff --git a/crates/cli/src/subcommands/dev.rs b/crates/cli/src/subcommands/dev.rs index 70acd76eadc..93ec1b3cfe0 100644 --- a/crates/cli/src/subcommands/dev.rs +++ b/crates/cli/src/subcommands/dev.rs @@ -567,7 +567,9 @@ pub async fn exec(mut config: Config, args: &ArgMatches) -> Result<(), anyhow::E } } - if !module_bindings_dir.exists() { + let should_prepare_module_bindings_dir = + should_prepare_default_module_bindings_dir(skip_generate, using_spacetime_config); + if should_prepare_module_bindings_dir && !module_bindings_dir.exists() { // Create the module bindings directory if it doesn't exist std::fs::create_dir_all(&module_bindings_dir).with_context(|| { format!( @@ -575,7 +577,7 @@ pub async fn exec(mut config: Config, args: &ArgMatches) -> Result<(), anyhow::E module_bindings_dir.display() ) })?; - } else if !module_bindings_dir.is_dir() { + } else if should_prepare_module_bindings_dir && !module_bindings_dir.is_dir() { anyhow::bail!( "Module bindings path {} exists but is not a directory.", module_bindings_path.display() @@ -1617,6 +1619,10 @@ fn create_default_spacetime_config_if_missing(project_dir: &Path) -> anyhow::Res Ok(Some(config.save_to_dir(project_dir)?)) } +fn should_prepare_default_module_bindings_dir(skip_generate: bool, using_spacetime_config: bool) -> bool { + !skip_generate && !using_spacetime_config +} + fn create_local_spacetime_config_if_missing( project_dir: &Path, database_name: &str, @@ -1630,12 +1636,22 @@ fn create_local_spacetime_config_if_missing( if local_config_path.exists() { let mut local_config = SpacetimeConfig::load(&local_config_path) .with_context(|| format!("Failed to load {}", local_config_path.display()))?; - if local_config.additional_fields.contains_key("database") { + let mut changed = false; + if !local_config.additional_fields.contains_key("database") { + local_config + .additional_fields + .insert("database".to_string(), json!(database_name)); + changed = true; + } + if !local_config.additional_fields.contains_key("server") { + local_config + .additional_fields + .insert("server".to_string(), json!("local")); + changed = true; + } + if !changed { return Ok(None); } - local_config - .additional_fields - .insert("database".to_string(), json!(database_name)); local_config.save(&local_config_path)?; return Ok(Some(local_config_path)); } @@ -1644,6 +1660,9 @@ fn create_local_spacetime_config_if_missing( local_config .additional_fields .insert("database".to_string(), json!(database_name)); + local_config + .additional_fields + .insert("server".to_string(), json!("local")); local_config.save(&local_config_path)?; Ok(Some(local_config_path)) @@ -1985,6 +2004,14 @@ mod tests { ); } + #[test] + fn test_default_module_bindings_dir_is_only_prepared_for_cli_generation() { + assert!(should_prepare_default_module_bindings_dir(false, false)); + assert!(!should_prepare_default_module_bindings_dir(false, true)); + assert!(!should_prepare_default_module_bindings_dir(true, false)); + assert!(!should_prepare_default_module_bindings_dir(true, true)); + } + #[test] fn test_create_local_spacetime_config_if_missing_creates_database_override() { let temp = TempDir::new().unwrap(); @@ -2005,9 +2032,7 @@ mod tests { .expect("database should be present"); assert_eq!(db, "my-app-123456"); - - let obj = parsed.as_object().expect("local config should be a JSON object"); - assert_eq!(obj.len(), 1, "local config should only contain database"); + assert_eq!(parsed.get("server").and_then(|v| v.as_str()), Some("local")); } #[test] @@ -2029,6 +2054,29 @@ mod tests { assert_eq!(parsed.get("database").and_then(|v| v.as_str()), Some("my-cli-db")); } + #[test] + fn test_create_local_spacetime_config_if_missing_upserts_missing_server() { + let temp = TempDir::new().unwrap(); + let project_path = temp.path(); + + std::fs::write(project_path.join("spacetime.json"), "{}").unwrap(); + std::fs::write( + project_path.join("spacetime.local.json"), + r#"{ "database": "my-cli-db" }"#, + ) + .unwrap(); + + let updated = create_local_spacetime_config_if_missing(project_path, "my-cli-db") + .unwrap() + .expect("expected local config to be updated"); + assert_eq!(updated, project_path.join("spacetime.local.json")); + + let content = std::fs::read_to_string(project_path.join("spacetime.local.json")).unwrap(); + let parsed: serde_json::Value = serde_json::from_str(&content).unwrap(); + assert_eq!(parsed.get("server").and_then(|v| v.as_str()), Some("local")); + assert_eq!(parsed.get("database").and_then(|v| v.as_str()), Some("my-cli-db")); + } + #[test] fn test_detect_and_save_merges_into_existing_file_when_no_existing_config_passed() { let temp = TempDir::new().unwrap(); diff --git a/crates/cli/src/subcommands/init.rs b/crates/cli/src/subcommands/init.rs index 77eb580943d..db1a1e6d0e3 100644 --- a/crates/cli/src/subcommands/init.rs +++ b/crates/cli/src/subcommands/init.rs @@ -685,6 +685,9 @@ fn create_local_spacetime_config_if_missing( local_config .additional_fields .insert("database".to_string(), json!(database_name)); + local_config + .additional_fields + .insert("server".to_string(), json!("local")); local_config.save(&local_config_path)?; Ok(Some(local_config_path)) @@ -2390,9 +2393,7 @@ bytes.workspace = true .expect("database should be present"); assert_eq!(db, "my-app-abc12"); - - let obj = parsed.as_object().expect("local config should be a JSON object"); - assert_eq!(obj.len(), 1, "local config should only contain database"); + assert_eq!(parsed.get("server").and_then(|v| v.as_str()), Some("local")); } #[test] diff --git a/templates/chat-console-rs/Cargo.toml b/templates/chat-console-rs/Cargo.toml index af92400907a..946159277c9 100644 --- a/templates/chat-console-rs/Cargo.toml +++ b/templates/chat-console-rs/Cargo.toml @@ -4,7 +4,10 @@ version = "0.1.0" edition = "2024" [workspace] -exclude = ["spacetimedb"] +members = ["spacetimedb"] + +[workspace.dependencies] +log = "0.4" [dependencies] spacetimedb-sdk = { path = "../../sdks/rust" } From 9c6a88d3e8b21f3b22e4ff84d0ba9c0ba72e6c3b Mon Sep 17 00:00:00 2001 From: clockwork-labs-bot Date: Mon, 29 Jun 2026 14:37:27 -0400 Subject: [PATCH 2/3] Keep local config server unchanged --- crates/cli/src/subcommands/dev.rs | 65 +++--------------------------- crates/cli/src/subcommands/init.rs | 7 ++-- 2 files changed, 9 insertions(+), 63 deletions(-) diff --git a/crates/cli/src/subcommands/dev.rs b/crates/cli/src/subcommands/dev.rs index 93ec1b3cfe0..18012e47d6a 100644 --- a/crates/cli/src/subcommands/dev.rs +++ b/crates/cli/src/subcommands/dev.rs @@ -1636,22 +1636,12 @@ fn create_local_spacetime_config_if_missing( if local_config_path.exists() { let mut local_config = SpacetimeConfig::load(&local_config_path) .with_context(|| format!("Failed to load {}", local_config_path.display()))?; - let mut changed = false; - if !local_config.additional_fields.contains_key("database") { - local_config - .additional_fields - .insert("database".to_string(), json!(database_name)); - changed = true; - } - if !local_config.additional_fields.contains_key("server") { - local_config - .additional_fields - .insert("server".to_string(), json!("local")); - changed = true; - } - if !changed { + if local_config.additional_fields.contains_key("database") { return Ok(None); } + local_config + .additional_fields + .insert("database".to_string(), json!(database_name)); local_config.save(&local_config_path)?; return Ok(Some(local_config_path)); } @@ -1660,9 +1650,6 @@ fn create_local_spacetime_config_if_missing( local_config .additional_fields .insert("database".to_string(), json!(database_name)); - local_config - .additional_fields - .insert("server".to_string(), json!("local")); local_config.save(&local_config_path)?; Ok(Some(local_config_path)) @@ -2032,49 +2019,9 @@ mod tests { .expect("database should be present"); assert_eq!(db, "my-app-123456"); - assert_eq!(parsed.get("server").and_then(|v| v.as_str()), Some("local")); - } - - #[test] - fn test_create_local_spacetime_config_if_missing_upserts_missing_database() { - let temp = TempDir::new().unwrap(); - let project_path = temp.path(); - - std::fs::write(project_path.join("spacetime.json"), "{}").unwrap(); - std::fs::write(project_path.join("spacetime.local.json"), r#"{ "server": "local" }"#).unwrap(); - - let updated = create_local_spacetime_config_if_missing(project_path, "my-cli-db") - .unwrap() - .expect("expected local config to be updated"); - assert_eq!(updated, project_path.join("spacetime.local.json")); - - let content = std::fs::read_to_string(project_path.join("spacetime.local.json")).unwrap(); - let parsed: serde_json::Value = serde_json::from_str(&content).unwrap(); - assert_eq!(parsed.get("server").and_then(|v| v.as_str()), Some("local")); - assert_eq!(parsed.get("database").and_then(|v| v.as_str()), Some("my-cli-db")); - } - - #[test] - fn test_create_local_spacetime_config_if_missing_upserts_missing_server() { - let temp = TempDir::new().unwrap(); - let project_path = temp.path(); - std::fs::write(project_path.join("spacetime.json"), "{}").unwrap(); - std::fs::write( - project_path.join("spacetime.local.json"), - r#"{ "database": "my-cli-db" }"#, - ) - .unwrap(); - - let updated = create_local_spacetime_config_if_missing(project_path, "my-cli-db") - .unwrap() - .expect("expected local config to be updated"); - assert_eq!(updated, project_path.join("spacetime.local.json")); - - let content = std::fs::read_to_string(project_path.join("spacetime.local.json")).unwrap(); - let parsed: serde_json::Value = serde_json::from_str(&content).unwrap(); - assert_eq!(parsed.get("server").and_then(|v| v.as_str()), Some("local")); - assert_eq!(parsed.get("database").and_then(|v| v.as_str()), Some("my-cli-db")); + let obj = parsed.as_object().expect("local config should be a JSON object"); + assert_eq!(obj.len(), 1, "local config should only contain database"); } #[test] diff --git a/crates/cli/src/subcommands/init.rs b/crates/cli/src/subcommands/init.rs index db1a1e6d0e3..77eb580943d 100644 --- a/crates/cli/src/subcommands/init.rs +++ b/crates/cli/src/subcommands/init.rs @@ -685,9 +685,6 @@ fn create_local_spacetime_config_if_missing( local_config .additional_fields .insert("database".to_string(), json!(database_name)); - local_config - .additional_fields - .insert("server".to_string(), json!("local")); local_config.save(&local_config_path)?; Ok(Some(local_config_path)) @@ -2393,7 +2390,9 @@ bytes.workspace = true .expect("database should be present"); assert_eq!(db, "my-app-abc12"); - assert_eq!(parsed.get("server").and_then(|v| v.as_str()), Some("local")); + + let obj = parsed.as_object().expect("local config should be a JSON object"); + assert_eq!(obj.len(), 1, "local config should only contain database"); } #[test] From 1872a19397e95b878d0efaaf65864b05111b288e Mon Sep 17 00:00:00 2001 From: clockwork-labs-bot Date: Mon, 29 Jun 2026 14:41:02 -0400 Subject: [PATCH 3/3] Keep Rust chat template workspace unchanged --- templates/chat-console-rs/Cargo.toml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/templates/chat-console-rs/Cargo.toml b/templates/chat-console-rs/Cargo.toml index 946159277c9..af92400907a 100644 --- a/templates/chat-console-rs/Cargo.toml +++ b/templates/chat-console-rs/Cargo.toml @@ -4,10 +4,7 @@ version = "0.1.0" edition = "2024" [workspace] -members = ["spacetimedb"] - -[workspace.dependencies] -log = "0.4" +exclude = ["spacetimedb"] [dependencies] spacetimedb-sdk = { path = "../../sdks/rust" }