UNPKG

reselect-tree

Version:

Wrapper around reselect for creating selector trees

315 lines (273 loc) 23.2 kB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define("reselect-tree", [], factory); else if(typeof exports === 'object') exports["reselect-tree"] = factory(); else root["reselect-tree"] = factory(); })(typeof self !== 'undefined' ? self : this, function() { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ } /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); /* harmony export (immutable) */ __webpack_exports__["createNestedSelector"] = createNestedSelector; /* harmony export (immutable) */ __webpack_exports__["createLeaf"] = createLeaf; /* harmony export (immutable) */ __webpack_exports__["createSelectorTree"] = createSelectorTree; const debugModule = __webpack_require__( 1); const debug = debugModule("reselect-tree"); const { createSelector, createStructuredSelector } = __webpack_require__(2); const jsonpointer = __webpack_require__(3); /** * Create a single memoized selector for a collection of named sub-selectors. * Behaves like `createStructuredSelector` but also allows direct invocation * of child selectors. * * For example: * * const shop = createNestedSelector({ * items: (state) => state.items, * promos: (state) => state.promos * }); * * Results in three selectors: * * shop(state) ==> { items: state.items, promos: state.items } * shop.items(state) => state.items * shop.promos(state) => state.promos * * Override `rootSelector` to change behavior of top-level (i.e. `shop(state)` * in example.) * * @param {Object} selectors - object description of selector funcs * @param {Selector} rootSelector - specify root selector instead of aggregation * @return Selector */ function createNestedSelector (selectors, rootSelector = null) { let selector; if (!rootSelector) { // unspecified means default to structured aggregation selector = createStructuredSelector(selectors); } else if (!(rootSelector instanceof Object) || !rootSelector.resultFunc) { // rootSelector isn't already a selector, or it's not an object... // forward to `createSelector()` selector = createSelector(rootSelector); } else { // otherwise, just use as is selector = rootSelector; } // add properties for child selectors Object.keys(selectors).forEach( (prop) => { selector[prop] = selectors[prop]; }); return selector; } class Leaf { constructor(deps, selector) { this.deps = deps; this.selector = selector; } contextualize(resolve, pointer) { let resolved = this.deps .map( (dep) => { if (typeof dep == 'string') { if (dep == "") { dep = "/"; } const abspath = _resolvePointer(pointer, "..", dep); debug("pointer %o", pointer); debug("abspath %o", abspath); return (...args) => { debug("args: %o", args); let selector = resolve(abspath); debug("resolved selector: %o", selector); if(!selector) { throw new Error( `Error: Cannot resolve dep ${dep} on ${pointer}` ); } let result = selector.apply(selector, args); debug("result: %o", result); return result; } } return dep; }); return createSelector(resolved, this.selector); } } function createLeaf(deps, selector) { return new Leaf(deps, selector); } class Tree { setRoot(root) { this.root = root; } resolve(abspath) { var resolved; try { let parsed = jsonpointer.parse(abspath); let cur = this.root; for (let step of parsed) { cur = cur[step]; } return cur; } catch (e) { debug("failed, root: %O", this.root); throw e; } return resolved; } } function createSelectorTree (root) { let tree = new Tree(); let selector = _createNode(root, tree.resolve.bind(tree), ""); tree.setRoot(selector); return selector; } /** * Recursively create a selector node in the tree, applying context to nodes * as needed. */ function _createNode(node, resolve, pointer = "") { //based on type of node, operate differently if (node instanceof Function) { // plain functions are converted to contextualized Leaf nodes return createLeaf([state => state], node).contextualize(resolve, pointer); } else if (node instanceof Leaf) { // explicit leaf nodes just need context resolution for relative deps return node.contextualize(resolve, pointer); } else if (node instanceof Object) { // otherwise, node is an object, so recurse const recurse = (key, child) => _createNode(child, resolve, `${pointer}/${key}`); let selectors = Object.assign({}, ...Object.entries(node) .map( ([key, child]) => ({ [key]: recurse(key, child) }) ) ); // special-case `_` child nodes override root selector const rootSelector = selectors._ || null; return createNestedSelector(selectors, rootSelector); } else { // other types are not allowed throw new Error( `Invalid node in selector tree at ${pointer}. ` + `Must be function, leaf, or object. Received: ${node}` ); } } /** * Behaves like path.posix.resolve(), ensuring the returned string is a * /-separated string with no ".." or ".". * * Later absolute entries in `paths` (i.e., items that start with `/`) * supercede previous entries. */ function _resolvePointer(...paths) { return paths // reduce to /-separated string, ignoring anything before the last- // specified absolute path (e.g. ["/a", "/b", "./c"] becomes "/b/./c") .reduce((joined, next) => { // next child is absolute; discard previous if (next.startsWith("/")) { return next; } return `${joined}/${next}`; }, "") // now, remove .. and . .split("/") .reduce((resolved, next) => { switch (next) { case "..": return resolved.slice(0, -1); case ".": return resolved; default: return resolved.concat(next); } }, []) .join("/"); } /***/ }), /* 1 */ /***/ (function(module, exports) { module.exports = require("debug"); /***/ }), /* 2 */ /***/ (function(module, exports) { module.exports = require("reselect"); /***/ }), /* 3 */ /***/ (function(module, exports) { module.exports = require("json-pointer"); /***/ }) /******/ ]); }); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VzIjpbIndlYnBhY2svdW5pdmVyc2FsTW9kdWxlRGVmaW5pdGlvbiIsIndlYnBhY2svYm9vdHN0cmFwIDdmYTY0MTYwMWViNGU1NGZlMzYwIiwiL2hvbWUvc25pZmZub3kvdHJ1ZmZsZS9yZXNlbGVjdC10cmVlL2xpYi9pbmRleC5qcyIsImV4dGVybmFsIFwiZGVidWdcIiIsImV4dGVybmFsIFwicmVzZWxlY3RcIiIsImV4dGVybmFsIFwianNvbi1wb2ludGVyXCIiXSwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIHdlYnBhY2tVbml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uKHJvb3QsIGZhY3RvcnkpIHtcblx0aWYodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnKVxuXHRcdG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSgpO1xuXHRlbHNlIGlmKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZClcblx0XHRkZWZpbmUoXCJyZXNlbGVjdC10cmVlXCIsIFtdLCBmYWN0b3J5KTtcblx0ZWxzZSBpZih0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcpXG5cdFx0ZXhwb3J0c1tcInJlc2VsZWN0LXRyZWVcIl0gPSBmYWN0b3J5KCk7XG5cdGVsc2Vcblx0XHRyb290W1wicmVzZWxlY3QtdHJlZVwiXSA9IGZhY3RvcnkoKTtcbn0pKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJyA/IHNlbGYgOiB0aGlzLCBmdW5jdGlvbigpIHtcbnJldHVybiBcblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gd2VicGFjay91bml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uIiwiIFx0Ly8gVGhlIG1vZHVsZSBjYWNoZVxuIFx0dmFyIGluc3RhbGxlZE1vZHVsZXMgPSB7fTtcblxuIFx0Ly8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbiBcdGZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblxuIFx0XHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcbiBcdFx0aWYoaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0pIHtcbiBcdFx0XHRyZXR1cm4gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0uZXhwb3J0cztcbiBcdFx0fVxuIFx0XHQvLyBDcmVhdGUgYSBuZXcgbW9kdWxlIChhbmQgcHV0IGl0IGludG8gdGhlIGNhY2hlKVxuIFx0XHR2YXIgbW9kdWxlID0gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0gPSB7XG4gXHRcdFx0aTogbW9kdWxlSWQsXG4gXHRcdFx0bDogZmFsc2UsXG4gXHRcdFx0ZXhwb3J0czoge31cbiBcdFx0fTtcblxuIFx0XHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cbiBcdFx0bW9kdWxlc1ttb2R1bGVJZF0uY2FsbChtb2R1bGUuZXhwb3J0cywgbW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cbiBcdFx0Ly8gRmxhZyB0aGUgbW9kdWxlIGFzIGxvYWRlZFxuIFx0XHRtb2R1bGUubCA9IHRydWU7XG5cbiBcdFx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcbiBcdFx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xuIFx0fVxuXG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlcyBvYmplY3QgKF9fd2VicGFja19tb2R1bGVzX18pXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm0gPSBtb2R1bGVzO1xuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZSBjYWNoZVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5jID0gaW5zdGFsbGVkTW9kdWxlcztcblxuIFx0Ly8gZGVmaW5lIGdldHRlciBmdW5jdGlvbiBmb3IgaGFybW9ueSBleHBvcnRzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSBmdW5jdGlvbihleHBvcnRzLCBuYW1lLCBnZXR0ZXIpIHtcbiBcdFx0aWYoIV9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBuYW1lKSkge1xuIFx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBuYW1lLCB7XG4gXHRcdFx0XHRjb25maWd1cmFibGU6IGZhbHNlLFxuIFx0XHRcdFx0ZW51bWVyYWJsZTogdHJ1ZSxcbiBcdFx0XHRcdGdldDogZ2V0dGVyXG4gXHRcdFx0fSk7XG4gXHRcdH1cbiBcdH07XG5cbiBcdC8vIGdldERlZmF1bHRFeHBvcnQgZnVuY3Rpb24gZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBub24taGFybW9ueSBtb2R1bGVzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm4gPSBmdW5jdGlvbihtb2R1bGUpIHtcbiBcdFx0dmFyIGdldHRlciA9IG1vZHVsZSAmJiBtb2R1bGUuX19lc01vZHVsZSA/XG4gXHRcdFx0ZnVuY3Rpb24gZ2V0RGVmYXVsdCgpIHsgcmV0dXJuIG1vZHVsZVsnZGVmYXVsdCddOyB9IDpcbiBcdFx0XHRmdW5jdGlvbiBnZXRNb2R1bGVFeHBvcnRzKCkgeyByZXR1cm4gbW9kdWxlOyB9O1xuIFx0XHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQoZ2V0dGVyLCAnYScsIGdldHRlcik7XG4gXHRcdHJldHVybiBnZXR0ZXI7XG4gXHR9O1xuXG4gXHQvLyBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGxcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubyA9IGZ1bmN0aW9uKG9iamVjdCwgcHJvcGVydHkpIHsgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIHByb3BlcnR5KTsgfTtcblxuIFx0Ly8gX193ZWJwYWNrX3B1YmxpY19wYXRoX19cbiBcdF9fd2VicGFja19yZXF1aXJlX18ucCA9IFwiXCI7XG5cbiBcdC8vIExvYWQgZW50cnkgbW9kdWxlIGFuZCByZXR1cm4gZXhwb3J0c1xuIFx0cmV0dXJuIF9fd2VicGFja19yZXF1aXJlX18oX193ZWJwYWNrX3JlcXVpcmVfXy5zID0gMCk7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gd2VicGFjay9ib290c3RyYXAgN2ZhNjQxNjAxZWI0ZTU0ZmUzNjAiLCJjb25zdCBkZWJ1Z01vZHVsZSA9IHJlcXVpcmUoIFwiZGVidWdcIik7XG5jb25zdCBkZWJ1ZyA9IGRlYnVnTW9kdWxlKFwicmVzZWxlY3QtdHJlZVwiKTtcblxuY29uc3QgeyBjcmVhdGVTZWxlY3RvciwgY3JlYXRlU3RydWN0dXJlZFNlbGVjdG9yIH0gPSByZXF1aXJlKFwicmVzZWxlY3RcIik7XG5jb25zdCBqc29ucG9pbnRlciA9IHJlcXVpcmUoXCJqc29uLXBvaW50ZXJcIik7XG5cbi8qKlxuICogQ3JlYXRlIGEgc2luZ2xlIG1lbW9pemVkIHNlbGVjdG9yIGZvciBhIGNvbGxlY3Rpb24gb2YgbmFtZWQgc3ViLXNlbGVjdG9ycy5cbiAqIEJlaGF2ZXMgbGlrZSBgY3JlYXRlU3RydWN0dXJlZFNlbGVjdG9yYCBidXQgYWxzbyBhbGxvd3MgZGlyZWN0IGludm9jYXRpb25cbiAqIG9mIGNoaWxkIHNlbGVjdG9ycy5cbiAqXG4gKiBGb3IgZXhhbXBsZTpcbiAqXG4gKiAgIGNvbnN0IHNob3AgPSBjcmVhdGVOZXN0ZWRTZWxlY3Rvcih7XG4gKiAgICAgaXRlbXM6IChzdGF0ZSkgPT4gc3RhdGUuaXRlbXMsXG4gKiAgICAgcHJvbW9zOiAoc3RhdGUpID0+IHN0YXRlLnByb21vc1xuICogICB9KTtcbiAqXG4gKiBSZXN1bHRzIGluIHRocmVlIHNlbGVjdG9yczpcbiAqXG4gKiAgIHNob3Aoc3RhdGUpID09PiB7IGl0ZW1zOiBzdGF0ZS5pdGVtcywgcHJvbW9zOiBzdGF0ZS5pdGVtcyB9XG4gKiAgIHNob3AuaXRlbXMoc3RhdGUpID0+IHN0YXRlLml0ZW1zXG4gKiAgIHNob3AucHJvbW9zKHN0YXRlKSA9PiBzdGF0ZS5wcm9tb3NcbiAqXG4gKiBPdmVycmlkZSBgcm9vdFNlbGVjdG9yYCB0byBjaGFuZ2UgYmVoYXZpb3Igb2YgdG9wLWxldmVsIChpLmUuIGBzaG9wKHN0YXRlKWBcbiAqIGluIGV4YW1wbGUuKVxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBzZWxlY3RvcnMgLSBvYmplY3QgZGVzY3JpcHRpb24gb2Ygc2VsZWN0b3IgZnVuY3NcbiAqIEBwYXJhbSB7U2VsZWN0b3J9IHJvb3RTZWxlY3RvciAtIHNwZWNpZnkgcm9vdCBzZWxlY3RvciBpbnN0ZWFkIG9mIGFnZ3JlZ2F0aW9uXG4gKiBAcmV0dXJuIFNlbGVjdG9yXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVOZXN0ZWRTZWxlY3RvciAoc2VsZWN0b3JzLCByb290U2VsZWN0b3IgPSBudWxsKSB7XG4gIGxldCBzZWxlY3RvcjtcblxuICBpZiAoIXJvb3RTZWxlY3Rvcikge1xuICAgIC8vIHVuc3BlY2lmaWVkIG1lYW5zIGRlZmF1bHQgdG8gc3RydWN0dXJlZCBhZ2dyZWdhdGlvblxuICAgIHNlbGVjdG9yID0gY3JlYXRlU3RydWN0dXJlZFNlbGVjdG9yKHNlbGVjdG9ycyk7XG5cbiAgfSBlbHNlIGlmICghKHJvb3RTZWxlY3RvciBpbnN0YW5jZW9mIE9iamVjdCkgfHwgIXJvb3RTZWxlY3Rvci5yZXN1bHRGdW5jKSB7XG4gICAgLy8gcm9vdFNlbGVjdG9yIGlzbid0IGFscmVhZHkgYSBzZWxlY3Rvciwgb3IgaXQncyBub3QgYW4gb2JqZWN0Li4uXG4gICAgLy8gZm9yd2FyZCB0byBgY3JlYXRlU2VsZWN0b3IoKWBcbiAgICBzZWxlY3RvciA9IGNyZWF0ZVNlbGVjdG9yKHJvb3RTZWxlY3Rvcik7XG4gIH0gZWxzZSB7XG4gICAgLy8gb3RoZXJ3aXNlLCBqdXN0IHVzZSBhcyBpc1xuICAgIHNlbGVjdG9yID0gcm9vdFNlbGVjdG9yO1xuICB9XG5cbiAgLy8gYWRkIHByb3BlcnRpZXMgZm9yIGNoaWxkIHNlbGVjdG9yc1xuICBPYmplY3Qua2V5cyhzZWxlY3RvcnMpLmZvckVhY2goIChwcm9wKSA9PiB7XG4gICAgc2VsZWN0b3JbcHJvcF0gPSBzZWxlY3RvcnNbcHJvcF07XG4gIH0pO1xuXG4gIHJldHVybiBzZWxlY3Rvcjtcbn1cblxuY2xhc3MgTGVhZiB7XG4gIGNvbnN0cnVjdG9yKGRlcHMsIHNlbGVjdG9yKSB7XG4gICAgdGhpcy5kZXBzID0gZGVwcztcbiAgICB0aGlzLnNlbGVjdG9yID0gc2VsZWN0b3I7XG4gIH1cblxuICBjb250ZXh0dWFsaXplKHJlc29sdmUsIHBvaW50ZXIpIHtcbiAgICBsZXQgcmVzb2x2ZWQgPSB0aGlzLmRlcHNcbiAgICAgIC5tYXAoIChkZXApID0+IHtcbiAgICAgICAgaWYgKHR5cGVvZiBkZXAgPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBpZiAoZGVwID09IFwiXCIpIHtcbiAgICAgICAgICAgIGRlcCA9IFwiL1wiO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGFic3BhdGggPSBfcmVzb2x2ZVBvaW50ZXIocG9pbnRlciwgXCIuLlwiLCBkZXApO1xuICAgICAgICAgIGRlYnVnKFwicG9pbnRlciAlb1wiLCBwb2ludGVyKTtcbiAgICAgICAgICBkZWJ1ZyhcImFic3BhdGggJW9cIiwgYWJzcGF0aCk7XG5cbiAgICAgICAgICByZXR1cm4gKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgICAgIGRlYnVnKFwiYXJnczogJW9cIiwgYXJncyk7XG4gICAgICAgICAgICBsZXQgc2VsZWN0b3IgPSByZXNvbHZlKGFic3BhdGgpO1xuICAgICAgICAgICAgZGVidWcoXCJyZXNvbHZlZCBzZWxlY3RvcjogJW9cIiwgc2VsZWN0b3IpO1xuICAgICAgICAgICAgaWYoIXNlbGVjdG9yKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICBgRXJyb3I6IENhbm5vdCByZXNvbHZlIGRlcCAke2RlcH0gb24gJHtwb2ludGVyfWBcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCByZXN1bHQgPSBzZWxlY3Rvci5hcHBseShzZWxlY3RvciwgYXJncyk7XG4gICAgICAgICAgICBkZWJ1ZyhcInJlc3VsdDogJW9cIiwgcmVzdWx0KTtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGRlcDtcbiAgICAgIH0pO1xuXG4gICAgcmV0dXJuIGNyZWF0ZVNlbGVjdG9yKHJlc29sdmVkLCB0aGlzLnNlbGVjdG9yKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlTGVhZihkZXBzLCBzZWxlY3Rvcikge1xuICByZXR1cm4gbmV3IExlYWYoZGVwcywgc2VsZWN0b3IpO1xufVxuXG5jbGFzcyBUcmVlIHtcbiAgc2V0Um9vdChyb290KSB7XG4gICAgdGhpcy5yb290ID0gcm9vdDtcbiAgfVxuXG4gIHJlc29sdmUoYWJzcGF0aCkge1xuICAgIHZhciByZXNvbHZlZDtcbiAgICB0cnkge1xuICAgICAgbGV0IHBhcnNlZCA9IGpzb25wb2ludGVyLnBhcnNlKGFic3BhdGgpO1xuXG4gICAgICBsZXQgY3VyID0gdGhpcy5yb290O1xuICAgICAgZm9yIChsZXQgc3RlcCBvZiBwYXJzZWQpIHtcbiAgICAgICAgY3VyID0gY3VyW3N0ZXBdO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gY3VyO1xuXG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgZGVidWcoXCJmYWlsZWQsIHJvb3Q6ICVPXCIsIHRoaXMucm9vdCk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiByZXNvbHZlZDtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU2VsZWN0b3JUcmVlIChyb290KSB7XG4gIGxldCB0cmVlID0gbmV3IFRyZWUoKTtcblxuICBsZXQgc2VsZWN0b3IgPSBfY3JlYXRlTm9kZShyb290LCB0cmVlLnJlc29sdmUuYmluZCh0cmVlKSwgXCJcIik7XG5cbiAgdHJlZS5zZXRSb290KHNlbGVjdG9yKTtcblxuICByZXR1cm4gc2VsZWN0b3I7XG59XG5cbi8qKlxuICogUmVjdXJzaXZlbHkgY3JlYXRlIGEgc2VsZWN0b3Igbm9kZSBpbiB0aGUgdHJlZSwgYXBwbHlpbmcgY29udGV4dCB0byBub2Rlc1xuICogYXMgbmVlZGVkLlxuICovXG5mdW5jdGlvbiBfY3JlYXRlTm9kZShub2RlLCByZXNvbHZlLCBwb2ludGVyID0gXCJcIikge1xuICAvL2Jhc2VkIG9uIHR5cGUgb2Ygbm9kZSwgb3BlcmF0ZSBkaWZmZXJlbnRseVxuICBpZiAobm9kZSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgLy8gcGxhaW4gZnVuY3Rpb25zIGFyZSBjb252ZXJ0ZWQgdG8gY29udGV4dHVhbGl6ZWQgTGVhZiBub2Rlc1xuICAgIHJldHVybiBjcmVhdGVMZWFmKFtzdGF0ZSA9PiBzdGF0ZV0sIG5vZGUpLmNvbnRleHR1YWxpemUocmVzb2x2ZSwgcG9pbnRlcik7XG5cbiAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgTGVhZikge1xuICAgIC8vIGV4cGxpY2l0IGxlYWYgbm9kZXMganVzdCBuZWVkIGNvbnRleHQgcmVzb2x1dGlvbiBmb3IgcmVsYXRpdmUgZGVwc1xuICAgIHJldHVybiBub2RlLmNvbnRleHR1YWxpemUocmVzb2x2ZSwgcG9pbnRlcik7XG5cbiAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgT2JqZWN0KSB7XG4gICAgLy8gb3RoZXJ3aXNlLCBub2RlIGlzIGFuIG9iamVjdCwgc28gcmVjdXJzZVxuICAgIGNvbnN0IHJlY3Vyc2UgPVxuICAgICAgKGtleSwgY2hpbGQpID0+IF9jcmVhdGVOb2RlKGNoaWxkLCByZXNvbHZlLCBgJHtwb2ludGVyfS8ke2tleX1gKTtcblxuICAgIGxldCBzZWxlY3RvcnMgPSBPYmplY3QuYXNzaWduKHt9LFxuICAgICAgLi4uT2JqZWN0LmVudHJpZXMobm9kZSlcbiAgICAgICAgLm1hcCggKFtrZXksIGNoaWxkXSkgPT4gKHsgW2tleV06IHJlY3Vyc2Uoa2V5LCBjaGlsZCkgfSkgKVxuICAgICk7XG5cbiAgICAvLyBzcGVjaWFsLWNhc2UgYF9gIGNoaWxkIG5vZGVzIG92ZXJyaWRlIHJvb3Qgc2VsZWN0b3JcbiAgICBjb25zdCByb290U2VsZWN0b3IgPSBzZWxlY3RvcnMuXyB8fCBudWxsO1xuXG4gICAgcmV0dXJuIGNyZWF0ZU5lc3RlZFNlbGVjdG9yKHNlbGVjdG9ycywgcm9vdFNlbGVjdG9yKTtcblxuICB9IGVsc2Uge1xuICAgIC8vIG90aGVyIHR5cGVzIGFyZSBub3QgYWxsb3dlZFxuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBJbnZhbGlkIG5vZGUgaW4gc2VsZWN0b3IgdHJlZSBhdCAke3BvaW50ZXJ9LiBgICtcbiAgICAgIGBNdXN0IGJlIGZ1bmN0aW9uLCBsZWFmLCBvciBvYmplY3QuIFJlY2VpdmVkOiAke25vZGV9YFxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBCZWhhdmVzIGxpa2UgcGF0aC5wb3NpeC5yZXNvbHZlKCksIGVuc3VyaW5nIHRoZSByZXR1cm5lZCBzdHJpbmcgaXMgYVxuICogLy1zZXBhcmF0ZWQgc3RyaW5nIHdpdGggbm8gXCIuLlwiIG9yIFwiLlwiLlxuICpcbiAqIExhdGVyIGFic29sdXRlIGVudHJpZXMgaW4gYHBhdGhzYCAoaS5lLiwgaXRlbXMgdGhhdCBzdGFydCB3aXRoIGAvYClcbiAqIHN1cGVyY2VkZSBwcmV2aW91cyBlbnRyaWVzLlxuICovXG5mdW5jdGlvbiBfcmVzb2x2ZVBvaW50ZXIoLi4ucGF0aHMpIHtcbiAgcmV0dXJuIHBhdGhzXG4gICAgLy8gcmVkdWNlIHRvIC8tc2VwYXJhdGVkIHN0cmluZywgaWdub3JpbmcgYW55dGhpbmcgYmVmb3JlIHRoZSBsYXN0LVxuICAgIC8vIHNwZWNpZmllZCBhYnNvbHV0ZSBwYXRoIChlLmcuIFtcIi9hXCIsIFwiL2JcIiwgXCIuL2NcIl0gYmVjb21lcyBcIi9iLy4vY1wiKVxuICAgIC5yZWR1Y2UoKGpvaW5lZCwgbmV4dCkgPT4ge1xuICAgICAgLy8gbmV4dCBjaGlsZCBpcyBhYnNvbHV0ZTsgZGlzY2FyZCBwcmV2aW91c1xuICAgICAgaWYgKG5leHQuc3RhcnRzV2l0aChcIi9cIikpIHtcbiAgICAgICAgcmV0dXJuIG5leHQ7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBgJHtqb2luZWR9LyR7bmV4dH1gO1xuICAgIH0sIFwiXCIpXG5cbiAgICAvLyBub3csIHJlbW92ZSAuLiBhbmQgLlxuICAgIC5zcGxpdChcIi9cIilcbiAgICAucmVkdWNlKChyZXNvbHZlZCwgbmV4dCkgPT4ge1xuICAgICAgc3dpdGNoIChuZXh0KSB7XG4gICAgICAgIGNhc2UgXCIuLlwiOlxuICAgICAgICAgIHJldHVybiByZXNvbHZlZC5zbGljZSgwLCAtMSk7XG4gICAgICAgIGNhc2UgXCIuXCI6XG4gICAgICAgICAgcmV0dXJuIHJlc29sdmVkO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHJldHVybiByZXNvbHZlZC5jb25jYXQobmV4dCk7XG4gICAgICB9XG4gICAgfSwgW10pXG4gICAgLmpvaW4oXCIvXCIpO1xufVxuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9saWIvaW5kZXguanNcbi8vIG1vZHVsZSBpZCA9IDBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwiZGVidWdcIik7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gZXh0ZXJuYWwgXCJkZWJ1Z1wiXG4vLyBtb2R1bGUgaWQgPSAxXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcInJlc2VsZWN0XCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwicmVzZWxlY3RcIlxuLy8gbW9kdWxlIGlkID0gMlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJqc29uLXBvaW50ZXJcIik7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gZXh0ZXJuYWwgXCJqc29uLXBvaW50ZXJcIlxuLy8gbW9kdWxlIGlkID0gM1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNWQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7OztBQzdEQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7OztBQzlNQTs7Ozs7O0FDQUE7Ozs7OztBQ0FBOzs7O0EiLCJzb3VyY2VSb290IjoiIn0=