UNPKG

@syntropysoft/praetorian

Version:

Praetorian CLI – A universal multi-environment configuration validator for DevSecOps teams. Validate, compare, and secure YAML/ENV files with ease.

221 lines 8.06 kB
"use strict"; /** * @file src/application/services/rule-loading/RuleSetLoader.ts * @description Pure functions for loading rule sets from various sources */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.combineRuleLoadResults = exports.createEmptyResult = exports.isUrl = exports.extractRulesFromContent = exports.parseContentByExtension = exports.parseRuleFile = exports.loadRuleSetFromUrl = exports.loadRuleSetFromFile = exports.loadCoreRuleSet = exports.loadRuleSet = void 0; const promises_1 = __importDefault(require("fs/promises")); const path_1 = __importDefault(require("path")); const js_yaml_1 = __importDefault(require("js-yaml")); const core_rules_1 = require("../../../shared/rules/core-rules"); /** * Loads a rule set from a path or URL * @param ruleSetPath - Path to rule set (file path or URL) * @param options - Loading options * @returns Promise with loaded rules */ const loadRuleSet = async (ruleSetPath, options) => { // Guard clause: empty path if (!ruleSetPath || ruleSetPath.trim().length === 0) { return (0, exports.createEmptyResult)(['Rule set path cannot be empty']); } try { // Check if it's a core rule set reference if (ruleSetPath.startsWith('@praetorian/core/')) { return (0, exports.loadCoreRuleSet)(ruleSetPath); } // Check if it's a URL if ((0, exports.isUrl)(ruleSetPath)) { return await (0, exports.loadRuleSetFromUrl)(ruleSetPath); } // Load from local file return await (0, exports.loadRuleSetFromFile)(ruleSetPath, options); } catch (error) { return (0, exports.createEmptyResult)([`Failed to load rule set ${ruleSetPath}: ${error.message}`]); } }; exports.loadRuleSet = loadRuleSet; /** * Loads a core rule set by name * @param corePath - Core rule set path (e.g., '@praetorian/core/all') * @returns Rule load result */ const loadCoreRuleSet = (corePath) => { // Guard clause: invalid core path if (!corePath || !corePath.startsWith('@praetorian/core/')) { return (0, exports.createEmptyResult)(['Invalid core rule set path']); } const coreSetName = corePath.replace('@praetorian/core/', ''); // Guard clause: unknown core set if (!(coreSetName in core_rules_1.CORE_RULE_SETS)) { return (0, exports.createEmptyResult)([`Unknown core rule set: ${coreSetName}`]); } const rules = core_rules_1.CORE_RULE_SETS[coreSetName]; return { rules: Array.isArray(rules) ? rules : [], errors: [], warnings: [], }; }; exports.loadCoreRuleSet = loadCoreRuleSet; /** * Loads rule set from a local file * @param filePath - Path to the rule file * @param options - Loading options * @returns Promise with loaded rules */ const loadRuleSetFromFile = async (filePath, options) => { // Guard clause: empty file path if (!filePath || filePath.trim().length === 0) { return (0, exports.createEmptyResult)(['File path cannot be empty']); } try { const fullPath = path_1.default.resolve(options.workingDirectory, filePath); const content = await promises_1.default.readFile(fullPath, 'utf-8'); const parseResult = (0, exports.parseRuleFile)(content, fullPath); return parseResult; } catch (error) { return (0, exports.createEmptyResult)([`Failed to read rule file ${filePath}: ${error.message}`]); } }; exports.loadRuleSetFromFile = loadRuleSetFromFile; /** * Loads rule set from a URL (placeholder for future implementation) * @param url - URL to the rule set * @returns Promise with loaded rules */ const loadRuleSetFromUrl = async (url) => { // Guard clause: empty URL if (!url || url.trim().length === 0) { return (0, exports.createEmptyResult)(['URL cannot be empty']); } // Guard clause: invalid URL if (!(0, exports.isUrl)(url)) { return (0, exports.createEmptyResult)(['Invalid URL format']); } // TODO: Implement URL loading return (0, exports.createEmptyResult)([`URL loading not yet implemented: ${url}`]); }; exports.loadRuleSetFromUrl = loadRuleSetFromUrl; /** * Parses rule file content based on file extension * @param content - File content * @param filePath - Full file path for extension detection * @returns Parsed rules result */ const parseRuleFile = (content, filePath) => { // Guard clause: empty content if (!content || content.trim().length === 0) { return (0, exports.createEmptyResult)(['File content is empty']); } try { const ext = path_1.default.extname(filePath).toLowerCase(); const parsedContent = (0, exports.parseContentByExtension)(content, ext); // Guard clause: invalid parsed content if (!parsedContent) { return (0, exports.createEmptyResult)([`Failed to parse ${ext} file`]); } const rules = (0, exports.extractRulesFromContent)(parsedContent); return { rules, errors: [], warnings: [], }; } catch (error) { return (0, exports.createEmptyResult)([`Failed to parse rule file: ${error.message}`]); } }; exports.parseRuleFile = parseRuleFile; /** * Parses content based on file extension * @param content - File content * @param extension - File extension * @returns Parsed content */ const parseContentByExtension = (content, extension) => { // Guard clause: empty content if (!content || content.trim().length === 0) { return null; } switch (extension) { case '.yaml': case '.yml': return js_yaml_1.default.load(content); case '.json': return JSON.parse(content); default: throw new Error(`Unsupported file format: ${extension}`); } }; exports.parseContentByExtension = parseContentByExtension; /** * Extracts rules from parsed content * @param parsedContent - Parsed file content * @returns Array of rules */ const extractRulesFromContent = (parsedContent) => { // Guard clause: null or undefined content if (!parsedContent) { return []; } // If it's already an array, return it if (Array.isArray(parsedContent)) { return parsedContent; } // If it has a rules property, extract it if (parsedContent.rules && Array.isArray(parsedContent.rules)) { return parsedContent.rules; } // Invalid format throw new Error('Invalid rule file format: expected array of rules or object with rules array'); }; exports.extractRulesFromContent = extractRulesFromContent; /** * Checks if a string is a valid URL * @param str - String to check * @returns True if URL, false otherwise */ const isUrl = (str) => { // Guard clause: empty string if (!str || str.trim().length === 0) { return false; } return str.startsWith('http://') || str.startsWith('https://'); }; exports.isUrl = isUrl; /** * Creates an empty rule load result with errors * @param errors - Array of error messages * @returns Empty result with errors */ const createEmptyResult = (errors = []) => ({ rules: [], errors, warnings: [], }); exports.createEmptyResult = createEmptyResult; /** * Combines multiple rule load results * @param results - Array of rule load results * @returns Combined result */ const combineRuleLoadResults = (results) => { // Guard clause: empty results array if (!results || results.length === 0) { return (0, exports.createEmptyResult)(); } return results.reduce((combined, result) => ({ rules: [...combined.rules, ...result.rules], errors: [...combined.errors, ...result.errors], warnings: [...combined.warnings, ...result.warnings], }), (0, exports.createEmptyResult)()); }; exports.combineRuleLoadResults = combineRuleLoadResults; //# sourceMappingURL=RuleSetLoader.js.map