fix(api): load dynamix config in the same way as the webgui

merge defaults + custom config

see original php implementation in the webgui:
[link](95c6913c62/emhttp/plugins/dynamix/include/Wrappers.php (L42))
This commit is contained in:
Pujit Mehrotra
2024-10-18 10:00:44 -04:00
parent 38524bce88
commit 5f4cc07473
2 changed files with 56 additions and 19 deletions

View File

@@ -1,11 +1,30 @@
import { parseConfig } from '@app/core/utils/misc/parse-config';
import {
createAsyncThunk,
} from '@reduxjs/toolkit';
import { createAsyncThunk } from '@reduxjs/toolkit';
import { access } from 'fs/promises';
import { F_OK } from 'constants';
import { type RecursivePartial, type RecursiveNullable } from '@app/types';
import { type DynamixConfig } from '@app/core/types/ini';
import { batchProcess } from '@app/utils';
/**
* Loads a configuration file from disk, parses it to a RecursivePartial of the provided type, and returns it.
*
* If the file is inaccessible, an empty object is returned instead.
*
* @param path The path to the configuration file on disk.
* @returns A parsed RecursivePartial of the provided type.
*/
async function loadConfigFile<ConfigType>(path: string): Promise<RecursivePartial<ConfigType>> {
const fileIsAccessible = await access(path, F_OK)
.then(() => true)
.catch(() => false);
return fileIsAccessible
? parseConfig<RecursivePartial<ConfigType>>({
filePath: path,
type: 'ini',
})
: {};
}
/**
* Load the dynamix.cfg into the store.
@@ -16,18 +35,12 @@ export const loadDynamixConfigFile = createAsyncThunk<
RecursiveNullable<RecursivePartial<DynamixConfig>>,
string | undefined
>('config/load-dynamix-config-file', async (filePath) => {
if (filePath) {
return loadConfigFile<DynamixConfig>(filePath);
}
const store = await import('@app/store');
const paths = store.getters.paths();
const path = filePath ?? paths['dynamix-config'];
const fileExists = await access(path, F_OK)
.then(() => true)
.catch(() => false);
const file: RecursivePartial<DynamixConfig> = fileExists
? parseConfig<RecursivePartial<DynamixConfig>>({
filePath: path,
type: 'ini',
})
: {};
return file;
const paths = store.getters.paths()['dynamix-config'];
const { data: configs } = await batchProcess(paths, (path) => loadConfigFile<DynamixConfig>(path));
const [defaultConfig = {}, customConfig = {}] = configs;
return { ...defaultConfig, ...customConfig };
});

View File

@@ -16,9 +16,33 @@ const initialState = {
'dynamix-base': resolvePath(
process.env.PATHS_DYNAMIX_BASE ?? ('/boot/config/plugins/dynamix/' as const)
),
'dynamix-config': resolvePath(
process.env.PATHS_DYNAMIX_CONFIG ?? ('/boot/config/plugins/dynamix/dynamix.cfg' as const)
),
/**------------------------------------------------------------------------
* Resolving Plugin Configs
*
* Plugins have a default config and, optionally, a user-customized config.
* You have to merge them to resolve a the correct config.
*
* i.e. the plugin author can update or change defaults without breaking user configs
*
* Thus, we've described this plugin's config paths as a list. The order matters!
* Config data in earlier paths will be overwritten by configs from later paths.
*
* See [the original PHP implementation.](https://github.com/unraid/webgui/blob/95c6913c62e64314b985e08222feb3543113b2ec/emhttp/plugins/dynamix/include/Wrappers.php#L42)
*
* Here, the first path in the list is the default config.
* The second is the user-customized config.
*
*------------------------------------------------------------------------**/
'dynamix-config': [
resolvePath(
process.env.PATHS_DYNAMIX_CONFIG_DEFAULT ??
('/usr/local/emhttp/plugins/dynamix/default.cfg' as const)
),
resolvePath(
process.env.PATHS_DYNAMIX_CONFIG ?? ('/boot/config/plugins/dynamix/dynamix.cfg' as const)
),
],
'myservers-base': '/boot/config/plugins/dynamix.my.servers/' as const,
'myservers-config': resolvePath(
process.env.PATHS_MY_SERVERS_CONFIG ??