From d9b9977fe903d3792568ef4e1e8a90f88555585d Mon Sep 17 00:00:00 2001 From: pompurin404 Date: Sat, 17 Aug 2024 15:02:54 +0800 Subject: [PATCH] use deep merge --- src/main/config/app.ts | 8 ++------ src/main/config/controledMihomo.ts | 22 ++++------------------ src/main/core/factory.ts | 28 ++++------------------------ src/main/utils/dirs.ts | 4 ++-- src/main/utils/merge.ts | 16 ++++++++++++++++ 5 files changed, 28 insertions(+), 50 deletions(-) create mode 100644 src/main/utils/merge.ts diff --git a/src/main/config/app.ts b/src/main/config/app.ts index 14955ac..fd40801 100644 --- a/src/main/config/app.ts +++ b/src/main/config/app.ts @@ -1,6 +1,7 @@ import { readFile, writeFile } from 'fs/promises' import { appConfigPath } from '../utils/dirs' import yaml from 'yaml' +import { deepMerge } from '../utils/merge' let appConfig: IAppConfig // config.yaml @@ -13,11 +14,6 @@ export async function getAppConfig(force = false): Promise { } export async function patchAppConfig(patch: Partial): Promise { - if (patch.sysProxy) { - const oldSysProxy = appConfig.sysProxy || {} - const newSysProxy = Object.assign(oldSysProxy, patch.sysProxy) - patch.sysProxy = newSysProxy - } - appConfig = Object.assign(appConfig, patch) + appConfig = deepMerge(appConfig, patch) await writeFile(appConfigPath(), yaml.stringify(appConfig)) } diff --git a/src/main/config/controledMihomo.ts b/src/main/config/controledMihomo.ts index c26c516..f95d825 100644 --- a/src/main/config/controledMihomo.ts +++ b/src/main/config/controledMihomo.ts @@ -5,6 +5,7 @@ import { getAxios, startMihomoMemory, startMihomoTraffic } from '../core/mihomoA import { generateProfile } from '../core/factory' import { getAppConfig } from './app' import { defaultControledMihomoConfig } from '../utils/template' +import { deepMerge } from '../utils/merge' let controledMihomoConfig: Partial // mihomo.yaml @@ -18,11 +19,6 @@ export async function getControledMihomoConfig(force = false): Promise): Promise { const { useNameserverPolicy, controlDns = true, controlSniff = true } = await getAppConfig() - if (patch.tun) { - const oldTun = controledMihomoConfig.tun || {} - const newTun = Object.assign(oldTun, patch.tun) - patch.tun = newTun - } if (!controlDns) { delete controledMihomoConfig.dns delete controledMihomoConfig.hosts @@ -32,14 +28,6 @@ export async function patchControledMihomoConfig(patch: Partial): controledMihomoConfig.dns = defaultControledMihomoConfig.dns } } - if (patch.dns) { - const oldDns = controledMihomoConfig.dns || {} - const newDns = Object.assign(oldDns, patch.dns) - if (!useNameserverPolicy) { - delete newDns['nameserver-policy'] - } - patch.dns = newDns - } if (!controlSniff) { delete controledMihomoConfig.sniffer } else { @@ -48,12 +36,10 @@ export async function patchControledMihomoConfig(patch: Partial): controledMihomoConfig.sniffer = defaultControledMihomoConfig.sniffer } } - if (patch.sniffer) { - const oldSniffer = controledMihomoConfig.sniffer || {} - const newSniffer = Object.assign(oldSniffer, patch.sniffer) - patch.sniffer = newSniffer + controledMihomoConfig = deepMerge(controledMihomoConfig, patch) + if (!useNameserverPolicy) { + delete controledMihomoConfig?.dns?.['nameserver-policy'] } - controledMihomoConfig = Object.assign(controledMihomoConfig, patch) if (patch['external-controller'] || patch.secret) { await getAxios(true) diff --git a/src/main/core/factory.ts b/src/main/core/factory.ts index 8c3e79a..518ad35 100644 --- a/src/main/core/factory.ts +++ b/src/main/core/factory.ts @@ -7,35 +7,15 @@ import { } from '../config' import { mihomoWorkConfigPath } from '../utils/dirs' import yaml from 'yaml' -import fs from 'fs' -import { readFile } from 'fs/promises' +import { readFile, writeFile } from 'fs/promises' +import { deepMerge } from '../utils/merge' export async function generateProfile(): Promise { const { current } = await getProfileConfig() const currentProfile = await overrideProfile(current, await getProfile(current)) const controledMihomoConfig = await getControledMihomoConfig() - const { tun: profileTun = {} } = currentProfile - const { tun: controledTun } = controledMihomoConfig - const tun = Object.assign(profileTun, controledTun) - const { dns: profileDns = {} } = currentProfile - const { dns: controledDns } = controledMihomoConfig - const dns = Object.assign(profileDns, controledDns) - const { sniffer: profileSniffer = {} } = currentProfile - const { sniffer: controledSniffer } = controledMihomoConfig - const sniffer = Object.assign(profileSniffer, controledSniffer) - const profile = Object.assign(currentProfile, controledMihomoConfig) - profile.tun = tun - profile.dns = dns - profile.sniffer = sniffer - return new Promise((resolve, reject) => { - fs.writeFile(mihomoWorkConfigPath(), yaml.stringify(profile), (err) => { - if (err) { - reject(err) - } else { - resolve() - } - }) - }) + const profile = deepMerge(currentProfile, controledMihomoConfig) + await writeFile(mihomoWorkConfigPath(), yaml.stringify(profile)) } async function overrideProfile( diff --git a/src/main/utils/dirs.ts b/src/main/utils/dirs.ts index a08a2f3..6413367 100644 --- a/src/main/utils/dirs.ts +++ b/src/main/utils/dirs.ts @@ -1,13 +1,13 @@ import { is } from '@electron-toolkit/utils' import { app } from 'electron' -import fs from 'fs' +import { existsSync } from 'fs' import { rm, writeFile } from 'fs/promises' import path from 'path' export const homeDir = app.getPath('home') export function isPortable(): boolean { - return fs.existsSync(path.join(exeDir(), 'PORTABLE')) + return existsSync(path.join(exeDir(), 'PORTABLE')) } export async function setPortable(portable: boolean): Promise { diff --git a/src/main/utils/merge.ts b/src/main/utils/merge.ts new file mode 100644 index 0000000..262fd58 --- /dev/null +++ b/src/main/utils/merge.ts @@ -0,0 +1,16 @@ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function isObject(item: any): boolean { + return item && typeof item === 'object' && !Array.isArray(item) +} + +export function deepMerge(target: T, other: Partial): T { + for (const key in other) { + if (isObject(other[key])) { + if (!target[key]) Object.assign(target, { [key]: {} }) + deepMerge(target[key] as object, other[key] as object) + } else { + Object.assign(target, { [key]: other[key] }) + } + } + return target as T +}