mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-02-27 18:22:41 -08:00
117 lines
3.4 KiB
TypeScript
117 lines
3.4 KiB
TypeScript
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
import { ConfigValidationWarning, RawConfig, ResolvedConfig } from '../types';
|
|
import { DEFAULT_CONFIG, deepCloneConfig, deepMergeRawConfig } from './definitions';
|
|
import { ConfigPaths, loadRawConfig, loadRawConfigStrict } from './load';
|
|
import { resolveConfig } from './resolve';
|
|
|
|
export type ReloadConfigStrictResult =
|
|
| {
|
|
ok: true;
|
|
config: ResolvedConfig;
|
|
warnings: ConfigValidationWarning[];
|
|
path: string;
|
|
}
|
|
| {
|
|
ok: false;
|
|
error: string;
|
|
path: string;
|
|
};
|
|
|
|
export class ConfigStartupParseError extends Error {
|
|
readonly path: string;
|
|
readonly parseError: string;
|
|
|
|
constructor(configPath: string, parseError: string) {
|
|
super(
|
|
`Failed to parse startup config at ${configPath}: ${parseError}. Fix the config file and restart SubMiner.`,
|
|
);
|
|
this.name = 'ConfigStartupParseError';
|
|
this.path = configPath;
|
|
this.parseError = parseError;
|
|
}
|
|
}
|
|
|
|
export class ConfigService {
|
|
private readonly configPaths: ConfigPaths;
|
|
private rawConfig: RawConfig = {};
|
|
private resolvedConfig: ResolvedConfig = deepCloneConfig(DEFAULT_CONFIG);
|
|
private warnings: ConfigValidationWarning[] = [];
|
|
private configPathInUse!: string;
|
|
|
|
constructor(configDir: string) {
|
|
this.configPaths = {
|
|
configDir,
|
|
configFileJsonc: path.join(configDir, 'config.jsonc'),
|
|
configFileJson: path.join(configDir, 'config.json'),
|
|
};
|
|
const loadResult = loadRawConfigStrict(this.configPaths);
|
|
if (!loadResult.ok) {
|
|
throw new ConfigStartupParseError(loadResult.path, loadResult.error);
|
|
}
|
|
this.applyResolvedConfig(loadResult.config, loadResult.path);
|
|
}
|
|
|
|
getConfigPath(): string {
|
|
return this.configPathInUse;
|
|
}
|
|
|
|
getConfig(): ResolvedConfig {
|
|
return deepCloneConfig(this.resolvedConfig);
|
|
}
|
|
|
|
getRawConfig(): RawConfig {
|
|
return JSON.parse(JSON.stringify(this.rawConfig)) as RawConfig;
|
|
}
|
|
|
|
getWarnings(): ConfigValidationWarning[] {
|
|
return [...this.warnings];
|
|
}
|
|
|
|
reloadConfig(): ResolvedConfig {
|
|
const { config, path: configPath } = loadRawConfig(this.configPaths);
|
|
return this.applyResolvedConfig(config, configPath);
|
|
}
|
|
|
|
reloadConfigStrict(): ReloadConfigStrictResult {
|
|
const loadResult = loadRawConfigStrict(this.configPaths);
|
|
if (!loadResult.ok) {
|
|
return loadResult;
|
|
}
|
|
|
|
const { config, path: configPath } = loadResult;
|
|
const resolvedConfig = this.applyResolvedConfig(config, configPath);
|
|
return {
|
|
ok: true,
|
|
config: resolvedConfig,
|
|
warnings: this.getWarnings(),
|
|
path: configPath,
|
|
};
|
|
}
|
|
|
|
saveRawConfig(config: RawConfig): void {
|
|
if (!fs.existsSync(this.configPaths.configDir)) {
|
|
fs.mkdirSync(this.configPaths.configDir, { recursive: true });
|
|
}
|
|
const targetPath = this.configPathInUse.endsWith('.json')
|
|
? this.configPathInUse
|
|
: this.configPaths.configFileJsonc;
|
|
fs.writeFileSync(targetPath, JSON.stringify(config, null, 2));
|
|
this.applyResolvedConfig(config, targetPath);
|
|
}
|
|
|
|
patchRawConfig(patch: RawConfig): void {
|
|
const merged = deepMergeRawConfig(this.getRawConfig(), patch);
|
|
this.saveRawConfig(merged);
|
|
}
|
|
|
|
private applyResolvedConfig(config: RawConfig, configPath: string): ResolvedConfig {
|
|
this.rawConfig = config;
|
|
this.configPathInUse = configPath;
|
|
const { resolved, warnings } = resolveConfig(config);
|
|
this.resolvedConfig = resolved;
|
|
this.warnings = warnings;
|
|
return this.getConfig();
|
|
}
|
|
}
|