chain-able
Version:
interfaces that describe their intentions.
408 lines (376 loc) • 32.8 kB
JavaScript
var Iterator = require('./deps/symbols/iterator')
var Instance = require('./deps/symbols/instance')
var Primitive = require('./deps/symbols/primitive')
var isPrototypeOf = require('./deps/is/prototypeOf')
var isMap = require('./deps/is/map')
var isSet = require('./deps/is/set')
var isUndefined = require('./deps/is/undefined')
var isFunction = require('./deps/is/function')
var isString = require('./deps/is/string')
var isFalse = require('./deps/is/false')
var ObjectKeys = require('./deps/util/keys')
var ObjectDefine = require('./deps/define')
var ignored = require('./deps/ignored')
var ENV_DEVELOPMENT = require('./deps/env/dev')
var shouldClear = function (key, property) { return !ignored(key) &&
(isMap(property) || isSet(property) || (property && property.store)); }
var C = function (SuperClass) {
/* istanbul ignore next: dev */
if (ENV_DEVELOPMENT) {
if (!SuperClass || !SuperClass.prototype) {
console.log({SuperClass: SuperClass})
throw new TypeError('did not have a super class / target base')
}
}
/**
* @desc Trait class that can inherit any class passed into compose, extended by ChainedMap & ChainedSet
*
* @member Chainable
* @class Chainable
* @category Chainable
* @type {Chainable}
*
* @prop {Chainable | any} parent
* @prop {string} className
*
* {@link https://github.com/iluwatar/java-design-patterns/tree/master/chain chain-pattern}
* @see {@link chain-pattern}
*
* @see ChainedMap
* @see ChainedSet
*
* @tests Chainable
* @types Chainable
*/
var Chainable = (function (SuperClass) {
function Chainable(parent) {
SuperClass.call(this)
if (parent) { this.parent = parent }
this.className = this.constructor.name
}
if ( SuperClass ) Chainable.__proto__ = SuperClass;
Chainable.prototype = Object.create( SuperClass && SuperClass.prototype );
Chainable.prototype.constructor = Chainable;
/**
* @desc Iterator for looping values in the store
*
* @since 0.5.0
* @see this.store
* @type {generator}
* @return {Object} {value: undefined | any, done: true | false}
*
* @NOTE assigned to a variable so buble ignores it
* @see https://github.com/sindresorhus/quick-lru/blob/master/index.js
* @see https://stackoverflow.com/questions/36976832/what-is-the-meaning-of-symbol-iterator-in-this-context
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator
* @tests iteration
*
* @example
*
* const chain = new Chain().set('eh', 1)
* for (var [key, val] of chain) console.log({[key]: val})
* //=> {eh: 1}
*
* @example
*
* *[Symbol.iterator](): void { for (const item of this.store) yield item }
*
* @example
*
* const {ChainedSet} = require('chain-able')
* const set = new ChainedSet()
* set.add('eh')
*
* for (const arr of set) {
* const [key, val] = arr
*
* key
* //=> 0
*
* val
* //=> 'eh'
*
* arr.length
* //=> 2
* }
*
*/
Chainable.prototype[Iterator] = function () {
var values = this.values()
var size = this.store.size
var entries = this.entries ? this.entries() : 0
var keys = entries === 0 ? new Array(size) : ObjectKeys(entries)
return {
i: 0,
next: function next() {
var i = this.i
var key = i
var val = values[i]
if (entries) { key = keys[i] }
// done - no more values, or iteration reached size
if ((isUndefined(key) && isUndefined(val)) || size <= i) {
return {value: undefined, done: true}
}
this.i++
// return
return {value: [key, val], done: false}
},
}
};
/**
* @desc for ending nested chains
* @since 0.4.0
* @return {Chainable | any}
* @see Chainable.parent
* @see FactoryChain
*
* @example
*
* const parent = 'eh'
* const child = newChain(parent)
* child.end()
* //=> 'eh'
*
*/
Chainable.prototype.end = function end () {
return this.parent
};
/**
* @desc when the condition is true,
* trueBrancher is called,
* else, falseBrancher is called
*
* @since 4.0.0 <- added string-as-has(condition)
* @since 2.0.0
*
* @param {boolean | string} condition when string, checks this.get
* @param {Function} [trueBrancher=Function] called when true
* @param {Function} [falseBrancher=Function] called when false
* @return {Chainable} @chainable
*
* @example
*
*
* const prod = process.env.NODE_ENV === 'production'
* chains.when(prod, c => c.set('prod', true), c => c.set('prod', false))
*
*
*/
Chainable.prototype.when = function when (condition, trueBrancher, falseBrancher) {
if (condition) {
if (isFunction(trueBrancher)) {
if (isString(condition)) {
if (this.get(condition)) {
trueBrancher(this)
}
}
else {
trueBrancher(this)
}
}
}
else if (isFunction(falseBrancher)) {
falseBrancher(this)
}
return this
};
/**
* @desc clears the map,
* goes through this properties,
* calls .clear if they are instanceof Chainable or Map
*
* @since 4.0.0 (moved only to Chainable, added option to clear this keys)
* @since 0.4.0 (in ChainedMap)
* @since 0.3.0 (in Chainable)
*
* @param {boolean | undefined} [clearPropertiesThatAreChainLike=true] checks properties on the object, if they are `chain-like`, clears them as well
* @return {Chainable} @chainable
*
* @see https://github.com/fliphub/flipchain/issues/2
* @see ChainedSet
* @see ChainedMap
*
* @example
*
* const chain = new Chain()
* chain.set('eh', 1)
* chain.entries()
* //=> {eh: 1}
* chain.clear()
* chain.entries()
* //=> {}
*
*/
Chainable.prototype.clear = function clear (clearPropertiesThatAreChainLike) {
var this$1 = this;
this.store.clear()
if (isFalse(clearPropertiesThatAreChainLike)) { return this }
var keys = ObjectKeys(this)
for (var k = 0; k < keys.length; k++) {
var key = keys[k]
var property = this$1[key]
if (shouldClear(key, property)) { this$1[key].clear() }
}
return this
};
/**
* @desc calls .delete on this.store.map
* @since 0.3.0
*
* @param {Primitive} key on a Map: key referencing the value. on a Set: the index
* @return {Chainable}
*
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/has
* @see ChainedSet
* @see ChainedMap
*
* @example
*
* const chain = new Chain()
* chain.set('eh', 1)
* chain.get('eh')
* // => 1
* chain.delete('eh', 1)
* chain.get('eh')
* // => undefined
*
*/
Chainable.prototype.delete = function delete$1 (key) {
this.store.delete(key)
return this
};
/**
* @since 0.3.0
* @param {any} keyOrValue key when Map, value when Set
* @return {boolean}
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has
*
* @example
*
* const chain = new Chain()
* chain.set('eh', 1).has('eh')
* //=> true
* chain.has('canada')
* //=> false
*
*/
Chainable.prototype.has = function has (keyOrValue) {
return this.store.has(keyOrValue)
};
/**
* @desc spreads the entries from ChainedMap.store.values
* @since 0.4.0
*
* @return {Array<any>} toArr(this.store.values())
*
* @NOTE look at Chainable.constructor to ensure not to use `new Array...`
* @NOTE moved from ChainedMap and ChainedSet to Chainable @2.0.2
* @NOTE this was [...] & Array.from(this.store.values())
*
* {@link https://kangax.github.io/compat-table/es6/#test-Array_static_methods compat-array-static-methods}
* {@link https://stackoverflow.com/questions/20069828/how-to-convert-set-to-array set-to-array}
* {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/values mozilla-map-values}
* {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/values mozilla-set-values}
*
* @see {@link mozilla-map-values}
* @see {@link mozilla-set-values}
* @see {@link compat-array-static-methods}
* @see {@link set-to-array}
*
* @example
*
* const chain = new Chain()
* chain.set('eh', 1)
* chain.values()
* //=> [1]
*
*/
Chainable.prototype.values = function values () {
var vals = []
this.store.forEach(function (v) { return vals.push(v); })
return vals
};
/**
* @see http://2ality.com/2015/09/well-known-symbols-es6.html#default-tostring-tags
* @since 1.0.2
*
* @param {string} hint enum[default, string, number]
* @return {Primitive}
*
* @example
*
* const chain = new Chain()
* chain.toNumber = () => 1
* +chain;
* //=> 1
* chain + 1
* //=>
*
* @example
*
* const chain = new Chain()
* chain.toString = () => 'eh'
* chain + ''
* //=> 'eh'
*
*/
Chainable.prototype[Primitive] = function (hint) {
/* prettier-ignore */
/**
* hint === 'number'
* `s`tring is 115
* `n`umber is 110
* 110 & 4 = 1
* 115 & 4 = 0
*
* if (hint === 'string' && this.toJSON) return this.toJSON()
* else if (hint === 'number' && this.toNumber) return this.toNumber()
*/
if (hint === 'number' && this.toNumber) { return this.toNumber() }
// hint === 'string'
if (this.toJSON) { return this.toJSON() }
// hint === 'default'
return this.toString()
};
return Chainable;
}(SuperClass));
var ChainPrototype = Chainable.prototype
/**
* @private
* @since 0.5.0
* @example for (var i = 0; i < chain.length; i++)
* @see ChainedMap.store
* @return {number}
*/
ObjectDefine(ChainPrototype, 'length', {
enumerable: false,
get: function get() {
return this.store.size
},
})
ObjectDefine(ChainPrototype, Instance, {
enumerable: false,
value: function (instance) { return instance && (isPrototypeOf(ChainPrototype, instance) || instance.store); },
})
return Chainable
}
var c = C((function () {
function anonymous () {}
return anonymous;
}()))
/**
* @since 3.0.0
* @func
* @example
*
* class Target {}
* const TargetChain = Chainable.compose(Target)
* const chain = new TargetChain()
* chain instanceof Target
* //=> true
*
*/
c.compose = C
module.exports = c
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2hhaW5hYmxlLmpzIiwic291cmNlcyI6WyJDaGFpbmFibGUuanMiXSwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgSXRlcmF0b3IgPSByZXF1aXJlKCcuL2RlcHMvc3ltYm9scy9pdGVyYXRvcicpXG5jb25zdCBJbnN0YW5jZSA9IHJlcXVpcmUoJy4vZGVwcy9zeW1ib2xzL2luc3RhbmNlJylcbmNvbnN0IFByaW1pdGl2ZSA9IHJlcXVpcmUoJy4vZGVwcy9zeW1ib2xzL3ByaW1pdGl2ZScpXG5jb25zdCBpc1Byb3RvdHlwZU9mID0gcmVxdWlyZSgnLi9kZXBzL2lzL3Byb3RvdHlwZU9mJylcbmNvbnN0IGlzTWFwID0gcmVxdWlyZSgnLi9kZXBzL2lzL21hcCcpXG5jb25zdCBpc1NldCA9IHJlcXVpcmUoJy4vZGVwcy9pcy9zZXQnKVxuY29uc3QgaXNVbmRlZmluZWQgPSByZXF1aXJlKCcuL2RlcHMvaXMvdW5kZWZpbmVkJylcbmNvbnN0IGlzRnVuY3Rpb24gPSByZXF1aXJlKCcuL2RlcHMvaXMvZnVuY3Rpb24nKVxuY29uc3QgaXNTdHJpbmcgPSByZXF1aXJlKCcuL2RlcHMvaXMvc3RyaW5nJylcbmNvbnN0IGlzRmFsc2UgPSByZXF1aXJlKCcuL2RlcHMvaXMvZmFsc2UnKVxuY29uc3QgT2JqZWN0S2V5cyA9IHJlcXVpcmUoJy4vZGVwcy91dGlsL2tleXMnKVxuY29uc3QgT2JqZWN0RGVmaW5lID0gcmVxdWlyZSgnLi9kZXBzL2RlZmluZScpXG5jb25zdCBpZ25vcmVkID0gcmVxdWlyZSgnLi9kZXBzL2lnbm9yZWQnKVxuY29uc3QgRU5WX0RFVkVMT1BNRU5UID0gcmVxdWlyZSgnLi9kZXBzL2Vudi9kZXYnKVxuXG5jb25zdCBzaG91bGRDbGVhciA9IChrZXksIHByb3BlcnR5KSA9PlxuICAhaWdub3JlZChrZXkpICYmXG4gIChpc01hcChwcm9wZXJ0eSkgfHwgaXNTZXQocHJvcGVydHkpIHx8IChwcm9wZXJ0eSAmJiBwcm9wZXJ0eS5zdG9yZSkpXG5cbmNvbnN0IEMgPSBTdXBlckNsYXNzID0+IHtcbiAgLyogaXN0YW5idWwgaWdub3JlIG5leHQ6IGRldiAqL1xuICBpZiAoRU5WX0RFVkVMT1BNRU5UKSB7XG4gICAgaWYgKCFTdXBlckNsYXNzIHx8ICFTdXBlckNsYXNzLnByb3RvdHlwZSkge1xuICAgICAgY29uc29sZS5sb2coe1N1cGVyQ2xhc3N9KVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGlkIG5vdCBoYXZlIGEgc3VwZXIgY2xhc3MgLyB0YXJnZXQgYmFzZScpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjIFRyYWl0IGNsYXNzIHRoYXQgY2FuIGluaGVyaXQgYW55IGNsYXNzIHBhc3NlZCBpbnRvIGNvbXBvc2UsIGV4dGVuZGVkIGJ5IENoYWluZWRNYXAgJiBDaGFpbmVkU2V0XG4gICAqXG4gICAqIEBtZW1iZXIgQ2hhaW5hYmxlXG4gICAqIEBjbGFzcyBDaGFpbmFibGVcbiAgICogQGNhdGVnb3J5IENoYWluYWJsZVxuICAgKiBAdHlwZSB7Q2hhaW5hYmxlfVxuICAgKlxuICAgKiBAcHJvcCB7Q2hhaW5hYmxlIHwgYW55fSBwYXJlbnRcbiAgICogQHByb3Age3N0cmluZ30gY2xhc3NOYW1lXG4gICAqXG4gICAqIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vaWx1d2F0YXIvamF2YS1kZXNpZ24tcGF0dGVybnMvdHJlZS9tYXN0ZXIvY2hhaW4gY2hhaW4tcGF0dGVybn1cbiAgICogQHNlZSB7QGxpbmsgY2hhaW4tcGF0dGVybn1cbiAgICpcbiAgICogQHNlZSBDaGFpbmVkTWFwXG4gICAqIEBzZWUgQ2hhaW5lZFNldFxuICAgKlxuICAgKiBAdGVzdHMgQ2hhaW5hYmxlXG4gICAqIEB0eXBlcyBDaGFpbmFibGVcbiAgICovXG4gIGNsYXNzIENoYWluYWJsZSBleHRlbmRzIFN1cGVyQ2xhc3Mge1xuICAgIC8qKlxuICAgICAqIEBzaW5jZSAwLjAuMVxuICAgICAqIEBwYXJhbSB7Q2hhaW5hYmxlIHwgYW55IHwgUGFyZW50VHlwZX0gcGFyZW50IFBhcmVudFR5cGVcbiAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICBjbGFzcyBDaGFpbmVkTWFwIGV4dGVuZHMgQ2hhaW5hYmxlIHt9XG4gICAgICogICAgY29uc3QgbWFwID0gbmV3IENoYWluZWRNYXAoKVxuICAgICAqICAgIG1hcC5jbGFzc05hbWVcbiAgICAgKiAgICAvLz0+IENoYWluZWRNYXBcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihwYXJlbnQpIHtcbiAgICAgIHN1cGVyKClcbiAgICAgIGlmIChwYXJlbnQpIHRoaXMucGFyZW50ID0gcGFyZW50XG4gICAgICB0aGlzLmNsYXNzTmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBkZXNjIEl0ZXJhdG9yIGZvciBsb29waW5nIHZhbHVlcyBpbiB0aGUgc3RvcmVcbiAgICAgKlxuICAgICAqIEBzaW5jZSAwLjUuMFxuICAgICAqIEBzZWUgdGhpcy5zdG9yZVxuICAgICAqIEB0eXBlIHtnZW5lcmF0b3J9XG4gICAgICogQHJldHVybiB7T2JqZWN0fSB7dmFsdWU6IHVuZGVmaW5lZCB8IGFueSwgZG9uZTogdHJ1ZSB8IGZhbHNlfVxuICAgICAqXG4gICAgICogQE5PVEUgYXNzaWduZWQgdG8gYSB2YXJpYWJsZSBzbyBidWJsZSBpZ25vcmVzIGl0XG4gICAgICogQHNlZSBodHRwczovL2dpdGh1Yi5jb20vc2luZHJlc29yaHVzL3F1aWNrLWxydS9ibG9iL21hc3Rlci9pbmRleC5qc1xuICAgICAqIEBzZWUgaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMzY5NzY4MzIvd2hhdC1pcy10aGUtbWVhbmluZy1vZi1zeW1ib2wtaXRlcmF0b3ItaW4tdGhpcy1jb250ZXh0XG4gICAgICogQHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9TeW1ib2wvaXRlcmF0b3JcbiAgICAgKiBAdGVzdHMgaXRlcmF0aW9uXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgY29uc3QgY2hhaW4gPSBuZXcgQ2hhaW4oKS5zZXQoJ2VoJywgMSlcbiAgICAgKiAgICBmb3IgKHZhciBba2V5LCB2YWxdIG9mIGNoYWluKSBjb25zb2xlLmxvZyh7W2tleV06IHZhbH0pXG4gICAgICogICAgLy89PiB7ZWg6IDF9XG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgKltTeW1ib2wuaXRlcmF0b3JdKCk6IHZvaWQgeyBmb3IgKGNvbnN0IGl0ZW0gb2YgdGhpcy5zdG9yZSkgeWllbGQgaXRlbSB9XG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgY29uc3Qge0NoYWluZWRTZXR9ID0gcmVxdWlyZSgnY2hhaW4tYWJsZScpXG4gICAgICogICAgY29uc3Qgc2V0ID0gbmV3IENoYWluZWRTZXQoKVxuICAgICAqICAgIHNldC5hZGQoJ2VoJylcbiAgICAgKlxuICAgICAqICAgIGZvciAoY29uc3QgYXJyIG9mIHNldCkge1xuICAgICAqICAgICAgY29uc3QgW2tleSwgdmFsXSA9IGFyclxuICAgICAqXG4gICAgICogICAgICBrZXlcbiAgICAgKiAgICAgIC8vPT4gMFxuICAgICAqXG4gICAgICogICAgICB2YWxcbiAgICAgKiAgICAgIC8vPT4gJ2VoJ1xuICAgICAqXG4gICAgICogICAgICBhcnIubGVuZ3RoXG4gICAgICogICAgICAvLz0+IDJcbiAgICAgKiAgICB9XG4gICAgICpcbiAgICAgKi9cbiAgICBbSXRlcmF0b3JdKCkge1xuICAgICAgY29uc3QgdmFsdWVzID0gdGhpcy52YWx1ZXMoKVxuICAgICAgY29uc3Qgc2l6ZSA9IHRoaXMuc3RvcmUuc2l6ZVxuICAgICAgY29uc3QgZW50cmllcyA9IHRoaXMuZW50cmllcyA/IHRoaXMuZW50cmllcygpIDogMFxuICAgICAgY29uc3Qga2V5cyA9IGVudHJpZXMgPT09IDAgPyBuZXcgQXJyYXkoc2l6ZSkgOiBPYmplY3RLZXlzKGVudHJpZXMpXG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGk6IDAsXG4gICAgICAgIG5leHQoKSB7XG4gICAgICAgICAgbGV0IGkgPSB0aGlzLmlcbiAgICAgICAgICBsZXQga2V5ID0gaVxuICAgICAgICAgIGNvbnN0IHZhbCA9IHZhbHVlc1tpXVxuICAgICAgICAgIGlmIChlbnRyaWVzKSBrZXkgPSBrZXlzW2ldXG5cbiAgICAgICAgICAvLyBkb25lIC0gbm8gbW9yZSB2YWx1ZXMsIG9yIGl0ZXJhdGlvbiByZWFjaGVkIHNpemVcbiAgICAgICAgICBpZiAoKGlzVW5kZWZpbmVkKGtleSkgJiYgaXNVbmRlZmluZWQodmFsKSkgfHwgc2l6ZSA8PSBpKSB7XG4gICAgICAgICAgICByZXR1cm4ge3ZhbHVlOiB1bmRlZmluZWQsIGRvbmU6IHRydWV9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy5pKytcblxuICAgICAgICAgIC8vIHJldHVyblxuICAgICAgICAgIHJldHVybiB7dmFsdWU6IFtrZXksIHZhbF0sIGRvbmU6IGZhbHNlfVxuICAgICAgICB9LFxuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBkZXNjIGZvciBlbmRpbmcgbmVzdGVkIGNoYWluc1xuICAgICAqIEBzaW5jZSAwLjQuMFxuICAgICAqIEByZXR1cm4ge0NoYWluYWJsZSB8IGFueX1cbiAgICAgKiBAc2VlIENoYWluYWJsZS5wYXJlbnRcbiAgICAgKiBAc2VlIEZhY3RvcnlDaGFpblxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgIGNvbnN0IHBhcmVudCA9ICdlaCdcbiAgICAgKiAgICBjb25zdCBjaGlsZCA9IG5ld0NoYWluKHBhcmVudClcbiAgICAgKiAgICBjaGlsZC5lbmQoKVxuICAgICAqICAgIC8vPT4gJ2VoJ1xuICAgICAqXG4gICAgICovXG4gICAgZW5kKCkge1xuICAgICAgcmV0dXJuIHRoaXMucGFyZW50XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGRlc2Mgd2hlbiB0aGUgY29uZGl0aW9uIGlzIHRydWUsXG4gICAgICogICAgICAgdHJ1ZUJyYW5jaGVyIGlzIGNhbGxlZCxcbiAgICAgKiAgICAgICBlbHNlLCBmYWxzZUJyYW5jaGVyIGlzIGNhbGxlZFxuICAgICAqXG4gICAgICogQHNpbmNlIDQuMC4wIDwtIGFkZGVkIHN0cmluZy1hcy1oYXMoY29uZGl0aW9uKVxuICAgICAqIEBzaW5jZSAyLjAuMFxuICAgICAqXG4gICAgICogQHBhcmFtICB7Ym9vbGVhbiB8IHN0cmluZ30gY29uZGl0aW9uIHdoZW4gc3RyaW5nLCBjaGVja3MgdGhpcy5nZXRcbiAgICAgKiBAcGFyYW0gIHtGdW5jdGlvbn0gW3RydWVCcmFuY2hlcj1GdW5jdGlvbl0gY2FsbGVkIHdoZW4gdHJ1ZVxuICAgICAqIEBwYXJhbSAge0Z1bmN0aW9ufSBbZmFsc2VCcmFuY2hlcj1GdW5jdGlvbl0gY2FsbGVkIHdoZW4gZmFsc2VcbiAgICAgKiBAcmV0dXJuIHtDaGFpbmFibGV9IEBjaGFpbmFibGVcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKlxuICAgICAqICBjb25zdCBwcm9kID0gcHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09ICdwcm9kdWN0aW9uJ1xuICAgICAqICBjaGFpbnMud2hlbihwcm9kLCBjID0+IGMuc2V0KCdwcm9kJywgdHJ1ZSksIGMgPT4gYy5zZXQoJ3Byb2QnLCBmYWxzZSkpXG4gICAgICpcbiAgICAgKlxuICAgICAqL1xuICAgIHdoZW4oY29uZGl0aW9uLCB0cnVlQnJhbmNoZXIsIGZhbHNlQnJhbmNoZXIpIHtcbiAgICAgIGlmIChjb25kaXRpb24pIHtcbiAgICAgICAgaWYgKGlzRnVuY3Rpb24odHJ1ZUJyYW5jaGVyKSkge1xuICAgICAgICAgIGlmIChpc1N0cmluZyhjb25kaXRpb24pKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5nZXQoY29uZGl0aW9uKSkge1xuICAgICAgICAgICAgICB0cnVlQnJhbmNoZXIodGhpcylcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0cnVlQnJhbmNoZXIodGhpcylcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKGlzRnVuY3Rpb24oZmFsc2VCcmFuY2hlcikpIHtcbiAgICAgICAgZmFsc2VCcmFuY2hlcih0aGlzKVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpc1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBkZXNjIGNsZWFycyB0aGUgbWFwLFxuICAgICAqICAgICAgIGdvZXMgdGhyb3VnaCB0aGlzIHByb3BlcnRpZXMsXG4gICAgICogICAgICAgY2FsbHMgLmNsZWFyIGlmIHRoZXkgYXJlIGluc3RhbmNlb2YgQ2hhaW5hYmxlIG9yIE1hcFxuICAgICAqXG4gICAgICogQHNpbmNlIDQuMC4wIChtb3ZlZCBvbmx5IHRvIENoYWluYWJsZSwgYWRkZWQgb3B0aW9uIHRvIGNsZWFyIHRoaXMga2V5cylcbiAgICAgKiBAc2luY2UgMC40LjAgKGluIENoYWluZWRNYXApXG4gICAgICogQHNpbmNlIDAuMy4wIChpbiBDaGFpbmFibGUpXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW4gfCB1bmRlZmluZWR9IFtjbGVhclByb3BlcnRpZXNUaGF0QXJlQ2hhaW5MaWtlPXRydWVdIGNoZWNrcyBwcm9wZXJ0aWVzIG9uIHRoZSBvYmplY3QsIGlmIHRoZXkgYXJlIGBjaGFpbi1saWtlYCwgY2xlYXJzIHRoZW0gYXMgd2VsbFxuICAgICAqIEByZXR1cm4ge0NoYWluYWJsZX0gQGNoYWluYWJsZVxuICAgICAqXG4gICAgICogQHNlZSBodHRwczovL2dpdGh1Yi5jb20vZmxpcGh1Yi9mbGlwY2hhaW4vaXNzdWVzLzJcbiAgICAgKiBAc2VlIENoYWluZWRTZXRcbiAgICAgKiBAc2VlIENoYWluZWRNYXBcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICBjb25zdCBjaGFpbiA9IG5ldyBDaGFpbigpXG4gICAgICogICAgY2hhaW4uc2V0KCdlaCcsIDEpXG4gICAgICogICAgY2hhaW4uZW50cmllcygpXG4gICAgICogICAgLy89PiB7ZWg6IDF9XG4gICAgICogICAgY2hhaW4uY2xlYXIoKVxuICAgICAqICAgIGNoYWluLmVudHJpZXMoKVxuICAgICAqICAgIC8vPT4ge31cbiAgICAgKlxuICAgICAqL1xuICAgIGNsZWFyKGNsZWFyUHJvcGVydGllc1RoYXRBcmVDaGFpbkxpa2UpIHtcbiAgICAgIHRoaXMuc3RvcmUuY2xlYXIoKVxuXG4gICAgICBpZiAoaXNGYWxzZShjbGVhclByb3BlcnRpZXNUaGF0QXJlQ2hhaW5MaWtlKSkgcmV0dXJuIHRoaXNcblxuICAgICAgY29uc3Qga2V5cyA9IE9iamVjdEtleXModGhpcylcbiAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwga2V5cy5sZW5ndGg7IGsrKykge1xuICAgICAgICBjb25zdCBrZXkgPSBrZXlzW2tdXG4gICAgICAgIGNvbnN0IHByb3BlcnR5ID0gdGhpc1trZXldXG4gICAgICAgIGlmIChzaG91bGRDbGVhcihrZXksIHByb3BlcnR5KSkgdGhpc1trZXldLmNsZWFyKClcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXNcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAZGVzYyBjYWxscyAuZGVsZXRlIG9uIHRoaXMuc3RvcmUubWFwXG4gICAgICogQHNpbmNlIDAuMy4wXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1ByaW1pdGl2ZX0ga2V5IG9uIGEgTWFwOiBrZXkgcmVmZXJlbmNpbmcgdGhlIHZhbHVlLiBvbiBhIFNldDogdGhlIGluZGV4XG4gICAgICogQHJldHVybiB7Q2hhaW5hYmxlfVxuICAgICAqXG4gICAgICogQHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9NYXAvaGFzXG4gICAgICogQHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9TZXQvaGFzXG4gICAgICogQHNlZSBDaGFpbmVkU2V0XG4gICAgICogQHNlZSBDaGFpbmVkTWFwXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgY29uc3QgY2hhaW4gPSBuZXcgQ2hhaW4oKVxuICAgICAqICAgIGNoYWluLnNldCgnZWgnLCAxKVxuICAgICAqICAgIGNoYWluLmdldCgnZWgnKVxuICAgICAqICAgIC8vID0+IDFcbiAgICAgKiAgICBjaGFpbi5kZWxldGUoJ2VoJywgMSlcbiAgICAgKiAgICBjaGFpbi5nZXQoJ2VoJylcbiAgICAgKiAgICAvLyA9PiB1bmRlZmluZWRcbiAgICAgKlxuICAgICAqL1xuICAgIGRlbGV0ZShrZXkpIHtcbiAgICAgIHRoaXMuc3RvcmUuZGVsZXRlKGtleSlcbiAgICAgIHJldHVybiB0aGlzXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHNpbmNlIDAuMy4wXG4gICAgICogQHBhcmFtIHthbnl9IGtleU9yVmFsdWUga2V5IHdoZW4gTWFwLCB2YWx1ZSB3aGVuIFNldFxuICAgICAqIEByZXR1cm4ge2Jvb2xlYW59XG4gICAgICogQHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9NYXAvaGFzXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICBjb25zdCBjaGFpbiA9IG5ldyBDaGFpbigpXG4gICAgICogICBjaGFpbi5zZXQoJ2VoJywgMSkuaGFzKCdlaCcpXG4gICAgICogICAvLz0+IHRydWVcbiAgICAgKiAgIGNoYWluLmhhcygnY2FuYWRhJylcbiAgICAgKiAgIC8vPT4gZmFsc2VcbiAgICAgKlxuICAgICAqL1xuICAgIGhhcyhrZXlPclZhbHVlKSB7XG4gICAgICByZXR1cm4gdGhpcy5zdG9yZS5oYXMoa2V5T3JWYWx1ZSlcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAZGVzYyBzcHJlYWRzIHRoZSBlbnRyaWVzIGZyb20gQ2hhaW5lZE1hcC5zdG9yZS52YWx1ZXNcbiAgICAgKiBAc2luY2UgMC40LjBcbiAgICAgKlxuICAgICAqIEByZXR1cm4ge0FycmF5PGFueT59IHRvQXJyKHRoaXMuc3RvcmUudmFsdWVzKCkpXG4gICAgICpcbiAgICAgKiBATk9URSBsb29rIGF0IENoYWluYWJsZS5jb25zdHJ1Y3RvciB0byBlbnN1cmUgbm90IHRvIHVzZSBgbmV3IEFycmF5Li4uYFxuICAgICAqIEBOT1RFIG1vdmVkIGZyb20gQ2hhaW5lZE1hcCBhbmQgQ2hhaW5lZFNldCB0byBDaGFpbmFibGUgQDIuMC4yXG4gICAgICogQE5PVEUgdGhpcyB3YXMgWy4uLl0gJiBBcnJheS5mcm9tKHRoaXMuc3RvcmUudmFsdWVzKCkpXG4gICAgICpcbiAgICAgKiB7QGxpbmsgaHR0cHM6Ly9rYW5nYXguZ2l0aHViLmlvL2NvbXBhdC10YWJsZS9lczYvI3Rlc3QtQXJyYXlfc3RhdGljX21ldGhvZHMgY29tcGF0LWFycmF5LXN0YXRpYy1tZXRob2RzfVxuICAgICAqIHtAbGluayBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yMDA2OTgyOC9ob3ctdG8tY29udmVydC1zZXQtdG8tYXJyYXkgc2V0LXRvLWFycmF5fVxuICAgICAqIHtAbGluayBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9NYXAvdmFsdWVzIG1vemlsbGEtbWFwLXZhbHVlc31cbiAgICAgKiB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvU2V0L3ZhbHVlcyBtb3ppbGxhLXNldC12YWx1ZXN9XG4gICAgICpcbiAgICAgKiBAc2VlIHtAbGluayBtb3ppbGxhLW1hcC12YWx1ZXN9XG4gICAgICogQHNlZSB7QGxpbmsgbW96aWxsYS1zZXQtdmFsdWVzfVxuICAgICAqIEBzZWUge0BsaW5rIGNvbXBhdC1hcnJheS1zdGF0aWMtbWV0aG9kc31cbiAgICAgKiBAc2VlIHtAbGluayBzZXQtdG8tYXJyYXl9XG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogIGNvbnN0IGNoYWluID0gbmV3IENoYWluKClcbiAgICAgKiAgY2hhaW4uc2V0KCdlaCcsIDEpXG4gICAgICogIGNoYWluLnZhbHVlcygpXG4gICAgICogIC8vPT4gWzFdXG4gICAgICpcbiAgICAgKi9cbiAgICB2YWx1ZXMoKSB7XG4gICAgICBjb25zdCB2YWxzID0gW11cbiAgICAgIHRoaXMuc3RvcmUuZm9yRWFjaCh2ID0+IHZhbHMucHVzaCh2KSlcbiAgICAgIHJldHVybiB2YWxzXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHNlZSBodHRwOi8vMmFsaXR5LmNvbS8yMDE1LzA5L3dlbGwta25vd24tc3ltYm9scy1lczYuaHRtbCNkZWZhdWx0LXRvc3RyaW5nLXRhZ3NcbiAgICAgKiBAc2luY2UgMS4wLjJcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBoaW50IGVudW1bZGVmYXVsdCwgc3RyaW5nLCBudW1iZXJdXG4gICAgICogQHJldHVybiB7UHJpbWl0aXZlfVxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICBjb25zdCBjaGFpbiA9IG5ldyBDaGFpbigpXG4gICAgICogIGNoYWluLnRvTnVtYmVyID0gKCkgPT4gMVxuICAgICAqICArY2hhaW47XG4gICAgICogIC8vPT4gMVxuICAgICAqICBjaGFpbiArIDFcbiAgICAgKiAgLy89PlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICBjb25zdCBjaGFpbiA9IG5ldyBDaGFpbigpXG4gICAgICogIGNoYWluLnRvU3RyaW5nID0gKCkgPT4gJ2VoJ1xuICAgICAqICBjaGFpbiArICcnXG4gICAgICogIC8vPT4gJ2VoJ1xuICAgICAqXG4gICAgICovXG4gICAgW1ByaW1pdGl2ZV0oaGludCkge1xuICAgICAgLyogcHJldHRpZXItaWdub3JlICovXG4gICAgICAvKipcbiAgICAgICAqIGhpbnQgPT09ICdudW1iZXInXG4gICAgICAgKiBgc2B0cmluZyBpcyAxMTVcbiAgICAgICAqIGBuYHVtYmVyIGlzIDExMFxuICAgICAgICogMTEwICYgNCA9IDFcbiAgICAgICAqIDExNSAmIDQgPSAwXG4gICAgICAgKlxuICAgICAgICogaWYgKGhpbnQgPT09ICdzdHJpbmcnICYmIHRoaXMudG9KU09OKSByZXR1cm4gdGhpcy50b0pTT04oKVxuICAgICAgICogZWxzZSBpZiAoaGludCA9PT0gJ251bWJlcicgJiYgdGhpcy50b051bWJlcikgcmV0dXJuIHRoaXMudG9OdW1iZXIoKVxuICAgICAgICovXG4gICAgICBpZiAoaGludCA9PT0gJ251bWJlcicgJiYgdGhpcy50b051bWJlcikgcmV0dXJuIHRoaXMudG9OdW1iZXIoKVxuXG4gICAgICAvLyBoaW50ID09PSAnc3RyaW5nJ1xuICAgICAgaWYgKHRoaXMudG9KU09OKSByZXR1cm4gdGhpcy50b0pTT04oKVxuXG4gICAgICAvLyBoaW50ID09PSAnZGVmYXVsdCdcbiAgICAgIHJldHVybiB0aGlzLnRvU3RyaW5nKClcbiAgICB9XG4gIH1cblxuICBjb25zdCBDaGFpblByb3RvdHlwZSA9IENoYWluYWJsZS5wcm90b3R5cGVcblxuICAvKipcbiAgICogQHByaXZhdGVcbiAgICogQHNpbmNlIDAuNS4wXG4gICAqIEBleGFtcGxlIGZvciAodmFyIGkgPSAwOyBpIDwgY2hhaW4ubGVuZ3RoOyBpKyspXG4gICAqIEBzZWUgQ2hhaW5lZE1hcC5zdG9yZVxuICAgKiBAcmV0dXJuIHtudW1iZXJ9XG4gICAqL1xuICBPYmplY3REZWZpbmUoQ2hhaW5Qcm90b3R5cGUsICdsZW5ndGgnLCB7XG4gICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgZ2V0KCkge1xuICAgICAgcmV0dXJuIHRoaXMuc3RvcmUuc2l6ZVxuICAgIH0sXG4gIH0pXG4gIE9iamVjdERlZmluZShDaGFpblByb3RvdHlwZSwgSW5zdGFuY2UsIHtcbiAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICB2YWx1ZTogaW5zdGFuY2UgPT5cbiAgICAgIGluc3RhbmNlICYmIChpc1Byb3RvdHlwZU9mKENoYWluUHJvdG90eXBlLCBpbnN0YW5jZSkgfHwgaW5zdGFuY2Uuc3RvcmUpLFxuICB9KVxuXG4gIHJldHVybiBDaGFpbmFibGVcbn1cblxuY29uc3QgYyA9IEMoY2xhc3Mge30pXG5cbi8qKlxuICogQHNpbmNlIDMuMC4wXG4gKiBAZnVuY1xuICogQGV4YW1wbGVcbiAqXG4gKiAgY2xhc3MgVGFyZ2V0IHt9XG4gKiAgY29uc3QgVGFyZ2V0Q2hhaW4gPSBDaGFpbmFibGUuY29tcG9zZShUYXJnZXQpXG4gKiAgY29uc3QgY2hhaW4gPSBuZXcgVGFyZ2V0Q2hhaW4oKVxuICogIGNoYWluIGluc3RhbmNlb2YgVGFyZ2V0XG4gKiAgLy89PiB0cnVlXG4gKlxuICovXG5jLmNvbXBvc2UgPSBDXG5cbm1vZHVsZS5leHBvcnRzID0gY1xuIl0sIm5hbWVzIjpbImNvbnN0Iiwic3VwZXIiLCJsZXQiLCJ0aGlzIl0sIm1hcHBpbmdzIjoiQUFBQUEsR0FBSyxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUMseUJBQXlCLENBQUM7QUFDbkRBLEdBQUssQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFDLHlCQUF5QixDQUFDO0FBQ25EQSxHQUFLLENBQUMsU0FBUyxHQUFHLE9BQU8sQ0FBQywwQkFBMEIsQ0FBQztBQUNyREEsR0FBSyxDQUFDLGFBQWEsR0FBRyxPQUFPLENBQUMsdUJBQXVCLENBQUM7QUFDdERBLEdBQUssQ0FB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