kist
Version:
Package Pipeline Processor
151 lines (150 loc) • 7.1 kB
JavaScript
;
// ============================================================================
// Import
// ============================================================================
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConfigLoader = void 0;
const fs_1 = __importDefault(require("fs"));
const js_yaml_1 = __importDefault(require("js-yaml"));
const path_1 = __importDefault(require("path"));
const ArgumentParser_1 = require("../../cli/ArgumentParser");
const AbstractProcess_1 = require("../abstract/AbstractProcess");
// ============================================================================
// Class
// ============================================================================
/**
* ConfigLoader is responsible for loading and parsing configuration files.
* Supports a custom path via `--config`, and falls back to `kist.yaml` or `kist.yml`.
*/
class ConfigLoader extends AbstractProcess_1.AbstractProcess {
// Constructor
// ========================================================================
constructor() {
super();
// Parameters
// ========================================================================
/**
* Resolved path to the configuration file, if found.
*/
this.configPath = null;
/**
* Default filenames to search for configuration files.
*/
this.defaultFilenames = ["kist.yaml", "kist.yml"];
this.logDebug("ConfigLoader initialized.");
}
// Methods
// ========================================================================
/**
* Initializes the loader by locating the configuration file.
* Uses `--config` CLI flag if provided, otherwise defaults.
*/
initialize() {
return __awaiter(this, void 0, void 0, function* () {
const parser = new ArgumentParser_1.ArgumentParser();
const cliFlags = parser.getAllFlags();
const cliPath = typeof cliFlags.config === "string" ? cliFlags.config : undefined;
const searchPaths = cliPath ? [cliPath] : this.defaultFilenames;
this.logDebug(`Current working directory: ${process.cwd()}`);
this.logDebug(`Searching for config file${cliPath ? ` from --config=${cliPath}` : ""}...`);
for (const fileName of searchPaths) {
const resolvedPath = path_1.default.resolve(process.cwd(), fileName);
this.logDebug(`Checking: ${resolvedPath}`);
try {
yield fs_1.default.promises.access(resolvedPath, fs_1.default.constants.F_OK | fs_1.default.constants.R_OK);
this.configPath = resolvedPath;
this.logDebug(`Configuration file found: ${resolvedPath}`);
return;
}
catch (error) {
this.logDebug(`File not accessible: ${resolvedPath}`);
// ❗ If user explicitly provided --config and it fails, stop immediately
if (cliPath) {
throw new Error(`Configuration file not found or not accessible: ${resolvedPath}`);
}
}
}
this.logWarn("No configuration file found. Proceeding with default settings.");
});
}
// public async initialize(): Promise<void> {
// const parser = new ArgumentParser();
// const cliFlags = parser.getAllFlags();
// const cliPath =
// typeof cliFlags.config === "string" ? cliFlags.config : undefined;
// const searchPaths = cliPath ? [cliPath] : this.defaultFilenames;
// this.logDebug(`Current working directory: ${process.cwd()}`);
// this.logDebug(
// `Searching for config file${cliPath ? ` from --config=${cliPath}` : ""}...`,
// );
// for (const fileName of searchPaths) {
// const resolvedPath = path.resolve(process.cwd(), fileName);
// this.logDebug(`Checking: ${resolvedPath}`);
// try {
// await fs.promises.access(
// resolvedPath,
// fs.constants.F_OK | fs.constants.R_OK,
// );
// this.configPath = resolvedPath;
// this.logDebug(`Configuration file found: ${resolvedPath}`);
// return;
// } catch (error) {
// this.logDebug(`File not accessible: ${resolvedPath}`);
// }
// }
// this.logWarn(
// "No configuration file found. Proceeding with default settings.",
// );
// }
/**
* Loads and validates the configuration file.
*
* @returns Parsed and validated configuration object.
* @throws Error if the configuration file cannot be read or validated.
*/
loadConfig() {
return __awaiter(this, void 0, void 0, function* () {
if (!this.configPath) {
this.logWarn("No configuration file found. Using default configuration.");
return { stages: [] };
}
try {
this.logDebug(`Loading configuration from: ${this.configPath}`);
const fileContents = yield fs_1.default.promises.readFile(this.configPath, "utf8");
const config = js_yaml_1.default.load(fileContents);
this.validateConfig(config);
this.logDebug(`Successfully loaded configuration from: ${this.configPath}`);
return config;
}
catch (error) {
this.logError("Failed to load configuration.", error);
throw new Error(`Failed to load configuration: ${error.message}`);
}
});
}
/**
* Validates the structure of the configuration.
*
* @param config - The configuration object to validate.
* @throws Error if validation fails.
*/
validateConfig(config) {
if (!Array.isArray(config.stages)) {
throw new Error("Invalid configuration: 'stages' must be an array.");
}
this.logDebug("Configuration structure validated successfully.");
}
}
exports.ConfigLoader = ConfigLoader;