UNPKG

@syntropysoft/praetorian

Version:

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

266 lines 9.23 kB
"use strict"; /** * @file src/application/services/rule-loading/SimpleRuleDictionary.ts * @description Pure functional dictionary for simple rules (SOLID SRP + Functional Programming) */ Object.defineProperty(exports, "__esModule", { value: true }); exports.validateSimpleRules = exports.validateSimpleRule = exports.overrideSimpleRulesInDictionary = exports.removeSimpleRulesFromDictionary = exports.filterSimpleDictionary = exports.getSimpleDictionaryStats = exports.hasSimpleRule = exports.getSimpleRuleById = exports.simpleDictionaryToRules = exports.mergeSimpleRuleDictionaries = exports.addSimpleRulesToDictionary = exports.createEmptySimpleDictionary = void 0; /** * Creates an empty simple rule dictionary * @returns Empty rule dictionary */ const createEmptySimpleDictionary = () => ({}); exports.createEmptySimpleDictionary = createEmptySimpleDictionary; /** * Adds simple rules to dictionary, skipping duplicates (Guard Clause Pattern) * @param dictionary - Current dictionary * @param rules - Rules to add * @param source - Source identifier for warnings * @returns Dictionary result with added/skipped rules */ const addSimpleRulesToDictionary = (dictionary, rules, source = 'unknown') => { // Guard clause: no rules to add if (!rules || rules.length === 0) { return { dictionary, added: [], skipped: [], warnings: [], }; } const newDictionary = { ...dictionary }; const added = []; const skipped = []; const warnings = []; for (const rule of rules) { // Guard clause: rule without ID if (!rule.id || rule.id.trim().length === 0) { warnings.push(`Rule from ${source} has no ID, skipping`); continue; } // Guard clause: rule without name if (!rule.name || rule.name.trim().length === 0) { warnings.push(`Rule '${rule.id}' from ${source} has no name, skipping`); continue; } if (newDictionary[rule.id]) { // Rule already exists skipped.push(rule.id); warnings.push(`Rule '${rule.id}' already exists, skipping duplicate from ${source}`); } else { // Add new rule newDictionary[rule.id] = rule; added.push(rule.id); } } return { dictionary: newDictionary, added, skipped, warnings, }; }; exports.addSimpleRulesToDictionary = addSimpleRulesToDictionary; /** * Merges multiple simple rule dictionaries (Functional Composition) * @param dictionaries - Array of dictionaries to merge * @param sources - Source identifiers for warnings * @returns Merged dictionary result */ const mergeSimpleRuleDictionaries = (dictionaries, sources = []) => { // Guard clause: no dictionaries if (!dictionaries || dictionaries.length === 0) { return { dictionary: (0, exports.createEmptySimpleDictionary)(), added: [], skipped: [], warnings: [], }; } let result = (0, exports.createEmptySimpleDictionary)(); const allAdded = []; const allSkipped = []; const allWarnings = []; for (let i = 0; i < dictionaries.length; i++) { const dict = dictionaries[i]; const source = sources[i] || `source-${i}`; // Convert dictionary to array of rules const rules = Object.values(dict); const mergeResult = (0, exports.addSimpleRulesToDictionary)(result, rules, source); result = mergeResult.dictionary; allAdded.push(...mergeResult.added); allSkipped.push(...mergeResult.skipped); allWarnings.push(...mergeResult.warnings); } return { dictionary: result, added: allAdded, skipped: allSkipped, warnings: allWarnings, }; }; exports.mergeSimpleRuleDictionaries = mergeSimpleRuleDictionaries; /** * Converts dictionary to array of simple rules (Pure Function) * @param dictionary - Rule dictionary * @returns Array of rules */ const simpleDictionaryToRules = (dictionary) => { return Object.values(dictionary); }; exports.simpleDictionaryToRules = simpleDictionaryToRules; /** * Gets simple rule by ID from dictionary (Pure Function) * @param dictionary - Rule dictionary * @param ruleId - Rule ID to find * @returns Rule if found, undefined otherwise */ const getSimpleRuleById = (dictionary, ruleId) => { return dictionary[ruleId]; }; exports.getSimpleRuleById = getSimpleRuleById; /** * Checks if simple rule exists in dictionary (Pure Function) * @param dictionary - Rule dictionary * @param ruleId - Rule ID to check * @returns True if rule exists */ const hasSimpleRule = (dictionary, ruleId) => { return ruleId in dictionary; }; exports.hasSimpleRule = hasSimpleRule; /** * Gets simple rule dictionary statistics (Pure Function) * @param dictionary - Rule dictionary * @returns Statistics about the dictionary */ const getSimpleDictionaryStats = (dictionary) => { const rules = Object.values(dictionary); const uniqueIds = Object.keys(dictionary).length; return { totalRules: rules.length, uniqueIds, ruleIds: Object.keys(dictionary).sort(), ruleNames: rules.map(rule => rule.name).sort(), }; }; exports.getSimpleDictionaryStats = getSimpleDictionaryStats; /** * Filters simple dictionary by predicate (Pure Function) * @param dictionary - Rule dictionary * @param predicate - Filter function * @returns Filtered dictionary */ const filterSimpleDictionary = (dictionary, predicate) => { const filtered = {}; for (const [id, rule] of Object.entries(dictionary)) { if (predicate(rule)) { filtered[id] = rule; } } return filtered; }; exports.filterSimpleDictionary = filterSimpleDictionary; /** * Removes simple rules from dictionary (Pure Function) * @param dictionary - Rule dictionary * @param ruleIds - Rule IDs to remove * @returns New dictionary without specified rules */ const removeSimpleRulesFromDictionary = (dictionary, ruleIds) => { const newDictionary = { ...dictionary }; for (const ruleId of ruleIds) { delete newDictionary[ruleId]; } return newDictionary; }; exports.removeSimpleRulesFromDictionary = removeSimpleRulesFromDictionary; /** * Overrides simple rules in dictionary (Pure Function) * @param dictionary - Rule dictionary * @param overrides - Rules to override (by ID) * @returns New dictionary with overridden rules */ const overrideSimpleRulesInDictionary = (dictionary, overrides) => { const newDictionary = { ...dictionary }; const overridden = []; const warnings = []; for (const override of overrides) { // Guard clause: no ID in override if (!override.id || override.id.trim().length === 0) { warnings.push('Override rule has no ID, skipping'); continue; } if (newDictionary[override.id]) { // Merge with existing rule newDictionary[override.id] = { ...newDictionary[override.id], ...override, id: override.id, // Ensure ID is not overridden }; overridden.push(override.id); } else { warnings.push(`Cannot override rule '${override.id}' - rule not found in dictionary`); } } return { dictionary: newDictionary, added: overridden, skipped: [], warnings, }; }; exports.overrideSimpleRulesInDictionary = overrideSimpleRulesInDictionary; /** * Validates simple rule structure (Pure Function with Guard Clauses) * @param rule - Rule to validate * @returns Validation result */ const validateSimpleRule = (rule) => { const errors = []; // Guard clause: no rule object if (!rule) { errors.push('Rule object is required'); return { valid: false, errors }; } // Guard clause: no ID if (!rule.id || typeof rule.id !== 'string' || rule.id.trim().length === 0) { errors.push('Rule must have a valid ID'); } // Guard clause: no name if (!rule.name || typeof rule.name !== 'string' || rule.name.trim().length === 0) { errors.push('Rule must have a valid name'); } return { valid: errors.length === 0, errors, }; }; exports.validateSimpleRule = validateSimpleRule; /** * Validates array of simple rules (Pure Function) * @param rules - Rules to validate * @returns Validation result */ const validateSimpleRules = (rules) => { // Guard clause: no rules array if (!Array.isArray(rules)) { return { valid: false, errors: ['Rules must be an array'] }; } const allErrors = []; for (let i = 0; i < rules.length; i++) { const rule = rules[i]; const validation = (0, exports.validateSimpleRule)(rule); if (!validation.valid) { allErrors.push(`Rule at index ${i}: ${validation.errors.join(', ')}`); } } return { valid: allErrors.length === 0, errors: allErrors, }; }; exports.validateSimpleRules = validateSimpleRules; //# sourceMappingURL=SimpleRuleDictionary.js.map