reselect-tree
Version:
Wrapper around reselect for creating selector trees
315 lines (273 loc) • 23.2 kB
JavaScript
(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__) {
;
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=