chore: remove dead code from providerConfigUtils and config API

- Remove unused functions: updateCommonConfigSnippet, replaceCommonConfigSnippet,
  replaceGeminiCommonConfigSnippet, updateTomlCommonConfigSnippet,
  replaceTomlCommonConfigSnippet and their internal helpers (~600 lines)
- Remove deprecated getClaudeCommonConfigSnippet and setClaudeCommonConfigSnippet
- Remove unused imports (deepClone, deepMerge)
This commit is contained in:
YoVinchen
2026-01-29 23:03:56 +08:00
Unverified
parent 0d67fba524
commit 06cde78945
2 changed files with 1 additions and 620 deletions
-22
View File
@@ -66,27 +66,6 @@ const pendingSyncParams: Record<
const SYNC_DEBOUNCE_MS = 500;
/**
* 获取 Claude 通用配置片段(已废弃,使用 getCommonConfigSnippet
* @returns 通用配置片段(JSON 字符串),如果不存在则返回 null
* @deprecated 使用 getCommonConfigSnippet('claude') 替代
*/
export async function getClaudeCommonConfigSnippet(): Promise<string | null> {
return invoke<string | null>("get_claude_common_config_snippet");
}
/**
* 设置 Claude 通用配置片段(已废弃,使用 setCommonConfigSnippet
* @param snippet - 通用配置片段(JSON 字符串)
* @throws 如果 JSON 格式无效
* @deprecated 使用 setCommonConfigSnippet('claude', snippet) 替代
*/
export async function setClaudeCommonConfigSnippet(
snippet: string,
): Promise<void> {
return invoke("set_claude_common_config_snippet", { snippet });
}
/**
* 获取通用配置片段(统一接口)
* @param appType - 应用类型(claude/codex/gemini
@@ -453,7 +432,6 @@ function getSettingsConfigString(
case "gemini":
// Gemini: settingsConfig 是包含 env 字段的 JSON 对象
// replaceGeminiCommonConfigSnippet 期望接收完整的 settingsConfig JSON
return typeof config === "string" ? config : JSON.stringify(config);
default:
+1 -598
View File
@@ -2,7 +2,7 @@
import type { TemplateValueConfig } from "../config/claudeProviderPresets";
import { normalizeQuotes } from "@/utils/textNormalization";
import { isPlainObject, deepClone, deepMerge } from "@/utils/configMerge";
import { isPlainObject } from "@/utils/configMerge";
// Gemini 通用配置禁止的键(共享常量,供 hook 和同步逻辑复用)
export const GEMINI_COMMON_ENV_FORBIDDEN_KEYS = [
@@ -12,26 +12,6 @@ export const GEMINI_COMMON_ENV_FORBIDDEN_KEYS = [
export type GeminiForbiddenEnvKey =
(typeof GEMINI_COMMON_ENV_FORBIDDEN_KEYS)[number];
const deepRemove = (
target: Record<string, any>,
source: Record<string, any>,
) => {
Object.entries(source).forEach(([key, value]) => {
if (!(key in target)) return;
if (isPlainObject(value) && isPlainObject(target[key])) {
// 只移除完全匹配的嵌套属性
deepRemove(target[key], value);
if (Object.keys(target[key]).length === 0) {
delete target[key];
}
} else if (isSubset(target[key], value)) {
// 只有当值完全匹配时才删除
delete target[key];
}
});
};
const isSubset = (target: any, source: any): boolean => {
if (isPlainObject(source)) {
if (!isPlainObject(target)) return false;
@@ -48,11 +28,6 @@ const isSubset = (target: any, source: any): boolean => {
return target === source;
};
export interface UpdateCommonConfigResult {
updatedConfig: string;
error?: string;
}
// 验证JSON配置格式
export const validateJsonConfig = (
value: string,
@@ -72,53 +47,6 @@ export const validateJsonConfig = (
}
};
// 将通用配置片段写入/移除 settingsConfig
export const updateCommonConfigSnippet = (
jsonString: string,
snippetString: string,
enabled: boolean,
): UpdateCommonConfigResult => {
let config: Record<string, any>;
try {
config = jsonString ? JSON.parse(jsonString) : {};
} catch (err) {
return {
updatedConfig: jsonString,
error: "配置 JSON 解析失败,无法写入通用配置",
};
}
if (!snippetString.trim()) {
return {
updatedConfig: JSON.stringify(config, null, 2),
};
}
// 使用统一的验证函数
const snippetError = validateJsonConfig(snippetString, "通用配置片段");
if (snippetError) {
return {
updatedConfig: JSON.stringify(config, null, 2),
error: snippetError,
};
}
const snippet = JSON.parse(snippetString) as Record<string, any>;
if (enabled) {
const merged = deepMerge(deepClone(config), snippet);
return {
updatedConfig: JSON.stringify(merged, null, 2),
};
}
const cloned = deepClone(config);
deepRemove(cloned, snippet);
return {
updatedConfig: JSON.stringify(cloned, null, 2),
};
};
// 检查当前配置是否已包含通用配置片段
export const hasCommonConfigSnippet = (
jsonString: string,
@@ -180,122 +108,6 @@ export const hasGeminiCommonConfigSnippet = (
}
};
/**
* 替换通用配置片段(用于同步更新)
* 先移除旧的通用配置,再添加新的通用配置
*/
export const replaceCommonConfigSnippet = (
jsonString: string,
oldSnippet: string,
newSnippet: string,
): UpdateCommonConfigResult => {
// 先移除旧的通用配置
const removeResult = updateCommonConfigSnippet(jsonString, oldSnippet, false);
if (removeResult.error) {
return removeResult;
}
// 再添加新的通用配置
return updateCommonConfigSnippet(
removeResult.updatedConfig,
newSnippet,
true,
);
};
/**
* 替换 Gemini 通用配置片段(用于同步更新)
* Gemini 的通用配置是 JSON 格式的 env 对象
*/
export const replaceGeminiCommonConfigSnippet = (
jsonString: string,
oldSnippet: string,
newSnippet: string,
): UpdateCommonConfigResult => {
try {
const config = jsonString ? JSON.parse(jsonString) : {};
// 校验 config 是对象类型
if (!isPlainObject(config)) {
return {
updatedConfig: jsonString,
error: "CONFIG_NOT_OBJECT",
};
}
const env = config.env ?? {};
// 校验 env 是对象类型
if (!isPlainObject(env)) {
return {
updatedConfig: jsonString,
error: "ENV_NOT_OBJECT",
};
}
// 解析旧的通用配置
let oldEnv: Record<string, string> = {};
if (oldSnippet.trim()) {
try {
const parsed = JSON.parse(oldSnippet);
if (isPlainObject(parsed)) {
oldEnv = parsed as Record<string, string>;
}
} catch {
// ignore parse error
}
}
// 解析新的通用配置
let newEnv: Record<string, string> = {};
if (newSnippet.trim()) {
try {
const parsed = JSON.parse(newSnippet);
if (isPlainObject(parsed)) {
// 过滤掉禁止的键
for (const [key, value] of Object.entries(parsed)) {
if (
typeof value === "string" &&
!GEMINI_COMMON_ENV_FORBIDDEN_KEYS.includes(
key as GeminiForbiddenEnvKey,
)
) {
newEnv[key] = value;
}
}
}
} catch {
return {
updatedConfig: jsonString,
error: "COMMON_CONFIG_JSON_INVALID",
};
}
}
// 移除旧的通用配置键值对
const updatedEnv = { ...env };
for (const [key, value] of Object.entries(oldEnv)) {
if (updatedEnv[key] === value) {
delete updatedEnv[key];
}
}
// 添加新的通用配置键值对
for (const [key, value] of Object.entries(newEnv)) {
updatedEnv[key] = value;
}
return {
updatedConfig: JSON.stringify({ ...config, env: updatedEnv }, null, 2),
};
} catch (err) {
return {
updatedConfig: jsonString,
error: "CONFIG_JSON_PARSE_FAILED",
};
}
};
// 读取配置中的 API Key(支持 Claude, Codex, Gemini
export const getApiKeyFromConfig = (
jsonString: string,
@@ -460,389 +272,6 @@ export const setApiKeyInConfig = (
}
};
// ========== TOML Config Utilities ==========
export interface UpdateTomlCommonConfigResult {
updatedConfig: string;
error?: string;
}
const TOML_COMMON_CONFIG_START = "# cc-switch:common-config:start";
const TOML_COMMON_CONFIG_END = "# cc-switch:common-config:end";
/**
* 移除旧版标记块(兼容性清理)
* 仅用于清理历史遗留的标记,新版本不再写入标记
*/
const stripTomlCommonConfigBlock = (tomlString: string): string => {
const startIndex = tomlString.indexOf(TOML_COMMON_CONFIG_START);
const endIndex = tomlString.indexOf(TOML_COMMON_CONFIG_END);
if (startIndex === -1 || endIndex === -1 || endIndex < startIndex) {
return tomlString;
}
const before = tomlString.slice(0, startIndex);
const after = tomlString.slice(endIndex + TOML_COMMON_CONFIG_END.length);
return `${before}${after}`;
};
/**
* 解析 TOML 文本为段落结构
* 返回 { topLevel: string[], sections: Map<string, string[]> }
* - topLevel: 顶级键值对行(在任何 [section] 之前)
* - sections: 每个 [section] 及其内容行
*/
interface TomlParsedStructure {
topLevel: string[];
sections: Map<string, string[]>;
sectionOrder: string[];
}
function parseTomlStructure(tomlText: string): TomlParsedStructure {
const lines = tomlText.split("\n");
const topLevel: string[] = [];
const sections = new Map<string, string[]>();
const sectionOrder: string[] = [];
let currentSection: string | null = null;
for (const line of lines) {
const trimmed = line.trim();
// 检查是否是 section 头(如 [mcp_servers.mcpServers]
const sectionMatch = trimmed.match(/^\[([^\]]+)\]$/);
if (sectionMatch) {
currentSection = sectionMatch[1];
if (!sections.has(currentSection)) {
sections.set(currentSection, []);
sectionOrder.push(currentSection);
}
continue;
}
if (currentSection === null) {
// 顶级内容
topLevel.push(line);
} else {
// section 内容
const sectionLines = sections.get(currentSection)!;
sectionLines.push(line);
}
}
return { topLevel, sections, sectionOrder };
}
/**
* 从顶级行中提取键名
*/
function extractKeyFromLine(line: string): string | null {
const trimmed = line.trim();
// 跳过空行和注释
if (!trimmed || trimmed.startsWith("#")) {
return null;
}
// 匹配 key = value 格式
const match = trimmed.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*=/);
return match ? match[1] : null;
}
/**
* 智能合并 TOML 配置
* - 顶级键值对:snippet 中的键会覆盖或添加到 base 的顶级区域
* - sections:同名 section 会合并内容,不同 section 会追加
*/
function mergeTomlConfigs(baseText: string, snippetText: string): string {
const base = parseTomlStructure(baseText);
const snippet = parseTomlStructure(snippetText);
// 1. 合并顶级键值对
// 提取 snippet 中的顶级键
const snippetTopLevelKeys = new Set<string>();
for (const line of snippet.topLevel) {
const key = extractKeyFromLine(line);
if (key) {
snippetTopLevelKeys.add(key);
}
}
// 过滤 base 中被 snippet 覆盖的键
const filteredBaseTopLevel = base.topLevel.filter((line) => {
const key = extractKeyFromLine(line);
return key === null || !snippetTopLevelKeys.has(key);
});
// 合并顶级内容:base 的非覆盖行 + snippet 的顶级行
const mergedTopLevel = [...filteredBaseTopLevel];
// 添加 snippet 的顶级行(跳过空行,除非是有意义的)
for (const line of snippet.topLevel) {
const trimmed = line.trim();
if (trimmed) {
mergedTopLevel.push(line);
}
}
// 2. 合并 sections
const mergedSections = new Map<string, string[]>();
const mergedSectionOrder: string[] = [];
// 先添加 base 的 sections
for (const sectionName of base.sectionOrder) {
mergedSections.set(sectionName, [...base.sections.get(sectionName)!]);
mergedSectionOrder.push(sectionName);
}
// 合并 snippet 的 sections
for (const sectionName of snippet.sectionOrder) {
const snippetLines = snippet.sections.get(sectionName)!;
if (mergedSections.has(sectionName)) {
// 同名 section:合并内容
const existingLines = mergedSections.get(sectionName)!;
// 提取 snippet section 中的键
const snippetSectionKeys = new Set<string>();
for (const line of snippetLines) {
const key = extractKeyFromLine(line);
if (key) {
snippetSectionKeys.add(key);
}
}
// 过滤 existing 中被覆盖的键
const filteredExisting = existingLines.filter((line) => {
const key = extractKeyFromLine(line);
return key === null || !snippetSectionKeys.has(key);
});
// 合并:existing 的非覆盖行 + snippet 的行
const merged = [...filteredExisting];
for (const line of snippetLines) {
const trimmed = line.trim();
if (trimmed) {
merged.push(line);
}
}
mergedSections.set(sectionName, merged);
} else {
// 新 section:直接添加
mergedSections.set(sectionName, [...snippetLines]);
mergedSectionOrder.push(sectionName);
}
}
// 3. 重建 TOML 文本
const resultLines: string[] = [];
// 添加顶级内容(清理多余空行)
let lastWasEmpty = true;
for (const line of mergedTopLevel) {
const isEmpty = !line.trim();
if (isEmpty && lastWasEmpty) {
continue; // 跳过连续空行
}
resultLines.push(line);
lastWasEmpty = isEmpty;
}
// 添加 sections
for (const sectionName of mergedSectionOrder) {
const sectionLines = mergedSections.get(sectionName)!;
// 确保 section 前有空行分隔
if (resultLines.length > 0 && resultLines[resultLines.length - 1].trim()) {
resultLines.push("");
}
// 添加 section 头
resultLines.push(`[${sectionName}]`);
// 添加 section 内容(清理多余空行)
lastWasEmpty = false;
for (const line of sectionLines) {
const isEmpty = !line.trim();
if (isEmpty && lastWasEmpty) {
continue;
}
resultLines.push(line);
lastWasEmpty = isEmpty;
}
}
// 清理末尾空行,确保以单个换行结尾
while (
resultLines.length > 0 &&
!resultLines[resultLines.length - 1].trim()
) {
resultLines.pop();
}
return resultLines.join("\n") + "\n";
}
/**
* 从 TOML 配置中移除指定的片段内容
* - 移除 snippet 中定义的顶级键
* - 移除 snippet 中定义的 section 内的键(如果 section 变空则移除整个 section
*/
function removeTomlSnippet(baseText: string, snippetText: string): string {
const base = parseTomlStructure(baseText);
const snippet = parseTomlStructure(snippetText);
// 1. 从顶级移除 snippet 的键
const snippetTopLevelKeys = new Set<string>();
for (const line of snippet.topLevel) {
const key = extractKeyFromLine(line);
if (key) {
snippetTopLevelKeys.add(key);
}
}
const filteredTopLevel = base.topLevel.filter((line) => {
const key = extractKeyFromLine(line);
return key === null || !snippetTopLevelKeys.has(key);
});
// 2. 从 sections 移除 snippet 的键
const filteredSections = new Map<string, string[]>();
const filteredSectionOrder: string[] = [];
for (const sectionName of base.sectionOrder) {
const baseLines = base.sections.get(sectionName)!;
// 检查 snippet 是否有这个 section
if (snippet.sections.has(sectionName)) {
const snippetLines = snippet.sections.get(sectionName)!;
// 提取 snippet section 中的键
const snippetSectionKeys = new Set<string>();
for (const line of snippetLines) {
const key = extractKeyFromLine(line);
if (key) {
snippetSectionKeys.add(key);
}
}
// 过滤掉 snippet 中的键
const filtered = baseLines.filter((line) => {
const key = extractKeyFromLine(line);
return key === null || !snippetSectionKeys.has(key);
});
// 检查过滤后是否还有实质内容
const hasContent = filtered.some((line) => {
const trimmed = line.trim();
return trimmed && !trimmed.startsWith("#");
});
if (hasContent) {
filteredSections.set(sectionName, filtered);
filteredSectionOrder.push(sectionName);
}
// 如果没有实质内容,整个 section 被移除
} else {
// snippet 中没有这个 section,保留
filteredSections.set(sectionName, baseLines);
filteredSectionOrder.push(sectionName);
}
}
// 3. 重建 TOML 文本
const resultLines: string[] = [];
// 添加顶级内容
let lastWasEmpty = true;
for (const line of filteredTopLevel) {
const isEmpty = !line.trim();
if (isEmpty && lastWasEmpty) {
continue;
}
resultLines.push(line);
lastWasEmpty = isEmpty;
}
// 添加 sections
for (const sectionName of filteredSectionOrder) {
const sectionLines = filteredSections.get(sectionName)!;
if (resultLines.length > 0 && resultLines[resultLines.length - 1].trim()) {
resultLines.push("");
}
resultLines.push(`[${sectionName}]`);
lastWasEmpty = false;
for (const line of sectionLines) {
const isEmpty = !line.trim();
if (isEmpty && lastWasEmpty) {
continue;
}
resultLines.push(line);
lastWasEmpty = isEmpty;
}
}
while (
resultLines.length > 0 &&
!resultLines[resultLines.length - 1].trim()
) {
resultLines.pop();
}
return resultLines.length > 0 ? resultLines.join("\n") + "\n" : "";
}
// 将通用配置片段写入/移除 TOML 配置
// 使用智能合并,避免重复定义 section
export const updateTomlCommonConfigSnippet = (
tomlString: string,
snippetString: string,
enabled: boolean,
): UpdateTomlCommonConfigResult => {
if (enabled) {
if (!snippetString.trim()) {
return {
updatedConfig: tomlString,
};
}
// 先清理旧版标记块(兼容性)
let baseConfig = stripTomlCommonConfigBlock(tomlString);
baseConfig = baseConfig.replace(/\n{3,}/g, "\n\n").trim();
if (baseConfig) {
baseConfig += "\n";
}
// 使用智能合并
const merged = mergeTomlConfigs(baseConfig, snippetString);
return {
updatedConfig: merged,
};
} else {
// 移除通用配置
// 先清理旧版标记块(兼容性)
const strippedConfig = stripTomlCommonConfigBlock(tomlString);
if (strippedConfig !== tomlString) {
const cleaned = strippedConfig.replace(/\n{3,}/g, "\n\n").trim();
return {
updatedConfig: cleaned ? cleaned + "\n" : "",
};
}
// 使用智能移除
if (snippetString.trim()) {
const removed = removeTomlSnippet(tomlString, snippetString);
return {
updatedConfig: removed,
};
}
return {
updatedConfig: tomlString,
};
}
};
// 检查 TOML 配置是否已包含通用配置片段
export const hasTomlCommonConfigSnippet = (
tomlString: string,
@@ -859,32 +288,6 @@ export const hasTomlCommonConfigSnippet = (
);
};
/**
* 替换 TOML 通用配置片段(用于同步更新)
* 先移除旧的通用配置,再添加新的通用配置
*/
export const replaceTomlCommonConfigSnippet = (
tomlString: string,
oldSnippet: string,
newSnippet: string,
): UpdateTomlCommonConfigResult => {
// 先清理旧版标记块(兼容性)
let configWithoutOld = stripTomlCommonConfigBlock(tomlString);
// 通过内容匹配移除旧片段
if (oldSnippet.trim() && configWithoutOld.includes(oldSnippet.trim())) {
configWithoutOld = configWithoutOld.replace(oldSnippet.trim(), "");
// 清理多余的空行
configWithoutOld = configWithoutOld.replace(/\n{3,}/g, "\n\n").trim();
if (configWithoutOld) {
configWithoutOld += "\n";
}
}
// 添加新的通用配置
return updateTomlCommonConfigSnippet(configWithoutOld, newSnippet, true);
};
// ========== Codex base_url utils ==========
// 从 Codex 的 TOML 配置文本中提取 base_url(支持单/双引号)