diff --git a/src/config/index.ts b/src/config/index.ts index 225efc6a..fb081f2b 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -1,17 +1,20 @@ import Store from 'electron-store'; +import { deepmerge as createDeepmerge } from '@fastify/deepmerge'; + import defaultConfig from './defaults'; import plugins from './plugins'; import store from './store'; import { restart } from '../providers/app-controls'; +const deepmerge = createDeepmerge(); const set = (key: string, value: unknown) => { store.set(key, value); }; -const setPartial = (value: object) => { - // deepmerge(store.get, value); +const setPartial = (key: string, value: object) => { + deepmerge(store.get(key), value); store.set(value); }; diff --git a/src/index.ts b/src/index.ts index e27ed203..ff99b5cf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -101,11 +101,7 @@ ipcMain.handle('get-main-plugin-names', () => Object.keys(mainPlugins)); const initHook = (win: BrowserWindow) => { ipcMain.handle('get-config', (_, id: keyof PluginBuilderList) => config.get(`plugins.${id}` as never) ?? pluginBuilders[id].config); - ipcMain.handle('set-config', (_, name: string, obj: object) => config.setPartial({ - plugins: { - [name]: obj, - } - })); + ipcMain.handle('set-config', (_, name: string, obj: object) => config.setPartial(`plugins.${name}`, obj)); config.watch((newValue) => { const value = newValue as Record; @@ -144,30 +140,18 @@ async function loadPlugins(win: BrowserWindow) { } }); - + const createContext = < Key extends keyof PluginBuilderList, Config extends PluginBaseConfig = PluginBuilderList[Key]['config'], >(name: Key): MainPluginContext => ({ - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error getConfig: () => config.get(`plugins.${name}`) as unknown as Config, setConfig: (newConfig) => { - config.setPartial({ - plugins: { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - [name]: { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - ...config.get(`plugins.${name}`), - ...newConfig, - }, - }, - }); + config.setPartial(`plugins.${name}`, newConfig); return Promise.resolve(); }, - + send: (event: string, ...args: unknown[]) => { win.webContents.send(event, ...args); }, @@ -175,7 +159,7 @@ async function loadPlugins(win: BrowserWindow) { ipcMain.handle(event, async (_, ...args) => listener(...args as never)); }, }); - + for (const [pluginId, options] of config.plugins.getEnabled()) { const builder = pluginBuilders[pluginId as keyof PluginBuilderList]; diff --git a/src/menu.ts b/src/menu.ts index 9d210f3d..d8199246 100644 --- a/src/menu.ts +++ b/src/menu.ts @@ -13,7 +13,7 @@ import { pluginBuilders } from 'virtual:PluginBuilders'; /* eslint-enable import/order */ import { getAvailablePluginNames } from './plugins/utils/main'; -import { MenuPluginContext, MenuPluginFactory, PluginBaseConfig, PluginContext } from './plugins/utils/builder'; +import { MenuPluginContext, MenuPluginFactory, PluginBaseConfig } from './plugins/utils/builder'; export type MenuTemplate = Electron.MenuItemConstructorOptions[]; @@ -48,22 +48,13 @@ export const refreshMenu = (win: BrowserWindow) => { export const mainMenuTemplate = async (win: BrowserWindow): Promise => { const innerRefreshMenu = () => refreshMenu(win); - const createContext = (name: string): MenuPluginContext => ({ - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error + const createContext = < + Key extends keyof PluginBuilderList, + Config extends PluginBaseConfig = PluginBuilderList[Key]['config'], + >(name: Key): MenuPluginContext => ({ getConfig: () => config.get(`plugins.${name}`) as unknown as Config, setConfig: (newConfig) => { - config.setPartial({ - plugins: { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - [name]: { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - ...config.get(`plugins.${name}`), - ...newConfig, - }, - }, - }); + config.setPartial(`plugins.${name}`, newConfig); return Promise.resolve(); }, @@ -83,7 +74,7 @@ export const mainMenuTemplate = async (win: BrowserWindow): Promise; - const template = await factory(createContext(id)); + const template = await factory(createContext(id as never)); return { label: pluginLabel, diff --git a/src/plugins/utils/builder.ts b/src/plugins/utils/builder.ts index c4d8ec6a..9416fe64 100644 --- a/src/plugins/utils/builder.ts +++ b/src/plugins/utils/builder.ts @@ -23,8 +23,8 @@ type IF = (args: T) => T; type Promisable = T | Promise; export type PluginContext = { - getConfig: () => Promise; - setConfig: (config: DeepPartial) => Promise; + getConfig: () => Promisable; + setConfig: (config: DeepPartial) => Promisable; }; export type MainPluginContext = PluginContext & { diff --git a/src/renderer.ts b/src/renderer.ts index d8aed8ad..dcb326a0 100644 --- a/src/renderer.ts +++ b/src/renderer.ts @@ -144,10 +144,11 @@ const createContext = < const rendererPluginResult = await Promise.allSettled( enabledPluginNameAndOptions.map(async ([id]) => { + // HACK: eslint has a bug detects the type of rendererPlugins as "any" const builder = (rendererPlugins as Record>)[id]; - const context = createContext(id as never); - return [id, await builder(context as never)] as const; + const context = createContext(id as keyof PluginBuilderList); + return [id, await builder(context)] as const; }), ); @@ -172,12 +173,12 @@ const createContext = < console.trace(error); } }); - - window.ipcRenderer.on('config-changed', (_event, id: string, newConfig) => { + + window.ipcRenderer.on('config-changed', (_event, id: string, newConfig: PluginBaseConfig) => { const plugin = rendererPluginList.find(([pluginId]) => pluginId === id); if (plugin) { - plugin[1].onConfigChange?.(newConfig as never); + plugin[1].onConfigChange?.(newConfig); } });