Overview
PathResolver provides secure dot-notation path resolution with caching and prototype pollution protection.
Note: PathResolver is used internally by RuleEngine. You typically use engine.resolvePath() instead of accessing PathResolver directly.
resolvePath()
Resolve a dot-notation path to a value.
const value = engine . resolvePath ( context , path , defaultValue );
Parameters
Object to resolve path in
Dot-notation path (e.g., ‘user.profile.name’)
Value to return if path doesn’t exist
Returns
Resolved value or defaultValue if path doesn’t exist.
Examples
Basic
Missing Paths
Arrays
Nested Objects
const data = {
user: {
name: 'John' ,
profile: {
age: 25 ,
email: 'john@example.com'
}
}
};
engine . resolvePath ( data , 'user.name' );
// 'John'
engine . resolvePath ( data , 'user.profile.age' );
// 25
engine . resolvePath ( data , 'user.profile.email' );
// 'john@example.com'
Security Features
Prototype Pollution Protection
PathResolver blocks dangerous paths by default:
const data = {};
// Blocked: prototype access
engine . resolvePath ( data , '__proto__' );
// undefined (blocked)
engine . resolvePath ( data , 'constructor' );
// undefined (blocked)
engine . resolvePath ( data , '__proto__.polluted' );
// undefined (blocked)
Never set allowPrototypeAccess: true in production. It opens security vulnerabilities.
Function Blocking
Functions are blocked by default:
const data = {
getName : function () { return 'John' ; }
};
engine . resolvePath ( data , 'getName' );
// undefined (blocked - it's a function)
Caching
PathResolver caches resolutions for performance:
// First call - cache miss
engine . resolvePath ( data , 'user.profile.name' ); // Resolves and caches
// Second call - cache hit (faster)
engine . resolvePath ( data , 'user.profile.name' ); // Retrieved from cache
Clear Cache
engine . clearCache ();
// Clears both expression and path caches
Advanced Usage
Direct PathResolver Access
// Access internal PathResolver (rare)
const pathResolver = engine . _internal . pathResolver ;
// Use NOT_FOUND symbol
const value = pathResolver . resolve ( data , path , pathResolver . NOT_FOUND );
if ( value === pathResolver . NOT_FOUND ) {
console . log ( 'Path does not exist' );
}
Literal Values
// resolveValueOrLiteral handles both paths and literals
const pathResolver = engine . _internal . pathResolver ;
pathResolver . resolveValueOrLiteral ( data , 'user.name' );
// Resolves path → 'John'
pathResolver . resolveValueOrLiteral ( data , 'literal-string' );
// Returns literal → 'literal-string'
pathResolver . resolveValueOrLiteral ( data , 123 );
// Returns literal → 123
Configuration
Configure via engine config:
const engine = createRuleEngine ({
allowPrototypeAccess: false , // Block prototype (default: false)
maxCacheSize: 1000 , // Path cache size
enableCache: true // Enable caching (default: true)
});
Common Patterns
// Instead of optional chaining
const email = data ?. user ?. profile ?. email ;
// Use resolvePath with default
const email = engine . resolvePath ( data , 'user.profile.email' , null );
const fields = [ 'user.name' , 'user.email' , 'user.age' ];
const values = fields . map ( field =>
engine . resolvePath ( data , field )
);
function validateRequired ( data , paths ) {
return paths . every ( path => {
const value = engine . resolvePath ( data , path );
return value !== null && value !== undefined ;
});
}
validateRequired ( data , [ 'user.name' , 'user.email' ]);
Error Handling
PathResolver doesn’t throw errors - it returns undefined or defaultValue:
// All return undefined (not errors)
engine . resolvePath ( null , 'path' );
engine . resolvePath ( undefined , 'path' );
engine . resolvePath ({}, 'nonexistent.path' );
engine . resolvePath ({}, '__proto__' ); // Blocked path