UNPKG

@henteko/kumiki

Version:

A video generation tool that creates videos from JSON configurations

113 lines 3.6 kB
import fs from 'node:fs/promises'; import os from 'node:os'; import path from 'node:path'; import { z } from 'zod'; import { logger } from '../utils/logger.js'; const ConfigSchema = z.object({ gemini: z.object({ apiKey: z.string().optional(), }).optional(), }); export class ConfigManager { static configDir = path.join(os.homedir(), '.kumiki'); static configFile = path.join(ConfigManager.configDir, 'config.json'); static async ensureConfigDir() { try { await fs.mkdir(this.configDir, { recursive: true }); } catch (error) { logger.error('Failed to create config directory', { error }); throw error; } } static async load() { try { await this.ensureConfigDir(); const data = await fs.readFile(this.configFile, 'utf-8'); const config = JSON.parse(data); return ConfigSchema.parse(config); } catch (error) { // If file doesn't exist or is invalid, return empty config if (error instanceof Error && 'code' in error && error.code === 'ENOENT') { return {}; } logger.warning('Failed to load config, using defaults'); return {}; } } static async save(config) { try { await this.ensureConfigDir(); const validated = ConfigSchema.parse(config); await fs.writeFile(this.configFile, JSON.stringify(validated, null, 2), 'utf-8'); } catch (error) { logger.error('Failed to save config', { error }); throw error; } } static async get(key) { const config = await this.load(); const keys = key.split('.'); let value = config; for (const k of keys) { if (value && typeof value === 'object' && k in value) { value = value[k]; } else { return undefined; } } return typeof value === 'string' ? value : undefined; } static async set(key, value) { const config = await this.load(); const keys = key.split('.'); let target = config; // Navigate to the parent object, creating nested objects as needed for (let i = 0; i < keys.length - 1; i++) { const k = keys[i]; if (!k) continue; if (!target[k] || typeof target[k] !== 'object') { target[k] = {}; } target = target[k]; } // Set the final value const lastKey = keys[keys.length - 1]; if (lastKey) { target[lastKey] = value; } await this.save(config); } static async unset(key) { const config = await this.load(); const keys = key.split('.'); let target = config; // Navigate to the parent object for (let i = 0; i < keys.length - 1; i++) { const k = keys[i]; if (!k) return; if (!target[k] || typeof target[k] !== 'object') { return; // Key doesn't exist } target = target[k]; } // Delete the final key const lastKey = keys[keys.length - 1]; if (lastKey) { delete target[lastKey]; } await this.save(config); } static async list() { return this.load(); } static getConfigPath() { return this.configFile; } } //# sourceMappingURL=config.js.map