@decaf-ts/decorator-validation
Version:
simple decorator based validation engine
93 lines • 4.24 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.PathProxyEngine = void 0;
const constants_1 = require("./../constants/index.cjs");
const strings_1 = require("./strings.cjs");
const fallbackGetParent = (target) => {
return target[constants_1.VALIDATION_PARENT_KEY];
};
const fallbackGetValue = (target, prop) => {
if (!Object.prototype.hasOwnProperty.call(target, prop))
throw new Error((0, strings_1.sf)(constants_1.COMPARISON_ERROR_MESSAGES.PROPERTY_NOT_EXIST, prop));
return target[prop];
};
/**
* Standard path resolution utility for accessing nested object properties.
* Provides consistent dot-notation access to both parent and child properties
* across complex object structures.
*
* - Dot-notation path resolution ('object.child.property')
* - Parent traversal using '../' notation
* - Configurable property access behavior
* - Null/undefined safety checks
*/
class PathProxyEngine {
/**
* Creates a path-aware proxy for the target object
* @template T - The type of the target object
* @param {T} rootTarget - The target object to proxy
* @param opts - Configuration options
* @param opts.getValue - Custom function to get property value
* @param opts.getParent - Custom function to get parent object
* @param opts.ignoreUndefined - Whether to ignore undefined values in paths
* @param opts.ignoreNull - Whether to ignore null values in paths
* @returns A proxy object with path access capabilities
*/
static create(rootTarget, opts) {
const { getValue, getParent, ignoreUndefined, ignoreNull } = {
getParent: fallbackGetParent,
getValue: fallbackGetValue,
ignoreNull: false,
ignoreUndefined: false,
...opts,
};
const proxy = new Proxy({}, {
get(target, prop) {
if (prop === "getValueFromPath") {
return function (path) {
const parts = PathProxyEngine.parsePath(path);
let current = rootTarget;
for (let i = 0; i < parts.length; i++) {
const part = parts[i];
if (part === "..") {
const parent = getParent(current);
if (!parent || typeof parent !== "object") {
throw new Error((0, strings_1.sf)(constants_1.COMPARISON_ERROR_MESSAGES.CONTEXT_NOT_OBJECT_COMPARISON, i + 1, path));
}
current = parent; //PathProxyEngine.create(parentTarget, opts);
continue;
}
current = getValue(current, part);
if (!ignoreUndefined && typeof current === "undefined")
throw new Error((0, strings_1.sf)(constants_1.COMPARISON_ERROR_MESSAGES.PROPERTY_INVALID, path, part));
if (!ignoreNull && current === null)
throw new Error((0, strings_1.sf)(constants_1.COMPARISON_ERROR_MESSAGES.PROPERTY_INVALID, path, part));
}
return current;
};
}
return target[prop];
},
});
// Object.defineProperty(proxy, PROXY_PROP, {
// value: true, // overwrite by proxy behavior
// enumerable: false,
// configurable: false,
// writable: false,
// });
return proxy;
}
/**
* Parses a path string into individual components
* @param path - The path string to parse (e.g., "user.address.city")
* @returns An array of path components
* @throws Error if the path is invalid
*/
static parsePath(path) {
if (typeof path !== "string" || !path.trim())
throw new Error((0, strings_1.sf)(constants_1.COMPARISON_ERROR_MESSAGES.INVALID_PATH, path));
return path.match(/(\.\.|[^/.]+)/g) || [];
}
}
exports.PathProxyEngine = PathProxyEngine;
//# sourceMappingURL=PathProxy.js.map