mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-04-25 11:28:46 +08:00
Compare commits
4 Commits
refactor/u
...
fix/proxy-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2af8c82977 | ||
|
|
d4286ab90a | ||
|
|
f7c6947220 | ||
|
|
8fccc2a286 |
@@ -75,8 +75,7 @@ mod tests {
|
|||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_macos_app_bundle_path_valid() {
|
fn test_get_macos_app_bundle_path_valid() {
|
||||||
let exe_path =
|
let exe_path = std::path::Path::new("/Applications/CC Switch.app/Contents/MacOS/CC Switch");
|
||||||
std::path::Path::new("/Applications/CC Switch.app/Contents/MacOS/CC Switch");
|
|
||||||
let result = get_macos_app_bundle_path(exe_path);
|
let result = get_macos_app_bundle_path(exe_path);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result,
|
result,
|
||||||
@@ -92,7 +91,9 @@ mod tests {
|
|||||||
let result = get_macos_app_bundle_path(exe_path);
|
let result = get_macos_app_bundle_path(exe_path);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result,
|
result,
|
||||||
Some(std::path::PathBuf::from("/Users/test/My Apps/CC Switch.app"))
|
Some(std::path::PathBuf::from(
|
||||||
|
"/Users/test/My Apps/CC Switch.app"
|
||||||
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,22 +12,22 @@ const UNIVERSAL_PROVIDERS_KEY: &str = "universal_providers";
|
|||||||
|
|
||||||
impl Database {
|
impl Database {
|
||||||
/// 获取所有统一供应商
|
/// 获取所有统一供应商
|
||||||
pub fn get_all_universal_providers(&self) -> Result<HashMap<String, UniversalProvider>, AppError> {
|
pub fn get_all_universal_providers(
|
||||||
|
&self,
|
||||||
|
) -> Result<HashMap<String, UniversalProvider>, AppError> {
|
||||||
let conn = lock_conn!(self.conn);
|
let conn = lock_conn!(self.conn);
|
||||||
|
|
||||||
let mut stmt = conn
|
let mut stmt = conn
|
||||||
.prepare("SELECT value FROM settings WHERE key = ?")
|
.prepare("SELECT value FROM settings WHERE key = ?")
|
||||||
.map_err(|e| AppError::Database(e.to_string()))?;
|
.map_err(|e| AppError::Database(e.to_string()))?;
|
||||||
|
|
||||||
let result: Option<String> = stmt
|
let result: Option<String> = stmt
|
||||||
.query_row([UNIVERSAL_PROVIDERS_KEY], |row| row.get(0))
|
.query_row([UNIVERSAL_PROVIDERS_KEY], |row| row.get(0))
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Some(json) => {
|
Some(json) => serde_json::from_str(&json)
|
||||||
serde_json::from_str(&json)
|
.map_err(|e| AppError::Database(format!("解析统一供应商数据失败: {e}"))),
|
||||||
.map_err(|e| AppError::Database(format!("解析统一供应商数据失败: {e}")))
|
|
||||||
}
|
|
||||||
None => Ok(HashMap::new()),
|
None => Ok(HashMap::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,14 +62,13 @@ impl Database {
|
|||||||
) -> Result<(), AppError> {
|
) -> Result<(), AppError> {
|
||||||
let conn = lock_conn!(self.conn);
|
let conn = lock_conn!(self.conn);
|
||||||
let json = to_json_string(providers)?;
|
let json = to_json_string(providers)?;
|
||||||
|
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)",
|
"INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)",
|
||||||
[UNIVERSAL_PROVIDERS_KEY, &json],
|
[UNIVERSAL_PROVIDERS_KEY, &json],
|
||||||
)
|
)
|
||||||
.map_err(|e| AppError::Database(e.to_string()))?;
|
.map_err(|e| AppError::Database(e.to_string()))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -233,6 +233,24 @@ impl Database {
|
|||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 尝试添加基础配置列到 proxy_config 表(兼容 v3.9.0-2 升级)
|
||||||
|
let _ = conn.execute(
|
||||||
|
"ALTER TABLE proxy_config ADD COLUMN proxy_enabled INTEGER NOT NULL DEFAULT 0",
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
let _ = conn.execute(
|
||||||
|
"ALTER TABLE proxy_config ADD COLUMN listen_address TEXT NOT NULL DEFAULT '127.0.0.1'",
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
let _ = conn.execute(
|
||||||
|
"ALTER TABLE proxy_config ADD COLUMN listen_port INTEGER NOT NULL DEFAULT 5000",
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
let _ = conn.execute(
|
||||||
|
"ALTER TABLE proxy_config ADD COLUMN enable_logging INTEGER NOT NULL DEFAULT 1",
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
// 尝试添加超时配置列到 proxy_config 表
|
// 尝试添加超时配置列到 proxy_config 表
|
||||||
let _ = conn.execute(
|
let _ = conn.execute(
|
||||||
"ALTER TABLE proxy_config ADD COLUMN streaming_first_byte_timeout INTEGER NOT NULL DEFAULT 30",
|
"ALTER TABLE proxy_config ADD COLUMN streaming_first_byte_timeout INTEGER NOT NULL DEFAULT 30",
|
||||||
@@ -247,6 +265,14 @@ impl Database {
|
|||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 兼容:若旧版 proxy_config 仍为单例结构(无 app_type),则在启动时直接转换为三行结构
|
||||||
|
// 说明:user_version=2 时不会再触发 v1->v2 迁移,但新代码查询依赖 app_type 列。
|
||||||
|
if Self::table_exists(conn, "proxy_config")?
|
||||||
|
&& !Self::has_column(conn, "proxy_config", "app_type")?
|
||||||
|
{
|
||||||
|
Self::migrate_proxy_config_to_per_app(conn)?;
|
||||||
|
}
|
||||||
|
|
||||||
// 确保 in_failover_queue 列存在(对于已存在的 v2 数据库)
|
// 确保 in_failover_queue 列存在(对于已存在的 v2 数据库)
|
||||||
Self::add_column_if_missing(
|
Self::add_column_if_missing(
|
||||||
conn,
|
conn,
|
||||||
@@ -411,6 +437,32 @@ impl Database {
|
|||||||
|
|
||||||
// 添加代理超时配置字段
|
// 添加代理超时配置字段
|
||||||
if Self::table_exists(conn, "proxy_config")? {
|
if Self::table_exists(conn, "proxy_config")? {
|
||||||
|
// 兼容旧版本缺失的基础字段
|
||||||
|
Self::add_column_if_missing(
|
||||||
|
conn,
|
||||||
|
"proxy_config",
|
||||||
|
"proxy_enabled",
|
||||||
|
"INTEGER NOT NULL DEFAULT 0",
|
||||||
|
)?;
|
||||||
|
Self::add_column_if_missing(
|
||||||
|
conn,
|
||||||
|
"proxy_config",
|
||||||
|
"listen_address",
|
||||||
|
"TEXT NOT NULL DEFAULT '127.0.0.1'",
|
||||||
|
)?;
|
||||||
|
Self::add_column_if_missing(
|
||||||
|
conn,
|
||||||
|
"proxy_config",
|
||||||
|
"listen_port",
|
||||||
|
"INTEGER NOT NULL DEFAULT 5000",
|
||||||
|
)?;
|
||||||
|
Self::add_column_if_missing(
|
||||||
|
conn,
|
||||||
|
"proxy_config",
|
||||||
|
"enable_logging",
|
||||||
|
"INTEGER NOT NULL DEFAULT 1",
|
||||||
|
)?;
|
||||||
|
|
||||||
Self::add_column_if_missing(
|
Self::add_column_if_missing(
|
||||||
conn,
|
conn,
|
||||||
"proxy_config",
|
"proxy_config",
|
||||||
|
|||||||
@@ -201,6 +201,53 @@ fn migration_aligns_column_defaults_and_types() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn create_tables_repairs_legacy_proxy_config_singleton_to_per_app() {
|
||||||
|
let conn = Connection::open_in_memory().expect("open memory db");
|
||||||
|
|
||||||
|
// 模拟测试版 v2:user_version=2,但 proxy_config 仍是单例结构(无 app_type)
|
||||||
|
Database::set_user_version(&conn, 2).expect("set user_version");
|
||||||
|
conn.execute_batch(
|
||||||
|
r#"
|
||||||
|
CREATE TABLE proxy_config (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
enabled INTEGER NOT NULL DEFAULT 0,
|
||||||
|
listen_address TEXT NOT NULL DEFAULT '127.0.0.1',
|
||||||
|
listen_port INTEGER NOT NULL DEFAULT 5000,
|
||||||
|
max_retries INTEGER NOT NULL DEFAULT 3,
|
||||||
|
request_timeout INTEGER NOT NULL DEFAULT 300,
|
||||||
|
enable_logging INTEGER NOT NULL DEFAULT 1,
|
||||||
|
target_app TEXT NOT NULL DEFAULT 'claude',
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
|
);
|
||||||
|
INSERT INTO proxy_config (id, enabled) VALUES (1, 1);
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.expect("seed legacy proxy_config");
|
||||||
|
|
||||||
|
Database::create_tables_on_conn(&conn).expect("create tables should repair proxy_config");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
Database::has_column(&conn, "proxy_config", "app_type").expect("check app_type"),
|
||||||
|
"proxy_config should be migrated to per-app structure"
|
||||||
|
);
|
||||||
|
|
||||||
|
let count: i32 = conn
|
||||||
|
.query_row("SELECT COUNT(*) FROM proxy_config", [], |r| r.get(0))
|
||||||
|
.expect("count rows");
|
||||||
|
assert_eq!(count, 3, "per-app proxy_config should have 3 rows");
|
||||||
|
|
||||||
|
// 新结构下应能按 app_type 查询
|
||||||
|
let _: i32 = conn
|
||||||
|
.query_row(
|
||||||
|
"SELECT COUNT(*) FROM proxy_config WHERE app_type = 'claude'",
|
||||||
|
[],
|
||||||
|
|r| r.get(0),
|
||||||
|
)
|
||||||
|
.expect("query by app_type");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn dry_run_does_not_write_to_disk() {
|
fn dry_run_does_not_write_to_disk() {
|
||||||
// Create minimal valid config for migration
|
// Create minimal valid config for migration
|
||||||
|
|||||||
Reference in New Issue
Block a user