From 58c4f19dd6a669a3b06c80c39ada583c33fb6e2b Mon Sep 17 00:00:00 2001 From: Jerryplusy Date: Tue, 6 Jan 2026 12:49:35 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(configControl.js):=20ensure=20?= =?UTF-8?q?data=20and=20plugin=20config=20directories=20exist=20and=20hand?= =?UTF-8?q?le=20missing=20files=20gracefully?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/config/configControl.js | 114 ++++++++++++++++++++++++++++-------- 1 file changed, 91 insertions(+), 23 deletions(-) diff --git a/lib/config/configControl.js b/lib/config/configControl.js index ff7a234..5930f1c 100644 --- a/lib/config/configControl.js +++ b/lib/config/configControl.js @@ -15,32 +15,61 @@ let watchers = []; */ async function init() { try { + // 确保数据配置目录存在 try { await fsp.access(dataConfigPath); } catch { await fsp.mkdir(dataConfigPath, { recursive: true }); logger.mark(`[crystelf-plugin] 配置目录创建成功: ${dataConfigPath}`); } + + // 确保默认配置目录存在 + try { + await fsp.access(pluginConfigPath); + } catch { + logger.warn(`[crystelf-plugin] 默认配置目录不存在: ${pluginConfigPath}`); + } + + // 处理主配置文件 const pluginDefaultFile = path.join(pluginConfigPath, 'config.json'); try { await fsp.access(configFile); } catch { - await fsp.copyFile(pluginDefaultFile, configFile); - logger.mark(`[crystelf-plugin] 默认配置复制成功: ${configFile}`); + try { + await fsp.copyFile(pluginDefaultFile, configFile); + logger.mark(`[crystelf-plugin] 默认配置复制成功: ${configFile}`); + } catch (copyError) { + logger.warn(`[crystelf-plugin] 复制默认配置失败,创建空配置: ${copyError.message}`); + await fc.writeJSON(configFile, {}); + } } - const pluginFiles = (await fsp.readdir(pluginConfigPath)).filter((f) => f.endsWith('.json')); + let pluginFiles = []; + try { + pluginFiles = (await fsp.readdir(pluginConfigPath)).filter((f) => f.endsWith('.json')); + } catch (error) { + logger.warn(`[crystelf-plugin] 读取默认配置目录失败: ${error.message}`); + } + + // 复制缺失的配置文件 for (const file of pluginFiles) { const pluginFilePath = path.join(pluginConfigPath, file); const dataFilePath = path.join(dataConfigPath, file); try { await fsp.access(dataFilePath); } catch { - await fsp.copyFile(pluginFilePath, dataFilePath); - logger.mark(`[crystelf-plugin] 配置文件缺失,已复制: ${file}`); + try { + await fsp.copyFile(pluginFilePath, dataFilePath); + logger.mark(`[crystelf-plugin] 配置文件缺失,已复制: ${file}`); + } catch (copyError) { + logger.warn(`[crystelf-plugin] 复制配置文件失败 ${file}: ${copyError.message}`); + } } } + + // 读取所有配置文件 const files = (await fsp.readdir(dataConfigPath)).filter((f) => f.endsWith('.json')); configCache = {}; + for (const file of files) { const filePath = path.join(dataConfigPath, file); const name = path.basename(file, '.json'); @@ -50,7 +79,9 @@ async function init() { try { await fsp.access(pluginFilePath); const pluginData = await fc.readJSON(pluginFilePath); + if (Array.isArray(data) && Array.isArray(pluginData)) { + // 合并数组类型配置 const strSet = new Set(data.map((x) => JSON.stringify(x))); for (const item of pluginData) { const str = JSON.stringify(item); @@ -60,20 +91,28 @@ async function init() { } } } else if (!Array.isArray(data) && !Array.isArray(pluginData)) { + // 合并对象类型配置 data = fc.mergeConfig(data, pluginData); } + + // 保存合并后的配置 await fc.writeJSON(filePath, data); - } catch {} + } catch (mergeError) { + logger.error('[crystelf-plugin]合并配置失败..'); + // 忽略合并错误,使用现有数据 + } + configCache[name] = data; } catch (e) { logger.warn(`[crystelf-plugin] 读取配置文件 ${file} 失败:`, e); } } + if (configCache.debug) { logger.info('[crystelf-plugin] 配置模块初始化成功..'); } } catch (err) { - logger.warn('[crystelf-plugin] 配置初始化失败,使用空配置..', err); + logger.warn('[crystelf-plugin] 配置初始化失败,使用空配置..', err); configCache = {}; } } @@ -120,36 +159,65 @@ const configControl = { }, async set(key, value) { + // 更新内存中的配置 configCache[key] = value; const filePath = path.join(dataConfigPath, `${key}.json`); + try { + // 尝试访问文件,如果存在则直接写入 await fsp.access(filePath); await fc.writeJSON(filePath, value); - } catch { - let cfg = await fc.readJSON(configFile); - if (Array.isArray(cfg)) { - cfg.push(value); - } else { - cfg[key] = value; + } catch (error) { + // 文件不存在,创建新文件 + try { + // 确保目录存在 + await fsp.mkdir(dataConfigPath, { recursive: true }); + // 直接写入新文件 + await fc.writeJSON(filePath, value); + logger.mark(`[crystelf-plugin] 创建新配置文件: ${filePath}`); + } catch (writeError) { + logger.error(`[crystelf-plugin] 创建配置文件失败: ${writeError.message}`); + throw writeError; + } + } + }, + + /** + * 批量设置配置 + * @param {Object} configs - 配置对象,键为配置名,值为配置数据 + */ + async setMultiple(configs) { + // 确保目录存在 + await fsp.mkdir(dataConfigPath, { recursive: true }); + + for (const [key, value] of Object.entries(configs)) { + try { + // 更新内存中的配置 + configCache[key] = value; + const filePath = path.join(dataConfigPath, `${key}.json`); + + // 写入配置文件 + await fc.writeJSON(filePath, value); + } catch (error) { + logger.error(`[crystelf-plugin] 设置配置失败 ${key}: ${error.message}`); + throw error; } - await fc.writeJSON(configFile, cfg); } }, async save() { + // 确保目录存在 + await fsp.mkdir(dataConfigPath, { recursive: true }); + for (const [key, value] of Object.entries(configCache)) { const filePath = path.join(dataConfigPath, `${key}.json`); + try { - await fsp.access(filePath); + // 直接写入配置文件 await fc.writeJSON(filePath, value); - } catch { - let cfg = await fc.readJSON(configFile); - if (Array.isArray(cfg)) { - cfg = value; - } else { - cfg[key] = value; - } - await fc.writeJSON(configFile, cfg); + } catch (error) { + logger.error(`[crystelf-plugin] 保存配置文件失败 ${filePath}: ${error.message}`); + throw error; } } },