UNPKG

nope-js-node

Version:

NoPE Runtime for Nodejs. For Browser-Support please use nope-browser

290 lines (289 loc) 11.6 kB
"use strict"; /** * @author Martin Karkowski * @email m.karkowski@zema.de * @desc [description] */ Object.defineProperty(exports, "__esModule", { value: true }); exports.patternIsValid = exports.containsWildcards = exports.comparePatternAndPath = exports.generateResult = exports.MULTI_LEVEL_WILDCARD = exports.SINGLE_LEVEL_WILDCARD = exports.SEPARATOR = void 0; const objectMethods_1 = require("./objectMethods"); exports.SEPARATOR = "/"; exports.SINGLE_LEVEL_WILDCARD = "+"; exports.MULTI_LEVEL_WILDCARD = "#"; /** * Helper to generate a Result. * * @author M.Karkowski * @export * @param {Partial<TPathCompareResult>} [res={}] * @return {*} {TPathCompareResult} */ function generateResult(res = {}) { let defaultResult = { affected: false, affectedByChild: false, affectedByParent: false, affectedOnSameLevel: false, containsWildcards: false, patternToExtractData: false, patternLengthComparedToPathLength: "=", pathToExtractData: false, }; defaultResult = Object.assign(defaultResult, res); defaultResult.affected = defaultResult.affectedByChild || defaultResult.affectedByParent || defaultResult.affectedOnSameLevel; return Object.assign(defaultResult, res); } exports.generateResult = generateResult; /** * Matches the given path, with the pattern and determines, if the path might affect * the given pattern. * * @example path = "a/b/c"; pattern = "a/#"; => totalPath = "a/b/c"; diffPath = "b/c" * @author M.Karkowski * @export * @param {string} pathPattern The pattern to test * @param {string} contentPath The path to use as basis * @return {TPathCompareResult} */ function comparePatternAndPath(pathPattern, contentPath, options = { matchTopicsWithoutWildcards: false, }) { if (containsWildcards(contentPath)) { throw Error("The Path is invalid. The path should not contain pattern-related chars '#' or '+'."); } if (!patternIsValid(pathPattern)) { throw Error("The Pattern is invalid."); } if (!patternIsValid(contentPath)) { throw Error("The Path is invalid."); } const _containsWildcards = containsWildcards(pathPattern); const patternSegments = pathPattern.split(exports.SEPARATOR); const contentPathSegments = contentPath.split(exports.SEPARATOR); const patternLength = patternSegments.length; const contentPathLength = contentPathSegments.length; // Define the Char for the comparer let patternLengthComparedToPathLength = "="; if (patternLength > contentPathLength) patternLengthComparedToPathLength = ">"; else if (patternLength < contentPathLength) patternLengthComparedToPathLength = "<"; // If both, the pattern and the path are equal => return the result. if (pathPattern === contentPath) { return generateResult({ affectedOnSameLevel: true, pathToExtractData: contentPath, patternLengthComparedToPathLength, }); } // If the Path is not realy defined. if (contentPath === "") { return generateResult({ affectedByParent: true, patternToExtractData: _containsWildcards ? pathPattern : false, pathToExtractData: _containsWildcards ? false : pathPattern, patternLengthComparedToPathLength: ">", containsWildcards: _containsWildcards, }); } if (pathPattern === "") { return generateResult({ affectedByChild: true, pathToExtractData: "", patternLengthComparedToPathLength: "<", }); } if (options.matchTopicsWithoutWildcards) { if (contentPath.startsWith(pathPattern)) { // Path is longer then the Pattern; // => A Change is performed by "Child", if (_containsWildcards) { return generateResult({ affectedByChild: true, pathToExtractData: contentPath, patternLengthComparedToPathLength: patternLengthComparedToPathLength, containsWildcards: _containsWildcards, }); } else { return generateResult({ affectedByChild: true, pathToExtractData: pathPattern, patternLengthComparedToPathLength: patternLengthComparedToPathLength, containsWildcards: _containsWildcards, }); } } else if (pathPattern.startsWith(contentPath)) { // Pattern is longer then the path; // => A Change might be initated by // the super element // The PathToExtractData is allways false, if the path is smaller then the // pattern if (_containsWildcards) { return generateResult({ affectedByParent: true, patternToExtractData: pathPattern, patternLengthComparedToPathLength: patternLengthComparedToPathLength, containsWildcards: _containsWildcards, }); } else { return generateResult({ affectedByParent: true, // No Pattern is used. pathToExtractData: pathPattern, patternLengthComparedToPathLength: patternLengthComparedToPathLength, containsWildcards: _containsWildcards, }); } } } let partialPath = ""; // Iterate over the Segments. for (let i = 0; i < patternLength; i++) { // Store the current Pattern Segment const currentPattern = patternSegments[i]; // We need to know, if there is SINGLE_LEVEL_WILDCARD or MULTI_LEVEL_WILDCARD // there fore we will extract the Wildlevels. const patternChar = currentPattern[0]; const currentPath = contentPathSegments[i]; if (currentPath === undefined) { // Our Pattern is larger then our contentPath. // So we dont know, whether we will get some // data. Therefore we have to perform a query // later ==> Set The Path / Pattern. if (_containsWildcards) { // But we contain Patterns. // So we are not allowed to build a // diff object. return generateResult({ affectedByParent: true, patternToExtractData: pathPattern, patternLengthComparedToPathLength: patternLengthComparedToPathLength, containsWildcards: _containsWildcards, }); } else if (patternLengthComparedToPathLength === ">") { // Fixing: it is possible to have a longer return generateResult({ affectedByParent: true, pathToExtractData: pathPattern, patternLengthComparedToPathLength: patternLengthComparedToPathLength, containsWildcards: _containsWildcards, }); } else { throw Error("Implementation Error! This should not happen."); } } else if (currentPath == currentPattern) { // The Patterns Match // We now store the correct path of our segment. partialPath = partialPath.length > 0 ? `${partialPath}${exports.SEPARATOR}${currentPath}` : currentPath; } else if (patternChar === exports.MULTI_LEVEL_WILDCARD) { // We know, that MULTI_LEVEL_WILDCARDs are only at the end of the // pattern. So it might happen, that: // a) our length of the pattern is the same length as the content path // b) our length of the pattern is smaller then length as the content path // // Our statement before alread tested, that either case a) or b) fits. Otherwise // another ifstatement is valid and we wont enter this statement here. // // We add the segment to testedCorrectPath // testedCorrectPath = testedCorrectPath.length > 0 ? `${testedCorrectPath}${SEPARATOR}${currentPath}` : currentPath; if (patternLengthComparedToPathLength == "=") { // Case a) return generateResult({ affectedOnSameLevel: true, pathToExtractData: contentPath, patternLengthComparedToPathLength, containsWildcards: _containsWildcards, }); } else if (patternLengthComparedToPathLength == "<") { // Case b) return generateResult({ affectedByChild: true, pathToExtractData: contentPath, patternLengthComparedToPathLength, containsWildcards: _containsWildcards, }); } else { throw Error("Implementation Error!"); } } else if (patternChar === exports.SINGLE_LEVEL_WILDCARD) { // Store the correct path. partialPath = partialPath.length > 0 ? `${partialPath}${exports.SEPARATOR}${currentPath}` : currentPath; } else if (patternChar !== exports.SINGLE_LEVEL_WILDCARD && currentPattern !== currentPath) { return generateResult({ patternLengthComparedToPathLength: patternLengthComparedToPathLength, containsWildcards: _containsWildcards, }); } } const diff = contentPath.slice(partialPath.length + 1); return generateResult({ affectedOnSameLevel: diff.length == 0, affectedByChild: diff.length >= 1, pathToExtractData: partialPath, patternLengthComparedToPathLength, containsWildcards: _containsWildcards, }); } exports.comparePatternAndPath = comparePatternAndPath; /** * Determines, whether the given string contains a single level card or not. * * @author M.Karkowski * @export * @param {string} str String to check * @return {*} {boolean} */ function containsWildcards(str) { return (str.includes(exports.SINGLE_LEVEL_WILDCARD) || str.includes(exports.MULTI_LEVEL_WILDCARD)); } exports.containsWildcards = containsWildcards; /** * Function to test if a pattern is valid * * * @author M.Karkowski * @export * @param {string} str * @return {*} {boolean} */ function patternIsValid(str) { if (str === "") { return true; } const splitted = str.split(objectMethods_1.SPLITCHAR); const lastIndex = splitted.length - 1; return splitted .map((value, idx) => { if (value) { if (value === exports.MULTI_LEVEL_WILDCARD) { return idx === lastIndex; } return true; } return false; }) .reduce((prev, current) => { return prev && current; }, true); } exports.patternIsValid = patternIsValid;