Operators
x-fidelity includes several built-in operators that can be used in your rules to evaluate conditions. Here's a comprehensive guide to each operator.
Overview
Operators are functions that:
- Evaluate conditions in rules
- Return boolean values (true indicates a rule failure)
- Can be customized and extended
- Support both simple and complex validations
Built-in Operators
fileContains
Checks if files contain specific patterns or strings.
{
"fact": "repoFileAnalysis",
"params": {
"checkPattern": ["password", "apiKey"],
"resultFact": "fileResults"
},
"operator": "fileContains",
"value": true
}
Features:
- Supports multiple patterns
- Line number tracking
- Sensitive data masking
- Multi-line content analysis
- Long line splitting
outdatedFramework
Verifies dependency versions against minimum requirements.
{
"fact": "repoDependencyAnalysis",
"params": {
"resultFact": "dependencyResults",
"minimumDependencyVersions": {
"react": ">=17.0.0",
"typescript": "^4.0.0"
}
},
"operator": "outdatedFramework",
"value": true
}
Features:
- Semver range support
- Nested dependency checking
- Pre-release version handling
- Package manager compatibility (npm/yarn)
- Build metadata support
- Complex version ranges
nonStandardDirectoryStructure
Validates project directory structure against defined standards.
{
"fact": "fileData",
"path": "$.filePath",
"operator": "nonStandardDirectoryStructure",
"value": {
"fact": "standardStructure"
}
}
Features:
- Recursive directory validation
- Blacklist/whitelist support
- Symlink handling
- Path traversal protection
- Detailed reporting
openaiAnalysisHighSeverity
Evaluates AI-generated analysis results for high-severity issues.
{
"fact": "openaiAnalysis",
"params": {
"prompt": "Identify security issues",
"resultFact": "securityAnalysis"
},
"operator": "openaiAnalysisHighSeverity",
"value": 8
}
Features:
- Configurable severity threshold
- Detailed issue reporting
- AI-powered analysis
- Custom prompt support
- Error handling for AI responses
globalPatternRatio
Evaluates the ratio of new API patterns to legacy patterns across the codebase.
{
"fact": "globalFileAnalysis",
"params": {
"newPatterns": ["newApiMethod\\("],
"legacyPatterns": ["legacyApiMethod\\("],
"fileFilter": "\\.(ts|js)$",
"resultFact": "apiMigrationAnalysis"
},
"operator": "globalPatternRatio",
"value": {
"threshold": 0.8,
"comparison": "gte"
}
}
Features:
- Measures adoption of new APIs
- Tracks deprecation of legacy code
- Configurable threshold
- Supports multiple patterns
- Flexible comparison types (gte/lte)
- Detailed statistics
globalPatternCount
Checks if a pattern appears a certain number of times across the codebase.
{
"fact": "globalFileAnalysis",
"params": {
"newPatterns": ["requiredMethod\\("],
"fileFilter": "\\.(ts|js)$",
"resultFact": "requiredMethodAnalysis"
},
"operator": "globalPatternCount",
"value": {
"threshold": 10,
"comparison": "gte"
}
}
Features:
- Ensures minimum/maximum usage of patterns
- Supports multiple patterns
- Configurable threshold
- Flexible comparison types (gte/lte)
- Detailed match information
hasFilesWithMultiplePatterns
Identifies files that contain multiple specified patterns.
{
"fact": "globalFileAnalysis",
"params": {
"patterns": ["pattern1\\(", "pattern2\\("],
"fileFilter": "\\.(ts|js)$",
"outputGrouping": "file",
"resultFact": "multiPatternAnalysis"
},
"operator": "hasFilesWithMultiplePatterns",
"value": 2
}
Features:
- Finds files with multiple patterns
- Configurable threshold for pattern count
- Works with file-centric output grouping
- Detailed file reporting
regexMatch
Tests if a string matches a regular expression pattern.
{
"fact": "fileData",
"path": "$.filePath",
"operator": "regexMatch",
"value": "^.*\\/facts\\/(?!.*\\.test).*\\.ts$"
}
Features:
- Supports complex regex patterns
- Handles regex flags
- Supports /pattern/flags format
- Detailed error reporting
invalidRemoteValidation
Validates extracted strings against remote endpoints.
{
"fact": "remoteSubstringValidation",
"params": {
"pattern": "\"systemId\":[\\s]*\"([a-z]*)\"",
"flags": "gi",
"validationParams": {
"url": "http://validator.example.com/check",
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
"body": {
"systemId": "#MATCH#"
},
"checkJsonPath": "$.validSystems[?(@.id == '#MATCH#')]"
},
"resultFact": "validationResult"
},
"operator": "invalidRemoteValidation",
"value": true
}
Features:
- Remote API integration
- Pattern extraction with flags
- JSONPath validation
- Flexible HTTP methods
- Custom headers and body
missingRequiredFiles
Checks if required files are missing from the repository.
{
"fact": "missingRequiredFiles",
"params": {
"requiredFiles": [
"/README.md",
"/CONTRIBUTING.md",
"/LICENSE"
],
"resultFact": "missingRequiredFilesResult"
},
"operator": "missingRequiredFiles",
"value": true
}
Features:
- Path pattern matching
- Detailed reporting
- Support for glob patterns
- Path normalization
astComplexity
Evaluates code complexity metrics from AST analysis.
{
"fact": "functionComplexity",
"params": {
"resultFact": "complexityResult",
"thresholds": {
"cyclomaticComplexity": 20,
"cognitiveComplexity": 30,
"nestingDepth": 10,
"parameterCount": 5,
"returnCount": 10
}
},
"operator": "astComplexity",
"value": {
"cyclomaticComplexity": 20,
"cognitiveComplexity": 30,
"nestingDepth": 10,
"parameterCount": 5,
"returnCount": 10
}
}
Features:
- Multiple complexity metrics
- Configurable thresholds
- Function-level analysis
- Detailed reporting
functionCount
Checks if a file contains too many functions.
{
"fact": "functionCount",
"params": {
"resultFact": "functionCountResult"
},
"operator": "functionCount",
"value": 20
}
Features:
- Counts all function types
- Configurable threshold
- Detailed reporting
- File-level analysis
Creating Custom Operators
You can create custom operators by:
- Implementing the
OperatorDefn
interface:
interface OperatorDefn {
name: string;
fn: (factValue: any, params: any) => boolean;
}
- Creating the operator function:
const customOperator = {
name: 'customOperator',
fn: (factValue, params) => {
try {
// Your logic here
return true; // or false
} catch (e) {
logger.error(`customOperator error: ${e}`);
return false;
}
}
};
- Adding it to your plugin:
module.exports = {
name: 'my-plugin',
version: '1.0.0',
operators: [customOperator]
};
Best Practices
-
Error Handling:
- Always include try/catch blocks
- Log errors appropriately
- Return false for non-fatal errors
- Provide detailed error messages
-
Performance:
- Keep operations lightweight
- Cache results when possible
- Use async/await for I/O operations
- Log performance metrics
-
Security:
- Validate all inputs
- Protect against path traversal
- Handle sensitive data carefully
- Use maskSensitiveData for logging
-
Testing:
- Write comprehensive unit tests
- Test edge cases and boundary conditions
- Mock external dependencies
- Test error handling
-
Flexibility:
- Support multiple input formats
- Provide configurable options
- Handle edge cases gracefully
- Document expected inputs and outputs
Next Steps
- Learn about Facts
- Explore Rules
- Create Custom Plugins