UNPKG

@elsikora/setup-wizard

Version:

Setup Wizard - CLI scaffolding utility

209 lines (206 loc) 7.55 kB
#!/usr/bin/env node import { cosmiconfig } from 'cosmiconfig'; import { stringify } from 'javascript-stringify'; import yaml from 'yaml'; import { CONFIG_FILE_DIRECTORY } from '../../application/constant/config-file-directory.constant.js'; import { CONFIG_MODULE_NAME } from '../../application/constant/config-module-name.constant.js'; /** * Implementation of ConfigService that uses cosmiconfig for configuration management. * Cosmiconfig searches for configuration in standard locations and formats. */ class CosmicConfigService { /** File system service for file operations */ FILE_SYSTEM_SERVICE; cachedConfig = null; EXPLORER; /** * Initializes a new instance of the CosmicConfigService. * @param fileSystemService */ constructor(fileSystemService) { this.FILE_SYSTEM_SERVICE = fileSystemService; this.EXPLORER = cosmiconfig(CONFIG_MODULE_NAME, { packageProp: `${CONFIG_FILE_DIRECTORY.replace(".", "")}.${CONFIG_MODULE_NAME}`, searchPlaces: [ "package.json", `${CONFIG_FILE_DIRECTORY}/.${CONFIG_MODULE_NAME}rc`, `${CONFIG_FILE_DIRECTORY}/.${CONFIG_MODULE_NAME}rc.json`, `${CONFIG_FILE_DIRECTORY}/.${CONFIG_MODULE_NAME}rc.yaml`, `${CONFIG_FILE_DIRECTORY}/.${CONFIG_MODULE_NAME}rc.yml`, `${CONFIG_FILE_DIRECTORY}/.${CONFIG_MODULE_NAME}rc.js`, `${CONFIG_FILE_DIRECTORY}/.${CONFIG_MODULE_NAME}rc.ts`, `${CONFIG_FILE_DIRECTORY}/.${CONFIG_MODULE_NAME}rc.mjs`, `${CONFIG_FILE_DIRECTORY}/.${CONFIG_MODULE_NAME}rc.cjs`, `${CONFIG_FILE_DIRECTORY}/${CONFIG_MODULE_NAME}.config.js`, `${CONFIG_FILE_DIRECTORY}/${CONFIG_MODULE_NAME}.config.ts`, `${CONFIG_FILE_DIRECTORY}/${CONFIG_MODULE_NAME}.config.mjs`, `${CONFIG_FILE_DIRECTORY}/${CONFIG_MODULE_NAME}.config.cjs`, ], }); } /** * Clears all caches. */ clearCaches() { this.cachedConfig = null; this.EXPLORER.clearCaches(); } /** * Checks if the configuration exists. * @returns Promise resolving to true if the configuration exists, false otherwise */ async exists() { const result = await this.EXPLORER.search(); return result !== null && !result.isEmpty; } /** * Retrieves the current configuration. * @returns Promise resolving to the configuration object */ async get() { if (this.cachedConfig) { return this.cachedConfig; } const result = await this.EXPLORER.search(); if (result?.config) { this.cachedConfig = result.config; return this.cachedConfig; } return {}; } /** * Gets the saved configuration for a specific module. * @param module - The module to get configuration for * @returns Promise resolving to the module configuration or null if not found */ async getModuleConfig(module) { try { const config = await this.get(); if (config[module]) { return config[module]; } return null; } catch { return null; } } /** * Gets a specific property from the configuration. * @param property - The property key to retrieve * @returns Promise resolving to the value of the specified property */ async getProperty(property) { const config = await this.get(); return config[property]; } /** * Checks if a specific module is enabled in the configuration. * @param module - The module to check * @returns Promise resolving to true if the module is enabled, false otherwise */ async isModuleEnabled(module) { try { const config = await this.get(); const moduleConfig = config[module]; if (!moduleConfig) { return false; } return moduleConfig.isEnabled !== false; } catch { return false; } } /** * Merges partial configuration with the existing configuration. * @param partial - Partial configuration to merge * @returns Promise that resolves when the merged configuration is saved */ async merge(partial) { try { const config = await this.get(); const merged = { ...config, ...partial }; await this.set(merged); } catch (error) { console.error("Error merging config:", error); await this.set(partial); } } /** * Saves the entire configuration. * @param config - The complete configuration to save * @returns Promise that resolves when the configuration is saved */ async set(config) { try { const result = await this.EXPLORER.search(); const filePath = result?.filepath ?? `${CONFIG_FILE_DIRECTORY}/${CONFIG_MODULE_NAME}.config.js`; await this.writeFile(filePath, config); this.cachedConfig = config; this.EXPLORER.clearSearchCache(); } catch (error) { console.error("Error saving configuration:", error); throw error; } } /** * Sets a specific property in the configuration. * @param property - The property key to set * @param value - The value to assign to the property * @returns Promise that resolves when the updated configuration is saved */ async setProperty(property, value) { const config = await this.get(); config[property] = value; await this.set(config); } /** * Writes configuration to a file. * @param filepath - Path to write the configuration to * @param config - Configuration to write * @returns Promise that resolves when the file is written */ async writeFile(filepath, config) { const extension = this.FILE_SYSTEM_SERVICE.getExtensionFromFilePath(filepath); let content; switch (extension) { case ".cjs": { content = `module.exports = ${String(stringify(config, null, 2))};`; break; } case ".js": { content = `export default ${String(stringify(config, null, 2))};`; break; } case ".json": { content = String(stringify(config, null, 2)); break; } case ".mjs": { content = `export default ${String(stringify(config, null, 2))};`; break; } case ".yaml": { content = yaml.stringify(config); break; } case ".yml": { content = yaml.stringify(config); break; } default: { content = JSON.stringify(config, null, 2); } } const directoryName = this.FILE_SYSTEM_SERVICE.getDirectoryNameFromFilePath(filepath); if (!(await this.FILE_SYSTEM_SERVICE.isPathExists(directoryName))) { await this.FILE_SYSTEM_SERVICE.createDirectory(directoryName, { isRecursive: true }); } await this.FILE_SYSTEM_SERVICE.writeFile(filepath, content, "utf8"); } } export { CosmicConfigService }; //# sourceMappingURL=cosmi-config-config.service.js.map