@syntropysoft/praetorian
Version:
Praetorian CLI – A universal multi-environment configuration validator for DevSecOps teams. Validate, compare, and secure YAML/ENV files with ease.
232 lines • 7.96 kB
JavaScript
;
/**
* @file src/application/services/rule-loading/UltraSimpleRuleDictionary.ts
* @description Ultra-simple rule dictionary - ID as key, name as value (SOLID SRP + Functional Programming)
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.dictionaryToArray = exports.arrayToDictionary = exports.overrideRulesInDictionary = exports.removeRulesFromDictionary = exports.filterDictionary = exports.getDictionaryStats = exports.hasRule = exports.getRuleNameById = exports.mergeRuleDictionaries = exports.addRulesToDictionary = exports.createEmptyDictionary = void 0;
/**
* Creates an empty rule dictionary
* @returns Empty rule dictionary
*/
const createEmptyDictionary = () => ({});
exports.createEmptyDictionary = createEmptyDictionary;
/**
* Adds rules to dictionary, skipping duplicates (Guard Clause Pattern)
* @param dictionary - Current dictionary
* @param rules - Rules to add (ID -> Name mapping)
* @param source - Source identifier for warnings
* @returns Dictionary result with added/skipped rules
*/
const addRulesToDictionary = (dictionary, rules, source = 'unknown') => {
// Guard clause: no rules to add
if (!rules || Object.keys(rules).length === 0) {
return {
dictionary,
added: [],
skipped: [],
warnings: [],
};
}
const newDictionary = { ...dictionary };
const added = [];
const skipped = [];
const warnings = [];
for (const [ruleId, ruleName] of Object.entries(rules)) {
// Guard clause: no ID
if (!ruleId || ruleId.trim().length === 0) {
warnings.push(`Rule from ${source} has no ID, skipping`);
continue;
}
// Guard clause: no name
if (!ruleName || ruleName.trim().length === 0) {
warnings.push(`Rule '${ruleId}' from ${source} has no name, skipping`);
continue;
}
if (newDictionary[ruleId]) {
// Rule already exists
skipped.push(ruleId);
warnings.push(`Rule '${ruleId}' already exists, skipping duplicate from ${source}`);
}
else {
// Add new rule
newDictionary[ruleId] = ruleName;
added.push(ruleId);
}
}
return {
dictionary: newDictionary,
added,
skipped,
warnings,
};
};
exports.addRulesToDictionary = addRulesToDictionary;
/**
* Merges multiple rule dictionaries (Functional Composition)
* @param dictionaries - Array of dictionaries to merge
* @param sources - Source identifiers for warnings
* @returns Merged dictionary result
*/
const mergeRuleDictionaries = (dictionaries, sources = []) => {
// Guard clause: no dictionaries
if (!dictionaries || dictionaries.length === 0) {
return {
dictionary: (0, exports.createEmptyDictionary)(),
added: [],
skipped: [],
warnings: [],
};
}
let result = (0, exports.createEmptyDictionary)();
const allAdded = [];
const allSkipped = [];
const allWarnings = [];
for (let i = 0; i < dictionaries.length; i++) {
const dict = dictionaries[i];
const source = sources[i] || `source-${i}`;
const mergeResult = (0, exports.addRulesToDictionary)(result, dict, 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.mergeRuleDictionaries = mergeRuleDictionaries;
/**
* Gets rule name by ID (Pure Function)
* @param dictionary - Rule dictionary
* @param ruleId - Rule ID to find
* @returns Rule name if found, undefined otherwise
*/
const getRuleNameById = (dictionary, ruleId) => {
return dictionary[ruleId];
};
exports.getRuleNameById = getRuleNameById;
/**
* Checks if rule exists in dictionary (Pure Function)
* @param dictionary - Rule dictionary
* @param ruleId - Rule ID to check
* @returns True if rule exists
*/
const hasRule = (dictionary, ruleId) => {
return ruleId in dictionary;
};
exports.hasRule = hasRule;
/**
* Gets dictionary statistics (Pure Function)
* @param dictionary - Rule dictionary
* @returns Statistics about the dictionary
*/
const getDictionaryStats = (dictionary) => {
const ruleIds = Object.keys(dictionary);
const ruleNames = Object.values(dictionary);
return {
totalRules: ruleIds.length,
uniqueIds: ruleIds.length,
ruleIds: ruleIds.sort(),
ruleNames: ruleNames.sort(),
};
};
exports.getDictionaryStats = getDictionaryStats;
/**
* Filters dictionary by predicate (Pure Function)
* @param dictionary - Rule dictionary
* @param predicate - Filter function
* @returns Filtered dictionary
*/
const filterDictionary = (dictionary, predicate) => {
const filtered = {};
for (const [ruleId, ruleName] of Object.entries(dictionary)) {
if (predicate(ruleId, ruleName)) {
filtered[ruleId] = ruleName;
}
}
return filtered;
};
exports.filterDictionary = filterDictionary;
/**
* Removes rules from dictionary (Pure Function)
* @param dictionary - Rule dictionary
* @param ruleIds - Rule IDs to remove
* @returns New dictionary without specified rules
*/
const removeRulesFromDictionary = (dictionary, ruleIds) => {
const newDictionary = { ...dictionary };
for (const ruleId of ruleIds) {
delete newDictionary[ruleId];
}
return newDictionary;
};
exports.removeRulesFromDictionary = removeRulesFromDictionary;
/**
* Overrides rules in dictionary (Pure Function)
* @param dictionary - Rule dictionary
* @param overrides - Rules to override (ID -> Name mapping)
* @returns New dictionary with overridden rules
*/
const overrideRulesInDictionary = (dictionary, overrides) => {
const newDictionary = { ...dictionary };
const overridden = [];
const warnings = [];
for (const override of overrides) {
for (const [ruleId, ruleName] of Object.entries(override)) {
// Guard clause: no ID in override
if (!ruleId || ruleId.trim().length === 0) {
warnings.push('Override rule has no ID, skipping');
continue;
}
// Guard clause: no name in override
if (!ruleName || ruleName.trim().length === 0) {
warnings.push(`Override rule '${ruleId}' has no name, skipping`);
continue;
}
if (newDictionary[ruleId]) {
// Override existing rule
newDictionary[ruleId] = ruleName;
overridden.push(ruleId);
}
else {
warnings.push(`Cannot override rule '${ruleId}' - rule not found in dictionary`);
}
}
}
return {
dictionary: newDictionary,
added: overridden,
skipped: [],
warnings,
};
};
exports.overrideRulesInDictionary = overrideRulesInDictionary;
/**
* Converts array of rule objects to dictionary (Pure Function)
* @param rules - Array of rule objects with id and name
* @returns Dictionary mapping
*/
const arrayToDictionary = (rules) => {
const dictionary = {};
for (const rule of rules) {
if (rule.id && rule.name) {
dictionary[rule.id] = rule.name;
}
}
return dictionary;
};
exports.arrayToDictionary = arrayToDictionary;
/**
* Converts dictionary to array of rule objects (Pure Function)
* @param dictionary - Rule dictionary
* @returns Array of rule objects
*/
const dictionaryToArray = (dictionary) => {
return Object.entries(dictionary).map(([id, name]) => ({ id, name }));
};
exports.dictionaryToArray = dictionaryToArray;
//# sourceMappingURL=UltraSimpleRuleDictionary.js.map