import fs from 'fs/promises' import path from 'path' import { app } from 'electron' const USER_DATA_STRING = '__DEFAULT_USER_DATA__' export default class Config { constructor(defaultPlugin) { this.defaultPlugin = defaultPlugin this.configPath = path.join(app.getPath('userData'), 'config.json') } // Helper to replace placeholders with dynamic values _resolveDefaults(config) { if (Array.isArray(config)) { return config.map((item) => this._resolveDefaults(item)) } else if (config && typeof config === 'object') { const resolved = {} for (const [key, value] of Object.entries(config)) { resolved[key] = this._resolveDefaults(value) } return resolved } else if ( typeof config === 'string' && config.includes(USER_DATA_STRING) ) { return config.replace(USER_DATA_STRING, app.getPath('userData')) } else { return config } } async load() { let parsed try { const raw = await fs.readFile(this.configPath, 'utf8') parsed = JSON.parse(raw) } catch (err) { parsed = null } if (!parsed || !parsed.activeAdapter) { const defaultConfig = {} for (const field of this.defaultPlugin.configSchema) { defaultConfig[field.key] = field.default ?? null } parsed = { ...(parsed ? parsed : {}), activeAdapter: this.defaultPlugin.id, adapters: {}, } parsed.adapters[this.defaultPlugin.id] = defaultConfig parsed[theme] = 'dark' await this.write(parsed) } else { // Ensure any "__DEFAULT_USER_DATA__" values are resolved on load parsed.adapters = this._resolveDefaults(parsed.adapters) } return parsed } async write(configObject) { const dir = path.dirname(this.configPath) // Ensure directory exists await fs.mkdir(dir, { recursive: true }) // Resolve defaults before writing const resolvedConfig = { ...configObject, adapters: this._resolveDefaults(configObject.adapters), } await fs.writeFile( this.configPath, JSON.stringify(resolvedConfig, null, 2), 'utf8', ) } }