UNPKG

@elsikora/commitizen-plugin-commitlint-ai

Version:
175 lines (172 loc) 6.84 kB
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 {IFileSystemService} fileSystemService - The file system service for file operations */ 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<boolean>} 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<IConfig>} 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 a specific property from the configuration. * @param {K} property - The property key to retrieve * @returns {Promise<IConfig[K]>} Promise resolving to the value of the specified property * @template K - The type of the property key */ async getProperty(property) { const config = await this.get(); return config[property]; } /** * Merges partial configuration with the existing configuration. * @param {Partial<IConfig>} partial - Partial configuration to merge * @returns {Promise<void>} 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 {IConfig} config - The complete configuration to save * @returns {Promise<void>} 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 {K} property - The property key to set * @param {IConfig[K]} value - The value to assign to the property * @returns {Promise<void>} Promise that resolves when the updated configuration is saved * @template K - The type of the property key */ async setProperty(property, value) { const config = await this.get(); config[property] = value; await this.set(config); } /** * Writes configuration to a file. * @param {string} filepath - Path to write the configuration to * @param {IConfig} config - Configuration to write * @returns {Promise<void>} 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=cosmic-config.service.js.map