UNPKG

netconf-client

Version:
114 lines 4.07 kB
/** * Finds the first object in the object hierarchy that matches the key * @param obj - The object to search * @param key - The key to search for * * @returns The object, wrapping the first object that matches the key, if found only one such object, * or the number of objects found, if there are multiple or none. */ function findDeep(obj, key, currentDepth = 1) { if (typeof obj !== 'object' || obj === null) return 0; if (Object.prototype.hasOwnProperty.call(obj, key)) { return { found: { [key]: obj[key] }, depth: currentDepth }; } let nFound = 0; let ret; for (const k of Object.keys(obj)) { if (Array.isArray(obj[k])) { ret = { found: { [k]: obj[k] }, key: k, depth: currentDepth + 1 }; nFound++; break; } const found = findDeep(obj[k], key, currentDepth + 1); if (typeof found === 'object') { nFound++; ret = found; } } if (nFound === 1) return ret ?? 0; return nFound; } /** * Cleans the XPath string to make it easier to parse * @param xpath - The XPath string to clean * @returns The cleaned XPath string */ function cleanXPath(xpath) { // convert wildcard to * xpath = xpath.replace(/\/\//g, '/*/'); // merge */* into * xpath = xpath.replace(/\*\/\*/g, '*'); // remove leading / xpath = xpath.replace(/^\/+/, ''); // remove any predicates/matching square brackets from the xpath const regExp = /\[[^[\]]*]/; while (regExp.test(xpath)) { xpath = xpath.replace(regExp, ''); } return xpath; } /** * The function will return the requested object by stripping the parent objects from the object returned from * the Netconf,matching the XPath, leaving only the last object. Therefore the actual object is returned without * the root path. For example, if XPath is //aaa//user[name="admin"]/homedir, the function will return the object * that contains the homedir value: * { * homedir: '/home/admin' * } * * @param {object} obj - Config object returned by Netconf when queried with XPath filter * @param {string} xpath - XPath string * @returns The object stripped of the XPath tokens, that is if XPath is /aaa/authentication/users/user[name="admin"]/homedir, * the function will return the object that contains the homedir value */ // eslint-disable-next-line sonarjs/cognitive-complexity export function resolveXPath(obj, xpath) { if (obj === undefined) return undefined; if (xpath.includes('|')) return obj; xpath = cleanXPath(xpath); if (!xpath) return obj; const pathParts = xpath.split('/'); let current = obj; let lastKey = null; let lastResolved = obj; let isDeep = false; let depth = 0; for (const part of pathParts) { if (part === '*') { isDeep = true; continue; } if (isDeep) { const found = findDeep(current, part, depth + 1); if (typeof found === 'number') { return depth === 1 ? obj : lastKey ? { [lastKey]: lastResolved } : obj; } current = found.found[found.key ?? part]; lastKey = found.key ?? part; lastResolved = current; isDeep = false; depth = found.depth; continue; } if (typeof current === 'object' && current !== null && current.hasOwnProperty(part)) { lastKey = part; lastResolved = current[part]; current = current[part]; } else { return depth === 1 ? obj : lastKey ? { [lastKey]: lastResolved } : obj; } depth++; } // Handle the case where the last part is a wildcard if (pathParts[pathParts.length - 1] === '*' && lastKey && typeof lastResolved === 'object' && lastResolved !== null) { return lastResolved; } return depth === 1 ? obj : lastKey ? { [lastKey]: lastResolved } : obj; } //# sourceMappingURL=resolve-xpath.js.map