refactor: 配置相关代码重构,减少重复代码。

pull/445/head
王良 2025-01-23 16:58:33 +08:00
parent 95de18a60f
commit 4f690ae0a7
7 changed files with 183 additions and 266 deletions

View File

@ -1,5 +1,4 @@
const fs = require('node:fs') const fs = require('node:fs')
const path = require('node:path')
const jsonApi = require('@docmirror/mitmproxy/src/json') const jsonApi = require('@docmirror/mitmproxy/src/json')
const lodash = require('lodash') const lodash = require('lodash')
const request = require('request') const request = require('request')
@ -7,6 +6,7 @@ const defConfig = require('./config/index.js')
const mergeApi = require('./merge.js') const mergeApi = require('./merge.js')
const Shell = require('./shell') const Shell = require('./shell')
const log = require('./utils/util.log') const log = require('./utils/util.log')
const configLoader = require('./config/local-config-loader')
let configTarget = lodash.cloneDeep(defConfig) let configTarget = lodash.cloneDeep(defConfig)
@ -14,34 +14,6 @@ function get () {
return configTarget return configTarget
} }
const getDefaultConfigBasePath = function () {
return get().server.setting.userBasePath
}
function _getRemoteSavePath (suffix = '') {
const dir = getDefaultConfigBasePath()
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir)
}
return path.join(dir, `/remote_config${suffix}.json5`)
}
function _getConfigPath () {
const dir = getDefaultConfigBasePath()
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir)
return path.join(dir, '/config.json')
} else {
// 兼容1.7.3及以下版本的配置文件处理逻辑
const newFilePath = path.join(dir, '/config.json')
const oldFilePath = path.join(dir, '/config.json5')
if (!fs.existsSync(newFilePath) && fs.existsSync(oldFilePath)) {
return oldFilePath // 如果新文件不存在,且旧文件存在,则返回旧文件路径
}
return newFilePath
}
}
let timer let timer
const configApi = { const configApi = {
async startAutoDownloadRemoteConfig () { async startAutoDownloadRemoteConfig () {
@ -68,13 +40,10 @@ const configApi = {
} }
const remoteConfig = get().app.remoteConfig const remoteConfig = get().app.remoteConfig
await configApi.doDownloadCommonRemoteConfig(remoteConfig.url) await configApi.doDownloadRemoteConfig(remoteConfig.url)
await configApi.doDownloadCommonRemoteConfig(remoteConfig.personalUrl, '_personal') await configApi.doDownloadRemoteConfig(remoteConfig.personalUrl, '_personal')
}, },
doDownloadCommonRemoteConfig (remoteConfigUrl, suffix = '') { doDownloadRemoteConfig (remoteConfigUrl, suffix = '') {
if (get().app.remoteConfig.enabled !== true) {
return
}
if (!remoteConfigUrl) { if (!remoteConfigUrl) {
// 删除保存的远程配置文件 // 删除保存的远程配置文件
configApi.deleteRemoteConfigFile(suffix) configApi.deleteRemoteConfigFile(suffix)
@ -116,7 +85,7 @@ const configApi = {
} }
if (remoteConfig != null) { if (remoteConfig != null) {
const remoteSavePath = _getRemoteSavePath(suffix) const remoteSavePath = configLoader.getRemoteConfigPath(suffix)
fs.writeFileSync(remoteSavePath, body) fs.writeFileSync(remoteSavePath, body)
log.info('保存远程配置文件成功:', remoteSavePath) log.info('保存远程配置文件成功:', remoteSavePath)
} else { } else {
@ -139,35 +108,15 @@ const configApi = {
}) })
}, },
deleteRemoteConfigFile (suffix = '') { deleteRemoteConfigFile (suffix = '') {
const remoteSavePath = _getRemoteSavePath(suffix) const remoteSavePath = configLoader.getRemoteConfigPath(suffix)
if (fs.existsSync(remoteSavePath)) { if (fs.existsSync(remoteSavePath)) {
fs.unlinkSync(remoteSavePath) fs.unlinkSync(remoteSavePath)
log.info('删除远程配置文件成功:', remoteSavePath) log.info('删除远程配置文件成功:', remoteSavePath)
} }
}, },
readRemoteConfig (suffix = '') {
try {
return jsonApi.parse(configApi.readRemoteConfigStr(suffix))
} catch (e) {
log.error(`读取远程配置失败suffix: ${suffix}`, e)
return {}
}
},
readRemoteConfigStr (suffix = '') { readRemoteConfigStr (suffix = '') {
if (get().app.remoteConfig.enabled !== true) {
if (suffix === '_personal') {
if (!get().app.remoteConfig.personalUrl) {
return '{}'
}
} else if (suffix === '') {
if (!get().app.remoteConfig.url) {
return '{}'
}
}
return '{}'
}
try { try {
const path = _getRemoteSavePath(suffix) const path = configLoader.getRemoteConfigPath(suffix)
if (fs.existsSync(path)) { if (fs.existsSync(path)) {
const file = fs.readFileSync(path) const file = fs.readFileSync(path)
log.info('读取远程配置文件内容成功:', path) log.info('读取远程配置文件内容成功:', path)
@ -187,21 +136,23 @@ const configApi = {
*/ */
save (newConfig) { save (newConfig) {
// 对比默认config的异同 // 对比默认config的异同
let defConfig = configApi.getDefault() const defConfig = configApi.cloneDefault()
// 如果开启了远程配置,则读取远程配置,合并到默认配置中 // 如果开启了远程配置,则读取远程配置,合并到默认配置中
if (get().app.remoteConfig.enabled === true) { if (get().app.remoteConfig.enabled === true) {
if (get().app.remoteConfig.url) { if (get().app.remoteConfig.url) {
defConfig = mergeApi.doMerge(defConfig, configApi.readRemoteConfig()) mergeApi.doMerge(defConfig, configLoader.getRemoteConfig())
} }
if (get().app.remoteConfig.personalUrl) { if (get().app.remoteConfig.personalUrl) {
defConfig = mergeApi.doMerge(defConfig, configApi.readRemoteConfig('_personal')) mergeApi.doMerge(defConfig, configLoader.getRemoteConfig('_personal'))
} }
} }
// 计算新配置与默认配置(启用远程配置时,含远程配置)的差异,并保存到 config.json 中 // 计算新配置与默认配置(启用远程配置时,含远程配置)的差异
const diffConfig = mergeApi.doDiff(defConfig, newConfig) const diffConfig = mergeApi.doDiff(defConfig, newConfig)
const configPath = _getConfigPath()
// 将差异作为用户配置保存到 config.json 中
const configPath = configLoader.getUserConfigPath()
fs.writeFileSync(configPath, jsonApi.stringify(diffConfig)) fs.writeFileSync(configPath, jsonApi.stringify(diffConfig))
log.info('保存 config.json 自定义配置文件成功:', configPath) log.info('保存 config.json 自定义配置文件成功:', configPath)
@ -219,25 +170,8 @@ const configApi = {
* 读取 config.json 合并配置 * 读取 config.json 合并配置
*/ */
reload () { reload () {
const configPath = _getConfigPath() const userConfig = configLoader.getUserConfig()
let userConfig return configApi.set(userConfig) || {}
if (!fs.existsSync(configPath)) {
userConfig = {}
log.info('config.json 文件不存在:', configPath)
} else {
const file = fs.readFileSync(configPath)
log.info('读取 config.json 成功:', configPath)
const fileStr = file.toString()
try {
userConfig = jsonApi.parse(fileStr)
} catch (e) {
log.error(`config.json 文件内容格式不正确,文件路径:${configPath},文件内容: ${fileStr}, error:`, e)
userConfig = {}
}
}
const config = configApi.set(userConfig)
return config || {}
}, },
update (partConfig) { update (partConfig) {
const newConfig = lodash.merge(configApi.get(), partConfig) const newConfig = lodash.merge(configApi.get(), partConfig)
@ -252,41 +186,11 @@ const configApi = {
return configApi.load(newConfig) return configApi.load(newConfig)
}, },
load (newConfig) { load (newConfig) {
// 以用户配置作为基准配置,是为了保证用户配置的顺序在前 const config = configLoader.getConfigFromFiles(newConfig, defConfig)
const merged = newConfig != null ? lodash.cloneDeep(newConfig) : {} configTarget = config
return config
if (get().app.remoteConfig.enabled === true) {
let personalRemoteConfig = null
let shareRemoteConfig = null
if (get().app.remoteConfig.personalUrl) {
personalRemoteConfig = configApi.readRemoteConfig('_personal')
mergeApi.doMerge(merged, personalRemoteConfig) // 先合并一次个人远程配置,使配置顺序在前
}
if (get().app.remoteConfig.url) {
shareRemoteConfig = configApi.readRemoteConfig()
mergeApi.doMerge(merged, shareRemoteConfig) // 先合并一次共享远程配置,使配置顺序在前
}
mergeApi.doMerge(merged, defConfig) // 合并默认配置,顺序排在最后
if (get().app.remoteConfig.url) {
mergeApi.doMerge(merged, shareRemoteConfig) // 再合并一次共享远程配置,使配置生效
}
if (get().app.remoteConfig.personalUrl) {
mergeApi.doMerge(merged, personalRemoteConfig) // 再合并一次个人远程配置,使配置生效
}
} else {
mergeApi.doMerge(merged, defConfig) // 合并默认配置
}
if (newConfig != null) {
mergeApi.doMerge(merged, newConfig) // 再合并一次用户配置,使用户配置重新生效
}
mergeApi.deleteNullItems(merged) // 删除为null及[delete]的项
configTarget = merged
log.info('加载及合并远程配置完成')
return configTarget
}, },
getDefault () { cloneDefault () {
return lodash.cloneDeep(defConfig) return lodash.cloneDeep(defConfig)
}, },
addDefault (key, defValue) { addDefault (key, defValue) {
@ -294,7 +198,7 @@ const configApi = {
}, },
// 移除用户配置,用于恢复出厂设置功能 // 移除用户配置,用于恢复出厂设置功能
async removeUserConfig () { async removeUserConfig () {
const configPath = _getConfigPath() const configPath = configLoader.getUserConfigPath()
if (fs.existsSync(configPath)) { if (fs.existsSync(configPath)) {
// 读取 config.json 文件内容 // 读取 config.json 文件内容
const fileOriginalStr = fs.readFileSync(configPath).toString() const fileOriginalStr = fs.readFileSync(configPath).toString()

View File

@ -1,20 +1,12 @@
const fs = require('node:fs')
const path = require('node:path') const path = require('node:path')
const lodash = require('lodash') const configLoader = require('./local-config-loader')
const jsonApi = require('@docmirror/mitmproxy/src/json')
const mergeApi = require('../merge')
function getUserBasePath () {
const userHome = process.env.USERPROFILE || process.env.HOME || '/'
return path.resolve(userHome, './.dev-sidecar')
}
function getRootCaCertPath () { function getRootCaCertPath () {
return path.join(getUserBasePath(), '/dev-sidecar.ca.crt') return path.join(configLoader.getUserBasePath(), '/dev-sidecar.ca.crt')
} }
function getRootCaKeyPath () { function getRootCaKeyPath () {
return path.join(getUserBasePath(), '/dev-sidecar.ca.key.pem') return path.join(configLoader.getUserBasePath(), '/dev-sidecar.ca.key.pem')
} }
const defaultConfig = { const defaultConfig = {
@ -43,7 +35,7 @@ const defaultConfig = {
showShutdownTip: true, showShutdownTip: true,
// 日志相关配置 // 日志相关配置
logFileSavePath: path.join(getUserBasePath(), '/logs'), // 日志文件保存路径 logFileSavePath: path.join(configLoader.getUserBasePath(), '/logs'), // 日志文件保存路径
keepLogFileCount: 15, // 保留日志文件数 keepLogFileCount: 15, // 保留日志文件数
}, },
server: { server: {
@ -57,7 +49,7 @@ const defaultConfig = {
enabled: true, enabled: true,
defaultDir: './extra/scripts/', defaultDir: './extra/scripts/',
}, },
userBasePath: getUserBasePath(), userBasePath: configLoader.getUserBasePath(),
rootCaFile: { rootCaFile: {
certPath: getRootCaCertPath(), certPath: getRootCaCertPath(),
keyPath: getRootCaKeyPath(), keyPath: getRootCaKeyPath(),
@ -447,126 +439,7 @@ const defaultConfig = {
}, },
} }
// region 加载本地配置文件所需的方法
function _getConfigPath () {
const dir = defaultConfig.server.setting.userBasePath
if (!fs.existsSync(dir)) {
return null
}
// 兼容1.7.3及以下版本的配置文件处理逻辑
const newFilePath = path.join(dir, '/config.json')
const oldFilePath = path.join(dir, '/config.json5')
if (!fs.existsSync(newFilePath)) {
if (fs.existsSync(oldFilePath)) {
return oldFilePath // 如果新文件不存在,且旧文件存在,则返回旧文件路径
} else {
return null // 两个文件都不存在
}
}
return newFilePath
}
function _getConfig () {
const configFilePath = _getConfigPath()
if (configFilePath == null) {
return {}
}
if (!fs.existsSync(configFilePath)) {
return {}
}
try {
return jsonApi.parse(fs.readFileSync(configFilePath))
} catch (e) {
console.error('读取配置文件失败:', configFilePath, e)
return {}
}
}
function _getRemoteSavePath (suffix = '') {
const dir = defaultConfig.server.setting.userBasePath
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir)
}
return path.join(dir, `/remote_config${suffix}.json5`)
}
function _readRemoteConfigStr (suffix = '') {
if (defaultConfig.app.remoteConfig.enabled !== true) {
if (suffix === '_personal') {
if (!defaultConfig.app.remoteConfig.personalUrl) {
return '{}'
}
} else if (suffix === '') {
if (!defaultConfig.app.remoteConfig.url) {
return '{}'
}
}
return '{}'
}
try {
const path = _getRemoteSavePath(suffix)
if (fs.existsSync(path)) {
const file = fs.readFileSync(path)
return file.toString()
}
} catch {
}
return '{}'
}
function _readRemoteConfig (suffix = '') {
try {
return jsonApi.parse(_readRemoteConfigStr(suffix))
} catch (e) {
console.error(`读取远程配置失败suffix: ${suffix}`, e)
return {}
}
}
function _getConfigFromFiles () {
const newConfig = _getConfig()
const merged = newConfig != null ? lodash.cloneDeep(newConfig) : {}
if (defaultConfig.app.remoteConfig.enabled === true) {
let personalRemoteConfig = null
let shareRemoteConfig = null
if (defaultConfig.app.remoteConfig.personalUrl) {
personalRemoteConfig = _readRemoteConfig('_personal')
mergeApi.doMerge(merged, personalRemoteConfig) // 先合并一次个人远程配置,使配置顺序在前
}
if (defaultConfig.app.remoteConfig.url) {
shareRemoteConfig = _readRemoteConfig()
mergeApi.doMerge(merged, shareRemoteConfig) // 先合并一次共享远程配置,使配置顺序在前
}
mergeApi.doMerge(merged, defaultConfig) // 合并默认配置,顺序排在最后
if (defaultConfig.app.remoteConfig.url) {
mergeApi.doMerge(merged, shareRemoteConfig) // 再合并一次共享远程配置,使配置生效
}
if (defaultConfig.app.remoteConfig.personalUrl) {
mergeApi.doMerge(merged, personalRemoteConfig) // 再合并一次个人远程配置,使配置生效
}
} else {
mergeApi.doMerge(merged, defaultConfig) // 合并默认配置
}
if (newConfig != null) {
mergeApi.doMerge(merged, newConfig) // 再合并一次用户配置,使用户配置重新生效
}
mergeApi.deleteNullItems(merged) // 删除为null及[delete]的项
return merged
}
// endregion
// 从本地文件中加载配置 // 从本地文件中加载配置
defaultConfig.configFromFiles = _getConfigFromFiles() defaultConfig.configFromFiles = configLoader.getConfigFromFiles(configLoader.getUserConfig(), defaultConfig)
module.exports = defaultConfig module.exports = defaultConfig

View File

@ -0,0 +1,138 @@
const fs = require('node:fs')
const path = require('node:path')
const lodash = require('lodash')
const jsonApi = require('@docmirror/mitmproxy/src/json')
const mergeApi = require('../merge')
let log = console // 默认使用console日志系统初始化完成后设置为 logger
function setLogger (logger) {
log = logger
jsonApi.setLogger(logger)
}
function getUserBasePath (autoCreate = true) {
const userHome = process.env.USERPROFILE || process.env.HOME || '/'
const dir = path.resolve(userHome, './.dev-sidecar')
// 自动创建目录
if (autoCreate && !fs.existsSync(dir)) {
fs.mkdirSync(dir)
}
return dir
}
function loadConfigFromFile (configFilePath) {
if (configFilePath == null) {
log.warn('配置文件地址为空')
return {}
}
if (!fs.existsSync(configFilePath)) {
log.info('配置文件不存在:', configFilePath)
return {} // 文件不存在,返回空配置
}
// 读取配置文件
let configStr
try {
configStr = fs.readFileSync(configFilePath)
} catch (e) {
log.error('读取配置文件失败:', configFilePath, ', error:', e)
return {}
}
// 解析配置文件
try {
const config = jsonApi.parse(configStr)
log.info('读取配置文件成功:', configFilePath)
return config
} catch (e) {
log.error(`解析配置文件失败,文件内容格式不正确,文件路径: ${configFilePath},文件内容:${configStr}error:`, e)
return {}
}
}
function getUserConfigPath () {
const dir = getUserBasePath()
// 兼容1.7.3及以下版本的配置文件处理逻辑
const newFilePath = path.join(dir, '/config.json')
const oldFilePath = path.join(dir, '/config.json5')
if (!fs.existsSync(newFilePath)) {
if (fs.existsSync(oldFilePath)) {
return oldFilePath // 如果新文件不存在,但旧文件存在,则返回旧文件路径
} else {
return null // 两个文件都不存在
}
}
return newFilePath
}
function getUserConfig () {
const configFilePath = getUserConfigPath()
return loadConfigFromFile(configFilePath)
}
function getRemoteConfigPath (suffix = '') {
const dir = getUserBasePath()
return path.join(dir, `/remote_config${suffix}.json5`)
}
function getRemoteConfig (suffix = '') {
const remoteConfigFilePath = getRemoteConfigPath(suffix)
return loadConfigFromFile(remoteConfigFilePath)
}
function getAutomaticCompatibleConfigPath () {
const dir = getUserBasePath()
return path.join(dir, '/automaticCompatibleConfig.json')
}
/**
* 从文件读取配置
*
* @param userConfig 用户配置
* @param defaultConfig 默认配置
*/
function getConfigFromFiles (userConfig, defaultConfig) {
const merged = userConfig != null ? lodash.cloneDeep(userConfig) : {}
const personalRemoteConfig = getRemoteConfig('_personal')
const shareRemoteConfig = getRemoteConfig()
mergeApi.doMerge(merged, personalRemoteConfig) // 先合并一次个人远程配置,使配置顺序在前
mergeApi.doMerge(merged, shareRemoteConfig) // 先合并一次共享远程配置,使配置顺序在前
mergeApi.doMerge(merged, defaultConfig) // 合并默认配置,顺序排在最后
mergeApi.doMerge(merged, shareRemoteConfig) // 再合并一次共享远程配置,使配置生效
mergeApi.doMerge(merged, personalRemoteConfig) // 再合并一次个人远程配置,使配置生效
if (userConfig != null) {
mergeApi.doMerge(merged, userConfig) // 再合并一次用户配置,使用户配置重新生效
}
// 删除为null及[delete]的项
mergeApi.deleteNullItems(merged)
log.info('加载及合并远程配置完成')
return merged
}
module.exports = {
setLogger,
getUserBasePath,
loadConfigFromFile,
getUserConfigPath,
getUserConfig,
getRemoteConfigPath,
getRemoteConfig,
getAutomaticCompatibleConfigPath,
getConfigFromFiles,
}

View File

@ -160,6 +160,7 @@ function getProxyExcludeIpStr (split) {
} }
// 排除国内域名 // 排除国内域名
// log.debug('系统代理排除域名excludeIpStr:', excludeIpStr)
if (config.get().proxy.excludeDomesticDomainAllowList) { if (config.get().proxy.excludeDomesticDomainAllowList) {
try { try {
let domesticDomainAllowList = getDomesticDomainAllowList() let domesticDomainAllowList = getDomesticDomainAllowList()
@ -177,8 +178,6 @@ function getProxyExcludeIpStr (split) {
} }
} }
log.debug('系统代理排除域名excludeIpStr:', excludeIpStr)
return excludeIpStr return excludeIpStr
} }

View File

@ -1,5 +1,6 @@
const path = require('node:path') const path = require('node:path')
const log4js = require('log4js') const log4js = require('log4js')
const configLoader = require('../config/local-config-loader')
const configFromFiles = require('../config/index').configFromFiles const configFromFiles = require('../config/index').configFromFiles
// 日志级别 // 日志级别
@ -52,6 +53,7 @@ function log4jsConfigure (categories) {
// 拿第一个日志类型来logger并设置到log变量中 // 拿第一个日志类型来logger并设置到log变量中
log = log4js.getLogger(categories[0]) log = log4js.getLogger(categories[0])
configLoader.setLogger(log)
log.info('设置日志配置完成:', config) log.info('设置日志配置完成:', config)
} }

View File

@ -1,18 +1,26 @@
let JSON5 = require('json5') let JSON5 = require('json5')
if (JSON5.default) { if (JSON5.default) {
JSON5 = JSON5.default JSON5 = JSON5.default
} }
let log = console // 默认使用console日志系统初始化完成后设置为 logger
function setLogger (logger) {
log = logger
}
module.exports = { module.exports = {
parse (str, defaultValue) { parse (str, defaultValue) {
if (str == null || str.length < 2) { if (str == null || str.length < 2) {
return defaultValue || {} return defaultValue || {}
} }
str = str.toString()
if (defaultValue != null) { if (defaultValue != null) {
try { try {
return JSON5.parse(str) return JSON5.parse(str)
} catch { } catch (e) {
log.error(`JSON5解析失败: ${e.message}JSON内容:\r\n`, str)
return defaultValue return defaultValue
} }
} else { } else {
@ -35,4 +43,6 @@ module.exports = {
} }
} }
}, },
setLogger,
} }

View File

@ -6,10 +6,10 @@
* @author WangLiang * @author WangLiang
*/ */
const fs = require('node:fs') const fs = require('node:fs')
const path = require('node:path')
const jsonApi = require('../../../json') const jsonApi = require('../../../json')
const log = require('../../../utils/util.log') const log = require('../../../utils/util.log')
const matchUtil = require('../../../utils/util.match') const matchUtil = require('../../../utils/util.match')
const configLoader = require('@docmirror/dev-sidecar/src/config/local-config-loader')
const defaultConfig = { const defaultConfig = {
// connect阶段所需的兼容性配置 // connect阶段所需的兼容性配置
@ -43,17 +43,8 @@ function _getRequestConfig (hostname, port) {
// region 本地配置文件所需函数 // region 本地配置文件所需函数
function _getConfigPath () {
const userHome = process.env.USERPROFILE || process.env.HOME || '/'
const dir = path.resolve(userHome, './.dev-sidecar')
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir)
}
return path.join(dir, '/automaticCompatibleConfig.json')
}
function _loadFromFile (defaultConfig) { function _loadFromFile (defaultConfig) {
const configPath = _getConfigPath() const configPath = configLoader.getAutomaticCompatibleConfigPath()
let config let config
if (!fs.existsSync(configPath)) { if (!fs.existsSync(configPath)) {
config = defaultConfig config = defaultConfig
@ -80,7 +71,7 @@ function _loadFromFile (defaultConfig) {
} }
function _saveConfigToFile () { function _saveConfigToFile () {
const filePath = _getConfigPath() const filePath = configLoader.getAutomaticCompatibleConfigPath()
try { try {
fs.writeFileSync(filePath, jsonApi.stringify(config)) fs.writeFileSync(filePath, jsonApi.stringify(config))
log.info('保存 automaticCompatibleConfig.json 成功:', filePath) log.info('保存 automaticCompatibleConfig.json 成功:', filePath)