foop
Version:
interfaces that describe their intentions.
330 lines (304 loc) • 29.7 kB
JavaScript
/* eslint complexity: "OFF" */
var MethodChain = require('./MethodChain')
var ChainedMapBase = require('./ChainedMapBase')
var dopemerge = require('./deps/dopemerge')
var isFunction = require('./deps/is/function')
var isUndefined = require('./deps/is/undefined')
var isTrue = require('./deps/is/true')
var isMapish = require('./deps/is/mapish')
var ObjectKeys = require('./deps/util/keys')
var constructInit = require('./deps/fp/constructInit')
var EMPTY_OBJ = require('./deps/native/EMPTY_OBJ')
var SHORTHANDS_KEY = require('./deps/meta/SHORTHANDS_KEY')
var ENV_DEVELOPMENT = require('./deps/env/dev')
var ENV_DEBUG = require('./deps/env/debug')
var ON_EXISTING_KEY = 'onExisting'
var ON_VALUE_KEY = 'onValue'
var MERGER_KEY = 'merger'
var MERGER_OPTIONS_KEY = 'opts'
var OBJ_KEY = 'obj'
/**
* @since 1.0.0
* @type {Map}
* @extends {ChainedMapBase}
* @member MergeChain
* @memberOf Chainable
*
* @types MergeChain
* @tests MergeChain
* @see deps/dopemerge
*
* {@link https://sourcemaking.com/design_patterns/visitor visitor-pattern}
*
* @TODO consider just making this a function,
* because 80/20 onValue merger & onExisting
* are rarely used & are easily overridable with .merge
*/
var MergeChain = (function (ChainedMapBase) {
function MergeChain(parent) {
ChainedMapBase.call(this, parent)
/* prettier-ignore */
this
.extend([ON_EXISTING_KEY, ON_VALUE_KEY, OBJ_KEY])
.set(ON_VALUE_KEY, function () { return true; })
.set(MERGER_KEY, dopemerge)
}
if ( ChainedMapBase ) MergeChain.__proto__ = ChainedMapBase;
MergeChain.prototype = Object.create( ChainedMapBase && ChainedMapBase.prototype );
MergeChain.prototype.constructor = MergeChain;
/**
* @desc options for merging with dopemerge
* @modifies this.merger | this.opts
*
* @memberOf MergeChain
* @since 1.0.2
* @param {Object | Function} opts when object: options for the merger. when function: is the merger
* @return {MergeChain} @chainable
* @see dopemerge
*
* @example
* {
* stringToArray: true,
* boolToArray: false,
* boolAsRight: true,
* ignoreTypes: ['null', 'undefined', 'NaN'],
* debug: false,
* }
*
* @example
* .merger(require('lodash.mergewith')())
*/
MergeChain.prototype.merger = function merger (opts) {
if (isFunction(opts)) { return this.set(MERGER_KEY, opts) }
else { return this.set(MERGER_OPTIONS_KEY, opts) }
};
// [v] messes comments on conditional brace style
/* prettier-ignore */
/**
* @desc merges object in, goes through all keys, checks cbs, dopemerges
*
* @since 1.0.0
*
* @param {Object} [obj2=undefined] object to merge in, defaults to this.get('obj')
* @return {MergeChain} @chainable
*
* @see ChainedMap
* @TODO issue here if we extend without shorthands &
* we want to merge existing values... :s
*
*
* @example
*
* const chain = new Chain()
* chain.merge({canada: {eh: true}})
* chain.merge({canada: {arr: [0, {'1': 2}], eh: {again: true}}})
* chain.entries()
* //=> {canada:{ eh: {again: true}, arr: [0, {'1': 2}] }}
*
*/
MergeChain.prototype.merge = function merge (obj2) {
var this$1 = this;
// better uglifying
var parent = this.parent
var get = function (key) { return this$1.get(key); }
var onExisting = get(ON_EXISTING_KEY)
var onValue = get(ON_VALUE_KEY)
var opts = get(MERGER_OPTIONS_KEY)
var obj = obj2 || get(OBJ_KEY)
var merger = get(MERGER_KEY)
var shorthands = parent.meta ? parent.meta(SHORTHANDS_KEY) : EMPTY_OBJ
var keys = ObjectKeys(obj)
// @@debugger
/* istanbul ignore next: devs */
if (ENV_DEVELOPMENT) {
if (!obj) {
console.log({onExisting: onExisting, opts: opts, obj: obj, merger: merger, shorthands: shorthands, keys: keys, parent: parent})
throw new Error('must provide an object to merge')
}
}
/**
* @private
*
* since this would be slower
* if I want to not have a speedy default when using .onExisting
* should @note to use .extend
* when using chains without a class & doing .merge (edge-case)
*
* @param {Primitive} key key (shorthands[key] or just key)
* @param {*} value obj[key]
* @return {void}
*
* @TODO could use .eq here
* @TODO if (isMapish(obj)) obj = obj.entries()
*
* @example
* var obj = {key: 1}
*
* MergeChain.init(obj).merge({key: ['value']})
*
* // goes to this internal scoped function
* handleExisting('key', ['value'])
* // if there is .onValue or .onExisting, use them, default deepmerge
*
* obj
* //=> {key: [1, 'value']}
*
*/
var handleExisting = function (key, value) {
/**
* @desc when fn is a full method, not an extended shorthand
* @since 0.5.0
*
* @param {Primitive} keyToSet key we chose to set
* @param {*} valueToSet value we chose to set (merged, existing, new)
* @return {Parent | Chain | *} .set or [keyToSet] return
*
* @example
*
* MergeChain.init(new Chain().extend(['eh']))
*
* //isFunction: true => call parent[keyToSet](valueToSet)
* setChosen('eh', 1)
* //=> parent
* parent.get('eh')
* //=> 1
*
* //=>isFunction: false => parent.set(keyToSet, valueToSet)
* setChosen('oh', 1)
* //=> parent //<- unless .set is overriden
* parent.get('oh')
* //=> 1
*
*/
var setChosen = function (keyToSet, valueToSet) { return (isFunction(parent[key])
? parent[keyToSet](valueToSet)
: parent.set(keyToSet, valueToSet)); }
/**
* check if it's shorthanded
* -> check if it has a value already
*/
if (isTrue(parent.has(key))) {
// get that value
var existing = parent.get(key)
/**
* if we have onExisting, call it
* else default to dopemerge
*/
if (isUndefined(onExisting)) {
/* istanbul ignore next: devs */
if (ENV_DEBUG) {
console.log(
'parent has: no onExisting',
{existing: existing, [key]: value}
)
}
setChosen(key, merger(existing, value, opts))
}
else {
/* istanbul ignore next: devs */
if (ENV_DEBUG) {
console.log(
'parent has: has onExisting',
{existing: existing, onExisting: onExisting, [key]: value}
)
}
/**
* maybe we should not even have `.onExisting`
* since we can just override merge method...
* and then client can just use a custom merger...
*
* could add and remove subscriber but that's overhead and
* tricky here, because if we set a value that was just set...
*/
setChosen(key, onExisting(existing, value, opts))
}
}
else {
/* istanbul ignore next: devs */
if (ENV_DEBUG) {
console.log('parent does not have', {[key]: value})
}
setChosen(key, value)
}
}
for (var k = 0, len = keys.length; k < len; k++) {
// key to the current property in the data being merged
var key = keys[k]
// we have our value, no we can change the key if needed for shorthands
var value = obj[key]
// @NOTE: when shorthands is an object, key is the method it should call
if (!isUndefined(shorthands[key]) && shorthands[key] !== key) {
/* istanbul ignore next: devs */
if (ENV_DEBUG) {
console.log(
'had a shorthand with a diff key than the object (likely @alias)',
{shorthandMethod: shorthands[key], key: key, value: value}
)
}
key = shorthands[key]
}
// method for the key
var method = parent[key]
/* istanbul ignore next: sourcemaps trigger istanbul here incorrectly */
// use onValue when set
if (!onValue(value, key, this$1)) {
/* istanbul ignore next: devs */
if (ENV_DEBUG) {
console.log('had onValue, was false, ignored', {onValue: onValue, key: key, value: value})
}
continue
}
// when property itself is a Chainable
else if (isMapish(method)) {
/* istanbul ignore next: devs */
if (ENV_DEBUG) {
console.log('has method or shorthand')
}
parent[key].merge(value)
}
// we have a method or shorthand
else if (method) {
/* istanbul ignore next: devs */
if (ENV_DEBUG) {
console.log('has method or shorthand', {method: method, key: key, value: value})
}
handleExisting(key, value)
}
// default to .set on the store
else {
/* istanbul ignore next: devs */
if (ENV_DEBUG) {
console.log('went to default', {method: method, key: key, value: value})
}
parent.set(key, value)
}
}
return parent
};
return MergeChain;
}(ChainedMapBase));
constructInit(MergeChain)
/**
* @memberOf MergeChain
* @method onExisting
* @since 0.9.0
* @example
*
* const {Chain, MergeChain} = require('chain-able')
*
* const chain = new Chain().set('str', 'stringy')
*
* MergeChain.init(chain)
* .onExisting((a, b) => a + b)
* .merge({str: '+'})
*
* chain.get('str')
* //=> 'stringy+'
*
*/
module.exports = MergeChain
// @TODO re-enable this later
// module.exports = new MethodChain(MergeChain.prototype)
// .methods(['onExisting', 'onValue', 'obj'])
// .build(MergeChain)
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWVyZ2VDaGFpbi5qcyIsInNvdXJjZXMiOlsiTWVyZ2VDaGFpbi5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQgY29tcGxleGl0eTogXCJPRkZcIiAqL1xuY29uc3QgTWV0aG9kQ2hhaW4gPSByZXF1aXJlKCcuL01ldGhvZENoYWluJylcbmNvbnN0IENoYWluZWRNYXBCYXNlID0gcmVxdWlyZSgnLi9DaGFpbmVkTWFwQmFzZScpXG5jb25zdCBkb3BlbWVyZ2UgPSByZXF1aXJlKCcuL2RlcHMvZG9wZW1lcmdlJylcbmNvbnN0IGlzRnVuY3Rpb24gPSByZXF1aXJlKCcuL2RlcHMvaXMvZnVuY3Rpb24nKVxuY29uc3QgaXNVbmRlZmluZWQgPSByZXF1aXJlKCcuL2RlcHMvaXMvdW5kZWZpbmVkJylcbmNvbnN0IGlzVHJ1ZSA9IHJlcXVpcmUoJy4vZGVwcy9pcy90cnVlJylcbmNvbnN0IGlzTWFwaXNoID0gcmVxdWlyZSgnLi9kZXBzL2lzL21hcGlzaCcpXG5jb25zdCBPYmplY3RLZXlzID0gcmVxdWlyZSgnLi9kZXBzL3V0aWwva2V5cycpXG5jb25zdCBjb25zdHJ1Y3RJbml0ID0gcmVxdWlyZSgnLi9kZXBzL2ZwL2NvbnN0cnVjdEluaXQnKVxuY29uc3QgRU1QVFlfT0JKID0gcmVxdWlyZSgnLi9kZXBzL25hdGl2ZS9FTVBUWV9PQkonKVxuY29uc3QgU0hPUlRIQU5EU19LRVkgPSByZXF1aXJlKCcuL2RlcHMvbWV0YS9TSE9SVEhBTkRTX0tFWScpXG5jb25zdCBFTlZfREVWRUxPUE1FTlQgPSByZXF1aXJlKCcuL2RlcHMvZW52L2RldicpXG5jb25zdCBFTlZfREVCVUcgPSByZXF1aXJlKCcuL2RlcHMvZW52L2RlYnVnJylcblxuY29uc3QgT05fRVhJU1RJTkdfS0VZID0gJ29uRXhpc3RpbmcnXG5jb25zdCBPTl9WQUxVRV9LRVkgPSAnb25WYWx1ZSdcbmNvbnN0IE1FUkdFUl9LRVkgPSAnbWVyZ2VyJ1xuY29uc3QgTUVSR0VSX09QVElPTlNfS0VZID0gJ29wdHMnXG5jb25zdCBPQkpfS0VZID0gJ29iaidcblxuLyoqXG4gKiBAc2luY2UgMS4wLjBcbiAqIEB0eXBlIHtNYXB9XG4gKiBAZXh0ZW5kcyB7Q2hhaW5lZE1hcEJhc2V9XG4gKiBAbWVtYmVyIE1lcmdlQ2hhaW5cbiAqIEBtZW1iZXJPZiBDaGFpbmFibGVcbiAqXG4gKiBAdHlwZXMgTWVyZ2VDaGFpblxuICogQHRlc3RzIE1lcmdlQ2hhaW5cbiAqIEBzZWUgZGVwcy9kb3BlbWVyZ2VcbiAqXG4gKiB7QGxpbmsgaHR0cHM6Ly9zb3VyY2VtYWtpbmcuY29tL2Rlc2lnbl9wYXR0ZXJucy92aXNpdG9yIHZpc2l0b3ItcGF0dGVybn1cbiAqXG4gKiBAVE9ETyBjb25zaWRlciBqdXN0IG1ha2luZyB0aGlzIGEgZnVuY3Rpb24sXG4gKiAgICAgICBiZWNhdXNlIDgwLzIwIG9uVmFsdWUgbWVyZ2VyICYgb25FeGlzdGluZ1xuICogICAgICAgYXJlIHJhcmVseSB1c2VkICYgYXJlIGVhc2lseSBvdmVycmlkYWJsZSB3aXRoIC5tZXJnZVxuICovXG5jbGFzcyBNZXJnZUNoYWluIGV4dGVuZHMgQ2hhaW5lZE1hcEJhc2Uge1xuICAvKipcbiAgICogQHN0YXRpY1xuICAgKiBAcGFyYW0gIHtDaGFpbmFibGUgfCBQYXJlbnRUeXBlfSBwYXJlbnQgUGFyZW50VHlwZSByZXF1aXJlZCwgZm9yIG1lcmdpbmdcbiAgICogQHJldHVybiB7TWVyZ2VDaGFpbn0gQGNoYWluYWJsZVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKlxuICAgKiAgICBsZXQgbWFwID0gbmV3IE1hcCgpXG4gICAqICAgIG1hcC5zZXQoJ2VoJywgMSlcbiAgICogICAgbWFwLnNldCgnY29vJywgJ29vJylcbiAgICpcbiAgICogICAgTWVyZ2VDaGFpbi5pbml0KG1hcCkubWVyZ2Uoe2VoOiAyfSlcbiAgICogICAgY29uc29sZS5kaXIobWFwKVxuICAgKiAgICAvLz0+IE1hcCB7ICdlaCcgPT4gMiwgJ2NvbycgPT4gJ29vJyB9XG4gICAqXG4gICAqL1xuICAvLyBzdGF0aWMgaW5pdChwYXJlbnQpIHtcbiAgLy8gICByZXR1cm4gbmV3IE1lcmdlQ2hhaW4ocGFyZW50KVxuICAvLyB9XG5cbiAgLyoqXG4gICAqIEBpbmhlcml0ZG9jXG4gICAqL1xuICBjb25zdHJ1Y3RvcihwYXJlbnQpIHtcbiAgICBzdXBlcihwYXJlbnQpXG5cbiAgICAvKiBwcmV0dGllci1pZ25vcmUgKi9cbiAgICB0aGlzXG4gICAgICAuZXh0ZW5kKFtPTl9FWElTVElOR19LRVksIE9OX1ZBTFVFX0tFWSwgT0JKX0tFWV0pXG4gICAgICAuc2V0KE9OX1ZBTFVFX0tFWSwgKCkgPT4gdHJ1ZSlcbiAgICAgIC5zZXQoTUVSR0VSX0tFWSwgZG9wZW1lcmdlKVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjIG9wdGlvbnMgZm9yIG1lcmdpbmcgd2l0aCBkb3BlbWVyZ2VcbiAgICogICAgICAgQG1vZGlmaWVzIHRoaXMubWVyZ2VyIHwgdGhpcy5vcHRzXG4gICAqXG4gICAqIEBtZW1iZXJPZiBNZXJnZUNoYWluXG4gICAqIEBzaW5jZSAxLjAuMlxuICAgKiBAcGFyYW0gIHtPYmplY3QgfCBGdW5jdGlvbn0gb3B0cyB3aGVuIG9iamVjdDogb3B0aW9ucyBmb3IgdGhlIG1lcmdlci4gd2hlbiBmdW5jdGlvbjogaXMgdGhlIG1lcmdlclxuICAgKiBAcmV0dXJuIHtNZXJnZUNoYWlufSBAY2hhaW5hYmxlXG4gICAqIEBzZWUgZG9wZW1lcmdlXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqICAge1xuICAgKiAgICAgc3RyaW5nVG9BcnJheTogdHJ1ZSxcbiAgICogICAgIGJvb2xUb0FycmF5OiBmYWxzZSxcbiAgICogICAgIGJvb2xBc1JpZ2h0OiB0cnVlLFxuICAgKiAgICAgaWdub3JlVHlwZXM6IFsnbnVsbCcsICd1bmRlZmluZWQnLCAnTmFOJ10sXG4gICAqICAgICBkZWJ1ZzogZmFsc2UsXG4gICAqICAgfVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiAgICAubWVyZ2VyKHJlcXVpcmUoJ2xvZGFzaC5tZXJnZXdpdGgnKSgpKVxuICAgKi9cbiAgbWVyZ2VyKG9wdHMpIHtcbiAgICBpZiAoaXNGdW5jdGlvbihvcHRzKSkgcmV0dXJuIHRoaXMuc2V0KE1FUkdFUl9LRVksIG9wdHMpXG4gICAgZWxzZSByZXR1cm4gdGhpcy5zZXQoTUVSR0VSX09QVElPTlNfS0VZLCBvcHRzKVxuICB9XG5cbiAgLy8gW3ZdIG1lc3NlcyBjb21tZW50cyBvbiBjb25kaXRpb25hbCBicmFjZSBzdHlsZVxuICAvKiBwcmV0dGllci1pZ25vcmUgKi9cbiAgLyoqXG4gICAqIEBkZXNjIG1lcmdlcyBvYmplY3QgaW4sIGdvZXMgdGhyb3VnaCBhbGwga2V5cywgY2hlY2tzIGNicywgZG9wZW1lcmdlc1xuICAgKlxuICAgKiBAc2luY2UgMS4wLjBcbiAgICpcbiAgICogQHBhcmFtICB7T2JqZWN0fSBbb2JqMj11bmRlZmluZWRdIG9iamVjdCB0byBtZXJnZSBpbiwgZGVmYXVsdHMgdG8gdGhpcy5nZXQoJ29iaicpXG4gICAqIEByZXR1cm4ge01lcmdlQ2hhaW59IEBjaGFpbmFibGVcbiAgICpcbiAgICogQHNlZSBDaGFpbmVkTWFwXG4gICAqIEBUT0RPIGlzc3VlIGhlcmUgaWYgd2UgZXh0ZW5kIHdpdGhvdXQgc2hvcnRoYW5kcyAmXG4gICAqICAgICAgIHdlIHdhbnQgdG8gbWVyZ2UgZXhpc3RpbmcgdmFsdWVzLi4uIDpzXG4gICAqXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqICBjb25zdCBjaGFpbiA9IG5ldyBDaGFpbigpXG4gICAqICBjaGFpbi5tZXJnZSh7Y2FuYWRhOiB7ZWg6IHRydWV9fSlcbiAgICogIGNoYWluLm1lcmdlKHtjYW5hZGE6IHthcnI6IFswLCB7JzEnOiAyfV0sIGVoOiB7YWdhaW46IHRydWV9fX0pXG4gICAqICBjaGFpbi5lbnRyaWVzKClcbiAgICogIC8vPT4ge2NhbmFkYTp7IGVoOiB7YWdhaW46IHRydWV9LCBhcnI6IFswLCB7JzEnOiAyfV0gfX1cbiAgICpcbiAgICovXG4gIG1lcmdlKG9iajIpIHtcbiAgICAvLyBiZXR0ZXIgdWdsaWZ5aW5nXG4gICAgY29uc3QgcGFyZW50ID0gdGhpcy5wYXJlbnRcbiAgICBjb25zdCBnZXQgPSBrZXkgPT4gdGhpcy5nZXQoa2V5KVxuXG4gICAgY29uc3Qgb25FeGlzdGluZyA9IGdldChPTl9FWElTVElOR19LRVkpXG4gICAgY29uc3Qgb25WYWx1ZSA9IGdldChPTl9WQUxVRV9LRVkpXG4gICAgY29uc3Qgb3B0cyA9IGdldChNRVJHRVJfT1BUSU9OU19LRVkpXG4gICAgY29uc3Qgb2JqID0gb2JqMiB8fCBnZXQoT0JKX0tFWSlcbiAgICBjb25zdCBtZXJnZXIgPSBnZXQoTUVSR0VSX0tFWSlcbiAgICBjb25zdCBzaG9ydGhhbmRzID0gcGFyZW50Lm1ldGEgPyBwYXJlbnQubWV0YShTSE9SVEhBTkRTX0tFWSkgOiBFTVBUWV9PQkpcbiAgICBjb25zdCBrZXlzID0gT2JqZWN0S2V5cyhvYmopXG5cbiAgICAvLyBAQGRlYnVnZ2VyXG5cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogZGV2cyAqL1xuICAgIGlmIChFTlZfREVWRUxPUE1FTlQpIHtcbiAgICAgIGlmICghb2JqKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKHtvbkV4aXN0aW5nLCBvcHRzLCBvYmosIG1lcmdlciwgc2hvcnRoYW5kcywga2V5cywgcGFyZW50fSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdtdXN0IHByb3ZpZGUgYW4gb2JqZWN0IHRvIG1lcmdlJylcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqXG4gICAgICogc2luY2UgdGhpcyB3b3VsZCBiZSBzbG93ZXJcbiAgICAgKiBpZiBJIHdhbnQgdG8gbm90IGhhdmUgYSBzcGVlZHkgZGVmYXVsdCB3aGVuIHVzaW5nIC5vbkV4aXN0aW5nXG4gICAgICogc2hvdWxkIEBub3RlIHRvIHVzZSAuZXh0ZW5kXG4gICAgICogd2hlbiB1c2luZyBjaGFpbnMgd2l0aG91dCBhIGNsYXNzICYgZG9pbmcgLm1lcmdlIChlZGdlLWNhc2UpXG4gICAgICpcbiAgICAgKiBAcGFyYW0gIHtQcmltaXRpdmV9IGtleSBrZXkgKHNob3J0aGFuZHNba2V5XSBvciBqdXN0IGtleSlcbiAgICAgKiBAcGFyYW0gIHsqfSB2YWx1ZSBvYmpba2V5XVxuICAgICAqIEByZXR1cm4ge3ZvaWR9XG4gICAgICpcbiAgICAgKiBAVE9ETyBjb3VsZCB1c2UgLmVxIGhlcmVcbiAgICAgKiBAVE9ETyBpZiAoaXNNYXBpc2gob2JqKSkgb2JqID0gb2JqLmVudHJpZXMoKVxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiAgdmFyIG9iaiA9IHtrZXk6IDF9XG4gICAgICpcbiAgICAgKiAgTWVyZ2VDaGFpbi5pbml0KG9iaikubWVyZ2Uoe2tleTogWyd2YWx1ZSddfSlcbiAgICAgKlxuICAgICAqICAvLyBnb2VzIHRvIHRoaXMgaW50ZXJuYWwgc2NvcGVkIGZ1bmN0aW9uXG4gICAgICogIGhhbmRsZUV4aXN0aW5nKCdrZXknLCBbJ3ZhbHVlJ10pXG4gICAgICogIC8vIGlmIHRoZXJlIGlzIC5vblZhbHVlIG9yIC5vbkV4aXN0aW5nLCB1c2UgdGhlbSwgZGVmYXVsdCBkZWVwbWVyZ2VcbiAgICAgKlxuICAgICAqICBvYmpcbiAgICAgKiAgLy89PiB7a2V5OiBbMSwgJ3ZhbHVlJ119XG4gICAgICpcbiAgICAgKi9cbiAgICBjb25zdCBoYW5kbGVFeGlzdGluZyA9IChrZXksIHZhbHVlKSA9PiB7XG4gICAgICAvKipcbiAgICAgICAqIEBkZXNjIHdoZW4gZm4gaXMgYSBmdWxsIG1ldGhvZCwgbm90IGFuIGV4dGVuZGVkIHNob3J0aGFuZFxuICAgICAgICogQHNpbmNlIDAuNS4wXG4gICAgICAgKlxuICAgICAgICogQHBhcmFtIHtQcmltaXRpdmV9IGtleVRvU2V0IGtleSB3ZSBjaG9zZSB0byBzZXRcbiAgICAgICAqIEBwYXJhbSB7Kn0gdmFsdWVUb1NldCB2YWx1ZSB3ZSBjaG9zZSB0byBzZXQgKG1lcmdlZCwgZXhpc3RpbmcsIG5ldylcbiAgICAgICAqIEByZXR1cm4ge1BhcmVudCB8IENoYWluIHwgKn0gLnNldCBvciBba2V5VG9TZXRdIHJldHVyblxuICAgICAgICpcbiAgICAgICAqIEBleGFtcGxlXG4gICAgICAgKlxuICAgICAgICogICAgTWVyZ2VDaGFpbi5pbml0KG5ldyBDaGFpbigpLmV4dGVuZChbJ2VoJ10pKVxuICAgICAgICpcbiAgICAgICAqICAgIC8vaXNGdW5jdGlvbjogdHJ1ZSA9PiBjYWxsIHBhcmVudFtrZXlUb1NldF0odmFsdWVUb1NldClcbiAgICAgICAqICAgIHNldENob3NlbignZWgnLCAxKVxuICAgICAgICogICAgLy89PiBwYXJlbnRcbiAgICAgICAqICAgIHBhcmVudC5nZXQoJ2VoJylcbiAgICAgICAqICAgIC8vPT4gMVxuICAgICAgICpcbiAgICAgICAqICAgIC8vPT5pc0Z1bmN0aW9uOiBmYWxzZSA9PiBwYXJlbnQuc2V0KGtleVRvU2V0LCB2YWx1ZVRvU2V0KVxuICAgICAgICogICAgc2V0Q2hvc2VuKCdvaCcsIDEpXG4gICAgICAgKiAgICAvLz0+IHBhcmVudCAvLzwtIHVubGVzcyAuc2V0IGlzIG92ZXJyaWRlblxuICAgICAgICogICAgcGFyZW50LmdldCgnb2gnKVxuICAgICAgICogICAgLy89PiAxXG4gICAgICAgKlxuICAgICAgICovXG4gICAgICBjb25zdCBzZXRDaG9zZW4gPSAoa2V5VG9TZXQsIHZhbHVlVG9TZXQpID0+XG4gICAgICAgIChpc0Z1bmN0aW9uKHBhcmVudFtrZXldKVxuICAgICAgICAgID8gcGFyZW50W2tleVRvU2V0XSh2YWx1ZVRvU2V0KVxuICAgICAgICAgIDogcGFyZW50LnNldChrZXlUb1NldCwgdmFsdWVUb1NldCkpXG5cbiAgICAgIC8qKlxuICAgICAgICogY2hlY2sgaWYgaXQncyBzaG9ydGhhbmRlZFxuICAgICAgICogLT4gY2hlY2sgaWYgaXQgaGFzIGEgdmFsdWUgYWxyZWFkeVxuICAgICAgICovXG4gICAgICBpZiAoaXNUcnVlKHBhcmVudC5oYXMoa2V5KSkpIHtcbiAgICAgICAgLy8gZ2V0IHRoYXQgdmFsdWVcbiAgICAgICAgY29uc3QgZXhpc3RpbmcgPSBwYXJlbnQuZ2V0KGtleSlcblxuICAgICAgICAvKipcbiAgICAgICAgICogaWYgd2UgaGF2ZSBvbkV4aXN0aW5nLCBjYWxsIGl0XG4gICAgICAgICAqIGVsc2UgZGVmYXVsdCB0byBkb3BlbWVyZ2VcbiAgICAgICAgICovXG4gICAgICAgIGlmIChpc1VuZGVmaW5lZChvbkV4aXN0aW5nKSkge1xuICAgICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBkZXZzICovXG4gICAgICAgICAgaWYgKEVOVl9ERUJVRykge1xuICAgICAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgICAgICdwYXJlbnQgaGFzOiBubyBvbkV4aXN0aW5nJyxcbiAgICAgICAgICAgICAge2V4aXN0aW5nLCBba2V5XTogdmFsdWV9XG4gICAgICAgICAgICApXG4gICAgICAgICAgfVxuICAgICAgICAgIHNldENob3NlbihrZXksIG1lcmdlcihleGlzdGluZywgdmFsdWUsIG9wdHMpKVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBkZXZzICovXG4gICAgICAgICAgaWYgKEVOVl9ERUJVRykge1xuICAgICAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgICAgICdwYXJlbnQgaGFzOiBoYXMgb25FeGlzdGluZycsXG4gICAgICAgICAgICAgIHtleGlzdGluZywgb25FeGlzdGluZywgW2tleV06IHZhbHVlfVxuICAgICAgICAgICAgKVxuICAgICAgICAgIH1cblxuICAgICAgICAgIC8qKlxuICAgICAgICAgICAqIG1heWJlIHdlIHNob3VsZCBub3QgZXZlbiBoYXZlIGAub25FeGlzdGluZ2BcbiAgICAgICAgICAgKiBzaW5jZSB3ZSBjYW4ganVzdCBvdmVycmlkZSBtZXJnZSBtZXRob2QuLi5cbiAgICAgICAgICAgKiBhbmQgdGhlbiBjbGllbnQgY2FuIGp1c3QgdXNlIGEgY3VzdG9tIG1lcmdlci4uLlxuICAgICAgICAgICAqXG4gICAgICAgICAgICogY291bGQgYWRkIGFuZCByZW1vdmUgc3Vic2NyaWJlciBidXQgdGhhdCdzIG92ZXJoZWFkIGFuZFxuICAgICAgICAgICAqIHRyaWNreSBoZXJlLCBiZWNhdXNlIGlmIHdlIHNldCBhIHZhbHVlIHRoYXQgd2FzIGp1c3Qgc2V0Li4uXG4gICAgICAgICAgICovXG4gICAgICAgICAgc2V0Q2hvc2VuKGtleSwgb25FeGlzdGluZyhleGlzdGluZywgdmFsdWUsIG9wdHMpKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQ6IGRldnMgKi9cbiAgICAgICAgaWYgKEVOVl9ERUJVRykge1xuICAgICAgICAgIGNvbnNvbGUubG9nKCdwYXJlbnQgZG9lcyBub3QgaGF2ZScsIHtba2V5XTogdmFsdWV9KVxuICAgICAgICB9XG4gICAgICAgIHNldENob3NlbihrZXksIHZhbHVlKVxuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAobGV0IGsgPSAwLCBsZW4gPSBrZXlzLmxlbmd0aDsgayA8IGxlbjsgaysrKSB7XG4gICAgICAvLyBrZXkgdG8gdGhlIGN1cnJlbnQgcHJvcGVydHkgaW4gdGhlIGRhdGEgYmVpbmcgbWVyZ2VkXG4gICAgICBsZXQga2V5ID0ga2V5c1trXVxuXG4gICAgICAvLyB3ZSBoYXZlIG91ciB2YWx1ZSwgbm8gd2UgY2FuIGNoYW5nZSB0aGUga2V5IGlmIG5lZWRlZCBmb3Igc2hvcnRoYW5kc1xuICAgICAgY29uc3QgdmFsdWUgPSBvYmpba2V5XVxuXG4gICAgICAvLyBATk9URTogd2hlbiBzaG9ydGhhbmRzIGlzIGFuIG9iamVjdCwga2V5IGlzIHRoZSBtZXRob2QgaXQgc2hvdWxkIGNhbGxcbiAgICAgIGlmICghaXNVbmRlZmluZWQoc2hvcnRoYW5kc1trZXldKSAmJiBzaG9ydGhhbmRzW2tleV0gIT09IGtleSkge1xuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogZGV2cyAqL1xuICAgICAgICBpZiAoRU5WX0RFQlVHKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgICAnaGFkIGEgc2hvcnRoYW5kIHdpdGggYSBkaWZmIGtleSB0aGFuIHRoZSBvYmplY3QgKGxpa2VseSBAYWxpYXMpJyxcbiAgICAgICAgICAgIHtzaG9ydGhhbmRNZXRob2Q6IHNob3J0aGFuZHNba2V5XSwga2V5LCB2YWx1ZX1cbiAgICAgICAgICApXG4gICAgICAgIH1cbiAgICAgICAga2V5ID0gc2hvcnRoYW5kc1trZXldXG4gICAgICB9XG5cbiAgICAgIC8vIG1ldGhvZCBmb3IgdGhlIGtleVxuICAgICAgY29uc3QgbWV0aG9kID0gcGFyZW50W2tleV1cblxuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQ6IHNvdXJjZW1hcHMgdHJpZ2dlciBpc3RhbmJ1bCBoZXJlIGluY29ycmVjdGx5ICovXG4gICAgICAvLyB1c2Ugb25WYWx1ZSB3aGVuIHNldFxuICAgICAgaWYgKCFvblZhbHVlKHZhbHVlLCBrZXksIHRoaXMpKSB7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBkZXZzICovXG4gICAgICAgIGlmIChFTlZfREVCVUcpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZygnaGFkIG9uVmFsdWUsIHdhcyBmYWxzZSwgaWdub3JlZCcsIHtvblZhbHVlLCBrZXksIHZhbHVlfSlcbiAgICAgICAgfVxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgLy8gd2hlbiBwcm9wZXJ0eSBpdHNlbGYgaXMgYSBDaGFpbmFibGVcbiAgICAgIGVsc2UgaWYgKGlzTWFwaXNoKG1ldGhvZCkpIHtcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQ6IGRldnMgKi9cbiAgICAgICAgaWYgKEVOVl9ERUJVRykge1xuICAgICAgICAgIGNvbnNvbGUubG9nKCdoYXMgbWV0aG9kIG9yIHNob3J0aGFuZCcpXG4gICAgICAgIH1cbiAgICAgICAgcGFyZW50W2tleV0ubWVyZ2UodmFsdWUpXG4gICAgICB9XG4gICAgICAvLyB3ZSBoYXZlIGEgbWV0aG9kIG9yIHNob3J0aGFuZFxuICAgICAgZWxzZSBpZiAobWV0aG9kKSB7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBkZXZzICovXG4gICAgICAgIGlmIChFTlZfREVCVUcpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZygnaGFzIG1ldGhvZCBvciBzaG9ydGhhbmQnLCB7bWV0aG9kLCBrZXksIHZhbHVlfSlcbiAgICAgICAgfVxuICAgICAgICBoYW5kbGVFeGlzdGluZyhrZXksIHZhbHVlKVxuICAgICAgfVxuICAgICAgLy8gZGVmYXVsdCB0byAuc2V0IG9uIHRoZSBzdG9yZVxuICAgICAgZWxzZSB7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBkZXZzICovXG4gICAgICAgIGlmIChFTlZfREVCVUcpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZygnd2VudCB0byBkZWZhdWx0Jywge21ldGhvZCwga2V5LCB2YWx1ZX0pXG4gICAgICAgIH1cbiAgICAgICAgcGFyZW50LnNldChrZXksIHZhbHVlKVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBwYXJlbnRcbiAgfVxufVxuXG5jb25zdHJ1Y3RJbml0KE1lcmdlQ2hhaW4pXG5cbi8qKlxuICogQG1lbWJlck9mIE1lcmdlQ2hhaW5cbiAqIEBtZXRob2Qgb25FeGlzdGluZ1xuICogQHNpbmNlIDAuOS4wXG4gKiBAZXhhbXBsZVxuICpcbiAqICAgIGNvbnN0IHtDaGFpbiwgTWVyZ2VDaGFpbn0gPSByZXF1aXJlKCdjaGFpbi1hYmxlJylcbiAqXG4gKiAgICBjb25zdCBjaGFpbiA9IG5ldyBDaGFpbigpLnNldCgnc3RyJywgJ3N0cmluZ3knKVxuICpcbiAqICAgIE1lcmdlQ2hhaW4uaW5pdChjaGFpbilcbiAqICAgICAgLm9uRXhpc3RpbmcoKGEsIGIpID0+IGEgKyBiKVxuICogICAgICAubWVyZ2Uoe3N0cjogJysnfSlcbiAqXG4gKiAgICBjaGFpbi5nZXQoJ3N0cicpXG4gKiAgICAvLz0+ICdzdHJpbmd5KydcbiAqXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBNZXJnZUNoYWluXG5cbi8vIEBUT0RPIHJlLWVuYWJsZSB0aGlzIGxhdGVyXG4vLyBtb2R1bGUuZXhwb3J0cyA9IG5ldyBNZXRob2RDaGFpbihNZXJnZUNoYWluLnByb3RvdHlwZSlcbi8vICAgLm1ldGhvZHMoWydvbkV4aXN0aW5nJywgJ29uVmFsdWUnLCAnb2JqJ10pXG4vLyAgIC5idWlsZChNZXJnZUNoYWluKVxuIl0sIm5hbWVzIjpbImNvbnN0Iiwic3VwZXIiLCJ0aGlzIiwibGV0Il0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBQSxHQUFLLENBQUMsV0FBVyxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUM7QUFDNUNBLEdBQUssQ0FBQyxjQUFjLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixDQUFDO0FBQ2xEQSxHQUFLLENBQUMsU0FBUyxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQztBQUM3Q0EsR0FBSyxDQUFDLFVBQVUsR0FBRyxPQUFPLENBQUMsb0JBQW9CLENBQUM7QUFDaERBLEdBQUssQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDLHFCQUFxQixDQUFDO0FBQ2xEQSxHQUFLLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQztBQUN4Q0EsR0FBSyxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUMsa0JBQWtCLENBQUM7QUFDNUNBLEdBQUssQ0FBQyxVQUFVLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixDQUFDO0FBQzlDQSxHQUFLLENBQUMsYUFBYSxHQUFHLE9BQU8sQ0FBQyx5QkFBeUIsQ0FBQztBQUN4REEsR0FBSyxDQUFDLFNBQVMsR0FBRyxPQUFPLENBQUMseUJBQXlCLENBQUM7QUFDcERBLEdBQUssQ0FBQyxjQUFjLEdBQUcsT0FBTyxDQUFDLDRCQUE0QixDQUFDO0FBQzVE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