From 46c1daca5eee3c44d042fbd5c21c22cee715d7ad Mon Sep 17 00:00:00 2001 From: Illia Polosukhin Date: Fri, 13 Feb 2026 18:27:53 -0800 Subject: [PATCH] feat: add interactive database backend selection during onboarding Previously the onboarding wizard silently defaulted to PostgreSQL because libsql wasn't in the default feature set. Now both backends ship by default and the wizard presents a selection prompt when both are available. DATABASE_BACKEND env var still bypasses the prompt for headless/CI use. Co-Authored-By: Claude Opus 4.6 --- Cargo.toml | 2 +- src/setup/wizard.rs | 50 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6a11219a..7c3f40b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -138,7 +138,7 @@ pretty_assertions = "1" tempfile = "3" [features] -default = ["postgres"] +default = ["postgres", "libsql"] postgres = [ "dep:deadpool-postgres", "dep:tokio-postgres", diff --git a/src/setup/wizard.rs b/src/setup/wizard.rs index 696a7a08..688c3bc6 100644 --- a/src/setup/wizard.rs +++ b/src/setup/wizard.rs @@ -165,20 +165,50 @@ impl SetupWizard { /// Step 1: Database connection. async fn step_database(&mut self) -> Result<(), SetupError> { - // Determine which backend to use based on compile-time features. - // When both features are enabled, prefer the currently configured backend - // or default to postgres. + // When both features are compiled, let the user choose. + // If DATABASE_BACKEND is already set in the environment, respect it. #[cfg(all(feature = "postgres", feature = "libsql"))] { - let backend = std::env::var("DATABASE_BACKEND") - .ok() - .or_else(|| self.settings.database_backend.clone()) - .unwrap_or_else(|| "postgres".to_string()); + // Check if a backend is already pinned via env var + let env_backend = std::env::var("DATABASE_BACKEND").ok(); - if backend == "libsql" || backend == "turso" || backend == "sqlite" { - return self.step_database_libsql().await; + if let Some(ref backend) = env_backend { + if backend == "libsql" || backend == "turso" || backend == "sqlite" { + return self.step_database_libsql().await; + } + return self.step_database_postgres().await; + } + + // Interactive selection + let pre_selected = self.settings.database_backend.as_deref().map(|b| match b { + "libsql" | "turso" | "sqlite" => 1, + _ => 0, + }); + + print_info("Which database backend would you like to use?"); + println!(); + + let options = &[ + "PostgreSQL - production-grade, requires a running server", + "libSQL - embedded SQLite, zero dependencies, optional Turso cloud sync", + ]; + let choice = + select_one("Select a database backend:", options).map_err(SetupError::Io)?; + + // If the user picked something different from what was pre-selected, clear + // stale connection settings so the next step starts fresh. + if let Some(prev) = pre_selected + && prev != choice + { + self.settings.database_url = None; + self.settings.libsql_path = None; + self.settings.libsql_url = None; + } + + match choice { + 1 => return self.step_database_libsql().await, + _ => return self.step_database_postgres().await, } - return self.step_database_postgres().await; } #[cfg(all(feature = "postgres", not(feature = "libsql")))]