import * as fs from 'fs'; import ConfigFileMissingError from '../errors/config_file_missing.error'; import ConfigProfileError from '../errors/config_profile_missing.error'; import ConfigFileFormatError from '../errors/config_file_format.error'; import Config004 from './config.0.0.4'; const HOME = require('os').homedir(); const CONFIG_FILE_NAME = '.telmeconfig'; const FILEPATH = `${HOME}/${CONFIG_FILE_NAME}`; let singleton = null; export enum EConfigVersions { V004 = '0.0.4', V010 = '0.1.0' } const CURRENT_CONFIG_VERSION = EConfigVersions.V010; export default class Config { static APP_NAME = 'telme'; static CURRENT_CONFIG_VERSION = CURRENT_CONFIG_VERSION; static DEFAULT_TASK_MESSAGE_TEMPLATE = '*Task:*\n\n```sh\n%cmd%\n```\nHas finished.\n*Errors*:\n %errors%'; private config: IConfig; static cliInit() { singleton = new Config(); } constructor() { const file = this.readConfigFile(); const parsed = this.parseConfig(file); if (parsed.originalConfigVersion != CURRENT_CONFIG_VERSION) { this.writeConfigToFile(parsed.config); } this.config = parsed.config; } static getConfig(profile: string = 'default'): ITaskConfig { return singleton.getConfig(profile); } static generateProfileTemplate(): ITaskConfig { return { chat_id: null, task_message_template: Config.DEFAULT_TASK_MESSAGE_TEMPLATE, bot_token: null } } static getFullConfig(): IConfig { return singleton.config; } static async writeConfigToFile(config: IConfig) { return singleton.writeConfigToFile(config); } private getConfig(profile: string): ITaskConfig { if (!this.config.profiles[profile]) { throw new ConfigProfileError(`No profile named ${profile} found.`); } return this.config.profiles[profile]; } private readConfigFile(): Buffer { try { const file = fs.readFileSync(FILEPATH); return file; } catch (e) { return Buffer.from(JSON.stringify(EMPTY_CONFIG)); } } private parseConfig(file: Buffer): { config: IConfig, originalConfigVersion: EConfigVersions } { try { const config = JSON.parse(file.toString()); const confVersion: EConfigVersions = config.version || EConfigVersions.V004; switch (confVersion) { case EConfigVersions.V004: return { config: Config004.parse(config), originalConfigVersion: EConfigVersions.V004 }; // Using switch to easily add more config version. If needed... default: return { config, originalConfigVersion: config.version }; } } catch (e) { throw new ConfigFileFormatError('Invalid JSON format in config file. If you modified the file yourself, please double check your modifications'); } } private writeConfigToFile(config: IConfig): boolean { try { fs.writeFileSync(FILEPATH, JSON.stringify(config, null, 2)); console.log(`✅ created config file at ${FILEPATH}`); return true; } catch (e) { return false; } } } const EMPTY_CONFIG: IConfig = { version: CURRENT_CONFIG_VERSION, profiles: {} } export interface IMessageConfig { chat_id: string; bot_token: string; } export interface ITaskConfig extends IMessageConfig { task_message_template: string; } export interface IConfig { version: EConfigVersions, profiles: { [key: string]: ITaskConfig; } }