UNPKG

foop

Version:

interfaces that describe their intentions.

330 lines (304 loc) 29.7 kB
/* 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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