foop
Version:
interfaces that describe their intentions.
245 lines (224 loc) • 18.8 kB
JavaScript
var TraverseChain = require('../TraverseChain')
var curry = require('../deps/fp/curry')
var isObj = require('../deps/is/obj')
var isTrue = require('../deps/is/true')
var isFalsy = require('../deps/is/falsy')
var isUndefined = require('../deps/is/undefined')
var ObjectKeys = require('../deps/util/keys')
var dotPropPaths = require('../deps/dot/paths')
var TRANSFORMERS_KEY = require('../deps/meta/TRANSFORMERS_KEY')
var OBSERVERS_KEY = require('../deps/meta/OBSERVERS_KEY')
/**
* @param {Class | Composable} Target composable class
* @return {TransformChain} class
* @example
* compose(class {})
* //=> TransformChain
*/
module.exports = function (Target) {
var set = Target.prototype.set
/**
* @class TransformChain
* @member TransformChain
* @extends {ChainedMap}
* @memberOf compose
* @category Chainable
*
* @tests TransformChain
* @types TransformChain
*
* @symb 🤖
* @type {Map}
*
* @see deps/traverse
* @see TraverseChain
*
* {@link https://github.com/iluwatar/java-design-patterns/tree/master/state state-pattern}
* {@link https://github.com/iluwatar/java-design-patterns/tree/master/strategy strategy-pattern}
*/
// class Transform extends Target
// -------------------------------------------
/**
* @desc traverse `this`, or `this.entries`
* @since 1.0.2
*
* @param {boolean | traversable} [useThis=false] use the instance properties that are `mapish` as well
* @return {TraverseChain} @chainable
*
* @see TraverseChain
* @see js-traverse
*
* @example
* TAKE FROM TRAVERSECHAIN
*/
Target.prototype.traverse = function traverseChain(useThis) {
/* prettier-ignore */
return new TraverseChain(this)
.obj(
// @NOTE
// defaultTo(false, useThis)
// defaulting arg to false is shorter
// & faster than void 0 inline checks
// that mutate arguments (when transpiled)
isFalsy(useThis)
? this.entries(true)
: isTrue(useThis)
? this
: useThis
// isFalse(useThis)
// ? this.entries(true)
// : isTrue(useThis)
// ? this
// : useThis
)
}
/**
* @since 1.0.2
* @memberOf TransformChain
*
* @param {string | Function} key currently just string
* @param {Function} value callback accepting the value as only arg to transform with
* @return {TransformChain} @chainable
*
* @TODO dot-prop here
*
* @example
*
* // coerce values with .id into the value they hold
* chain
* .transform('dis', val => (typeof val === 'string' ? val : val.id))
*
* chain.set('dis', 'eh')
* chain.get('dis')
* //=> 'eh'
*
* chain.set('dis', {id: 'eh'})
* chain.get('dis')
* //=> 'eh'
*
*
* @example
*
* import {format} from 'date-fns/esm'
* import {Chain} from 'chain-able'
*
* const chain = new Chain()
* chain.transform('created_at', date => format(date, 'MM/DD/YYYY'))
* chain.set('created_at', new Date())
*
* // is formatted human-readable pretty!
* const {created_at} = chain.entries()
* //=> '02/11/2014'
*
*/
Target.prototype.transform = function transform(key, value) {
return this.meta(TRANSFORMERS_KEY, key, value)
}
/**
* @memberOf TransformChain
*
* @override
* @inheritdoc
* @since 1.0.0
*
* @TODO curry
*
* @param {Primitive} key key to set with
* @param {any} val value to set for key
* @param {undefined | string | Array<string>} dotPropKey special key used for initializing dot prop values in an optimized way to keep reference
* @return {Chainable} @chainable
*
* @see this.observe, this.transform
*/
Target.prototype.set = function transformSet(key, val, dotPropKey) {
var this$1 = this;
var value = val
// get
var transformers = this.meta(TRANSFORMERS_KEY, key)
for (var t = 0; t < transformers.length; t++) {
value = transformers[t].call(this$1, value, this$1)
}
// super.set(key, value)
set.call(this, key, value)
// get
var observers = this.meta(OBSERVERS_KEY)
// @TODO !isEmpty
// skip the below if we have no observers
if (!observers.length) {
return this
}
var data = {key: dotPropKey, value: value}
if (isUndefined(dotPropKey)) {
data.key = isObj(value) ? dotPropPaths(key, value) : key
}
for (var o = 0; o < observers.length; o++) {
observers[o](data)
}
return this
}
// @TODO
// // https://stackoverflow.com/questions/31158902/is-it-possible-to-sort-a-es6-map-object
// ordered(comperator = null) {
// // this.set = this.before(this.set)
// this.set = (key, value) => {
// // have to iterate over the keys before setting
// // and then after merging in values, update
// if (this.store.has(key)) {
// // first
// let keys = this.store.keys()
// if (isFunction(comperator)) keys = keys.sort(comperator)
//
// // after
// const store = this.store
// this.store = new Map()
// keys.forEach(keyInOrder => this.store.set(key, store.get(key)))
// store.clear()
// }
// }
// }
// --- remap ---
/**
* @desc remap properties from 1 to another, for example, apis with inconsistent naming
* @memberOf TransformChain
* @since 1.0.0
* @symb 🗺
*
* @param {string | Object} from property name string, or {[from]: to}
* @param {string} [to=undefined] property name to change key to
* @return {Chain} @chainable
*
* @see TransformChain.transform
* @IDEA could also be a function, but then might as well use .transform
*
* @example
*
* chain
* .remap('dis', 'dat')
* .from({dis: true})
*
* chain.entries()
* //=> {dat: true}
*
* @example
*
* chain
* .remap({dis: 'dat'})
* .from({dis: 1, other: true}}
*
* chain.entries()
* //=> {dist: 1, other: true}
*
*/
Target.prototype.remap = function chainRemap(from, to) {
var this$1 = this;
var remap = isObj(from) ? from : {[from]: to}
/* prettier-ignore */
ObjectKeys(remap).forEach(function (key) { return this$1.transform(key, function (val) {
this$1.set(remap[key], val)
return val
}); })
return this
}
return Target
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVHJhbnNmb3JtLmpzIiwic291cmNlcyI6WyJUcmFuc2Zvcm0uanMiXSwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgVHJhdmVyc2VDaGFpbiA9IHJlcXVpcmUoJy4uL1RyYXZlcnNlQ2hhaW4nKVxuY29uc3QgY3VycnkgPSByZXF1aXJlKCcuLi9kZXBzL2ZwL2N1cnJ5JylcbmNvbnN0IGlzT2JqID0gcmVxdWlyZSgnLi4vZGVwcy9pcy9vYmonKVxuY29uc3QgaXNUcnVlID0gcmVxdWlyZSgnLi4vZGVwcy9pcy90cnVlJylcbmNvbnN0IGlzRmFsc3kgPSByZXF1aXJlKCcuLi9kZXBzL2lzL2ZhbHN5JylcbmNvbnN0IGlzVW5kZWZpbmVkID0gcmVxdWlyZSgnLi4vZGVwcy9pcy91bmRlZmluZWQnKVxuY29uc3QgT2JqZWN0S2V5cyA9IHJlcXVpcmUoJy4uL2RlcHMvdXRpbC9rZXlzJylcbmNvbnN0IGRvdFByb3BQYXRocyA9IHJlcXVpcmUoJy4uL2RlcHMvZG90L3BhdGhzJylcbmNvbnN0IFRSQU5TRk9STUVSU19LRVkgPSByZXF1aXJlKCcuLi9kZXBzL21ldGEvVFJBTlNGT1JNRVJTX0tFWScpXG5jb25zdCBPQlNFUlZFUlNfS0VZID0gcmVxdWlyZSgnLi4vZGVwcy9tZXRhL09CU0VSVkVSU19LRVknKVxuXG4vKipcbiAqIEBwYXJhbSB7Q2xhc3MgfCBDb21wb3NhYmxlfSBUYXJnZXQgY29tcG9zYWJsZSBjbGFzc1xuICogQHJldHVybiB7VHJhbnNmb3JtQ2hhaW59IGNsYXNzXG4gKiBAZXhhbXBsZVxuICogICAgY29tcG9zZShjbGFzcyB7fSlcbiAqICAgIC8vPT4gVHJhbnNmb3JtQ2hhaW5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBUYXJnZXQgPT4ge1xuICBjb25zdCBzZXQgPSBUYXJnZXQucHJvdG90eXBlLnNldFxuXG4gIC8qKlxuICAgKiBAY2xhc3MgVHJhbnNmb3JtQ2hhaW5cbiAgICogQG1lbWJlciBUcmFuc2Zvcm1DaGFpblxuICAgKiBAZXh0ZW5kcyB7Q2hhaW5lZE1hcH1cbiAgICogQG1lbWJlck9mIGNvbXBvc2VcbiAgICogQGNhdGVnb3J5IENoYWluYWJsZVxuICAgKlxuICAgKiBAdGVzdHMgVHJhbnNmb3JtQ2hhaW5cbiAgICogQHR5cGVzIFRyYW5zZm9ybUNoYWluXG4gICAqXG4gICAqIEBzeW1iIPCfpJZcbiAgICogQHR5cGUge01hcH1cbiAgICpcbiAgICogQHNlZSBkZXBzL3RyYXZlcnNlXG4gICAqIEBzZWUgVHJhdmVyc2VDaGFpblxuICAgKlxuICAgKiB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2lsdXdhdGFyL2phdmEtZGVzaWduLXBhdHRlcm5zL3RyZWUvbWFzdGVyL3N0YXRlIHN0YXRlLXBhdHRlcm59XG4gICAqIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vaWx1d2F0YXIvamF2YS1kZXNpZ24tcGF0dGVybnMvdHJlZS9tYXN0ZXIvc3RyYXRlZ3kgc3RyYXRlZ3ktcGF0dGVybn1cbiAgICovXG4gIC8vIGNsYXNzIFRyYW5zZm9ybSBleHRlbmRzIFRhcmdldFxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgLyoqXG4gICAqIEBkZXNjIHRyYXZlcnNlIGB0aGlzYCwgb3IgYHRoaXMuZW50cmllc2BcbiAgICogQHNpbmNlIDEuMC4yXG4gICAqXG4gICAqIEBwYXJhbSAge2Jvb2xlYW4gfCB0cmF2ZXJzYWJsZX0gW3VzZVRoaXM9ZmFsc2VdIHVzZSB0aGUgaW5zdGFuY2UgcHJvcGVydGllcyB0aGF0IGFyZSBgbWFwaXNoYCBhcyB3ZWxsXG4gICAqIEByZXR1cm4ge1RyYXZlcnNlQ2hhaW59IEBjaGFpbmFibGVcbiAgICpcbiAgICogQHNlZSBUcmF2ZXJzZUNoYWluXG4gICAqIEBzZWUganMtdHJhdmVyc2VcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogIFRBS0UgRlJPTSBUUkFWRVJTRUNIQUlOXG4gICAqL1xuICBUYXJnZXQucHJvdG90eXBlLnRyYXZlcnNlID0gZnVuY3Rpb24gdHJhdmVyc2VDaGFpbih1c2VUaGlzKSB7XG4gICAgLyogcHJldHRpZXItaWdub3JlICovXG4gICAgcmV0dXJuIG5ldyBUcmF2ZXJzZUNoYWluKHRoaXMpXG4gICAgICAub2JqKFxuICAgICAgICAvLyBATk9URVxuICAgICAgICAvLyBkZWZhdWx0VG8oZmFsc2UsIHVzZVRoaXMpXG4gICAgICAgIC8vICBkZWZhdWx0aW5nIGFyZyB0byBmYWxzZSBpcyBzaG9ydGVyXG4gICAgICAgIC8vICAmIGZhc3RlciB0aGFuIHZvaWQgMCBpbmxpbmUgY2hlY2tzXG4gICAgICAgIC8vICB0aGF0IG11dGF0ZSBhcmd1bWVudHMgKHdoZW4gdHJhbnNwaWxlZClcbiAgICAgICAgaXNGYWxzeSh1c2VUaGlzKVxuICAgICAgICAgID8gdGhpcy5lbnRyaWVzKHRydWUpXG4gICAgICAgICAgOiBpc1RydWUodXNlVGhpcylcbiAgICAgICAgICAgID8gdGhpc1xuICAgICAgICAgICAgOiB1c2VUaGlzXG5cbiAgICAgICAgLy8gaXNGYWxzZSh1c2VUaGlzKVxuICAgICAgICAvLyAgID8gdGhpcy5lbnRyaWVzKHRydWUpXG4gICAgICAgIC8vICAgOiBpc1RydWUodXNlVGhpcylcbiAgICAgICAgLy8gICAgID8gdGhpc1xuICAgICAgICAvLyAgICAgOiB1c2VUaGlzXG4gICAgICApXG4gIH1cblxuICAvKipcbiAgICogQHNpbmNlIDEuMC4yXG4gICAqIEBtZW1iZXJPZiBUcmFuc2Zvcm1DaGFpblxuICAgKlxuICAgKiBAcGFyYW0gIHtzdHJpbmcgfCBGdW5jdGlvbn0ga2V5IGN1cnJlbnRseSBqdXN0IHN0cmluZ1xuICAgKiBAcGFyYW0gIHtGdW5jdGlvbn0gdmFsdWUgY2FsbGJhY2sgYWNjZXB0aW5nIHRoZSB2YWx1ZSBhcyBvbmx5IGFyZyB0byB0cmFuc2Zvcm0gd2l0aFxuICAgKiBAcmV0dXJuIHtUcmFuc2Zvcm1DaGFpbn0gQGNoYWluYWJsZVxuICAgKlxuICAgKiBAVE9ETyBkb3QtcHJvcCBoZXJlXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqICAgLy8gY29lcmNlIHZhbHVlcyB3aXRoIC5pZCBpbnRvIHRoZSB2YWx1ZSB0aGV5IGhvbGRcbiAgICogICBjaGFpblxuICAgKiAgICAgLnRyYW5zZm9ybSgnZGlzJywgdmFsID0+ICh0eXBlb2YgdmFsID09PSAnc3RyaW5nJyA/IHZhbCA6IHZhbC5pZCkpXG4gICAqXG4gICAqICAgY2hhaW4uc2V0KCdkaXMnLCAnZWgnKVxuICAgKiAgIGNoYWluLmdldCgnZGlzJylcbiAgICogICAvLz0+ICdlaCdcbiAgICpcbiAgICogICBjaGFpbi5zZXQoJ2RpcycsIHtpZDogJ2VoJ30pXG4gICAqICAgY2hhaW4uZ2V0KCdkaXMnKVxuICAgKiAgIC8vPT4gJ2VoJ1xuICAgKlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKlxuICAgKiAgICBpbXBvcnQge2Zvcm1hdH0gZnJvbSAnZGF0ZS1mbnMvZXNtJ1xuICAgKiAgICBpbXBvcnQge0NoYWlufSBmcm9tICdjaGFpbi1hYmxlJ1xuICAgKlxuICAgKiAgICBjb25zdCBjaGFpbiA9IG5ldyBDaGFpbigpXG4gICAqICAgIGNoYWluLnRyYW5zZm9ybSgnY3JlYXRlZF9hdCcsIGRhdGUgPT4gZm9ybWF0KGRhdGUsICdNTS9ERC9ZWVlZJykpXG4gICAqICAgIGNoYWluLnNldCgnY3JlYXRlZF9hdCcsIG5ldyBEYXRlKCkpXG4gICAqXG4gICAqICAgIC8vIGlzIGZvcm1hdHRlZCBodW1hbi1yZWFkYWJsZSBwcmV0dHkhXG4gICAqICAgIGNvbnN0IHtjcmVhdGVkX2F0fSA9IGNoYWluLmVudHJpZXMoKVxuICAgKiAgICAvLz0+ICcwMi8xMS8yMDE0J1xuICAgKlxuICAgKi9cbiAgVGFyZ2V0LnByb3RvdHlwZS50cmFuc2Zvcm0gPSBmdW5jdGlvbiB0cmFuc2Zvcm0oa2V5LCB2YWx1ZSkge1xuICAgIHJldHVybiB0aGlzLm1ldGEoVFJBTlNGT1JNRVJTX0tFWSwga2V5LCB2YWx1ZSlcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWVtYmVyT2YgVHJhbnNmb3JtQ2hhaW5cbiAgICpcbiAgICogQG92ZXJyaWRlXG4gICAqIEBpbmhlcml0ZG9jXG4gICAqIEBzaW5jZSAxLjAuMFxuICAgKlxuICAgKiBAVE9ETyBjdXJyeVxuICAgKlxuICAgKiBAcGFyYW0ge1ByaW1pdGl2ZX0ga2V5IGtleSB0byBzZXQgd2l0aFxuICAgKiBAcGFyYW0ge2FueX0gdmFsIHZhbHVlIHRvIHNldCBmb3Iga2V5XG4gICAqIEBwYXJhbSB7dW5kZWZpbmVkIHwgc3RyaW5nIHwgQXJyYXk8c3RyaW5nPn0gZG90UHJvcEtleSBzcGVjaWFsIGtleSB1c2VkIGZvciBpbml0aWFsaXppbmcgZG90IHByb3AgdmFsdWVzIGluIGFuIG9wdGltaXplZCB3YXkgdG8ga2VlcCByZWZlcmVuY2VcbiAgICogQHJldHVybiB7Q2hhaW5hYmxlfSBAY2hhaW5hYmxlXG4gICAqXG4gICAqIEBzZWUgdGhpcy5vYnNlcnZlLCB0aGlzLnRyYW5zZm9ybVxuICAgKi9cbiAgVGFyZ2V0LnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbiB0cmFuc2Zvcm1TZXQoa2V5LCB2YWwsIGRvdFByb3BLZXkpIHtcbiAgICBsZXQgdmFsdWUgPSB2YWxcblxuICAgIC8vIGdldFxuICAgIGNvbnN0IHRyYW5zZm9ybWVycyA9IHRoaXMubWV0YShUUkFOU0ZPUk1FUlNfS0VZLCBrZXkpXG4gICAgZm9yIChsZXQgdCA9IDA7IHQgPCB0cmFuc2Zvcm1lcnMubGVuZ3RoOyB0KyspIHtcbiAgICAgIHZhbHVlID0gdHJhbnNmb3JtZXJzW3RdLmNhbGwodGhpcywgdmFsdWUsIHRoaXMpXG4gICAgfVxuXG4gICAgLy8gc3VwZXIuc2V0KGtleSwgdmFsdWUpXG4gICAgc2V0LmNhbGwodGhpcywga2V5LCB2YWx1ZSlcblxuICAgIC8vIGdldFxuICAgIGNvbnN0IG9ic2VydmVycyA9IHRoaXMubWV0YShPQlNFUlZFUlNfS0VZKVxuXG4gICAgLy8gQFRPRE8gIWlzRW1wdHlcbiAgICAvLyBza2lwIHRoZSBiZWxvdyBpZiB3ZSBoYXZlIG5vIG9ic2VydmVyc1xuICAgIGlmICghb2JzZXJ2ZXJzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIHRoaXNcbiAgICB9XG5cbiAgICBjb25zdCBkYXRhID0ge2tleTogZG90UHJvcEtleSwgdmFsdWV9XG4gICAgaWYgKGlzVW5kZWZpbmVkKGRvdFByb3BLZXkpKSB7XG4gICAgICBkYXRhLmtleSA9IGlzT2JqKHZhbHVlKSA/IGRvdFByb3BQYXRocyhrZXksIHZhbHVlKSA6IGtleVxuICAgIH1cblxuICAgIGZvciAobGV0IG8gPSAwOyBvIDwgb2JzZXJ2ZXJzLmxlbmd0aDsgbysrKSB7XG4gICAgICBvYnNlcnZlcnNbb10oZGF0YSlcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgLy8gQFRPRE9cbiAgLy8gLy8gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMzExNTg5MDIvaXMtaXQtcG9zc2libGUtdG8tc29ydC1hLWVzNi1tYXAtb2JqZWN0XG4gIC8vIG9yZGVyZWQoY29tcGVyYXRvciA9IG51bGwpIHtcbiAgLy8gICAvLyB0aGlzLnNldCA9IHRoaXMuYmVmb3JlKHRoaXMuc2V0KVxuICAvLyAgIHRoaXMuc2V0ID0gKGtleSwgdmFsdWUpID0+IHtcbiAgLy8gICAgIC8vIGhhdmUgdG8gaXRlcmF0ZSBvdmVyIHRoZSBrZXlzIGJlZm9yZSBzZXR0aW5nXG4gIC8vICAgICAvLyBhbmQgdGhlbiBhZnRlciBtZXJnaW5nIGluIHZhbHVlcywgdXBkYXRlXG4gIC8vICAgICBpZiAodGhpcy5zdG9yZS5oYXMoa2V5KSkge1xuICAvLyAgICAgICAvLyBmaXJzdFxuICAvLyAgICAgICBsZXQga2V5cyA9IHRoaXMuc3RvcmUua2V5cygpXG4gIC8vICAgICAgIGlmIChpc0Z1bmN0aW9uKGNvbXBlcmF0b3IpKSBrZXlzID0ga2V5cy5zb3J0KGNvbXBlcmF0b3IpXG4gIC8vXG4gIC8vICAgICAgIC8vIGFmdGVyXG4gIC8vICAgICAgIGNvbnN0IHN0b3JlID0gdGhpcy5zdG9yZVxuICAvLyAgICAgICB0aGlzLnN0b3JlID0gbmV3IE1hcCgpXG4gIC8vICAgICAgIGtleXMuZm9yRWFjaChrZXlJbk9yZGVyID0+IHRoaXMuc3RvcmUuc2V0KGtleSwgc3RvcmUuZ2V0KGtleSkpKVxuICAvLyAgICAgICBzdG9yZS5jbGVhcigpXG4gIC8vICAgICB9XG4gIC8vICAgfVxuICAvLyB9XG5cbiAgLy8gLS0tIHJlbWFwIC0tLVxuICAvKipcbiAgICogQGRlc2MgcmVtYXAgcHJvcGVydGllcyBmcm9tIDEgdG8gYW5vdGhlciwgZm9yIGV4YW1wbGUsIGFwaXMgd2l0aCBpbmNvbnNpc3RlbnQgbmFtaW5nXG4gICAqIEBtZW1iZXJPZiBUcmFuc2Zvcm1DaGFpblxuICAgKiBAc2luY2UgMS4wLjBcbiAgICogQHN5bWIg8J+XulxuICAgKlxuICAgKiBAcGFyYW0gIHtzdHJpbmcgfCBPYmplY3R9IGZyb20gcHJvcGVydHkgbmFtZSBzdHJpbmcsIG9yIHtbZnJvbV06IHRvfVxuICAgKiBAcGFyYW0gIHtzdHJpbmd9IFt0bz11bmRlZmluZWRdIHByb3BlcnR5IG5hbWUgdG8gY2hhbmdlIGtleSB0b1xuICAgKiBAcmV0dXJuIHtDaGFpbn0gQGNoYWluYWJsZVxuICAgKlxuICAgKiBAc2VlIFRyYW5zZm9ybUNoYWluLnRyYW5zZm9ybVxuICAgKiBASURFQSBjb3VsZCBhbHNvIGJlIGEgZnVuY3Rpb24sIGJ1dCB0aGVuIG1pZ2h0IGFzIHdlbGwgdXNlIC50cmFuc2Zvcm1cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICpcbiAgICogIGNoYWluXG4gICAqICAgIC5yZW1hcCgnZGlzJywgJ2RhdCcpXG4gICAqICAgIC5mcm9tKHtkaXM6IHRydWV9KVxuICAgKlxuICAgKiAgY2hhaW4uZW50cmllcygpXG4gICAqICAvLz0+IHtkYXQ6IHRydWV9XG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqICBjaGFpblxuICAgKiAgICAucmVtYXAoe2RpczogJ2RhdCd9KVxuICAgKiAgICAuZnJvbSh7ZGlzOiAxLCBvdGhlcjogdHJ1ZX19XG4gICAqXG4gICAqICBjaGFpbi5lbnRyaWVzKClcbiAgICogIC8vPT4ge2Rpc3Q6IDEsIG90aGVyOiB0cnVlfVxuICAgKlxuICAgKi9cbiAgVGFyZ2V0LnByb3RvdHlwZS5yZW1hcCA9IGZ1bmN0aW9uIGNoYWluUmVtYXAoZnJvbSwgdG8pIHtcbiAgICBsZXQgcmVtYXAgPSBpc09iaihmcm9tKSA/IGZyb20gOiB7W2Zyb21dOiB0b31cblxuICAgIC8qIHByZXR0aWVyLWlnbm9yZSAqL1xuICAgIE9iamVjdEtleXMocmVtYXApLmZvckVhY2goa2V5ID0+IHRoaXMudHJhbnNmb3JtKGtleSwgdmFsID0+IHtcbiAgICAgIHRoaXMuc2V0KHJlbWFwW2tleV0sIHZhbClcbiAgICAgIHJldHVybiB2YWxcbiAgICB9KSlcblxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICByZXR1cm4gVGFyZ2V0XG59XG4iXSwibmFtZXMiOlsiY29uc3QiLCJsZXQiLCJ0aGlzIl0sIm1hcHBpbmdzIjoiQUFBQUEsR0FBSyxDQUFDLGFBQWEsR0FBRyxPQUFPLENBQUMsa0JBQWtCLENBQUM7QUFDakRBLEdBQUssQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixDQUFDO0FBQ3pDQSxHQUFLLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQztBQUN2Q0EsR0FBSyxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsaUJBQWlCLENBQUM7QUFDekNBLEdBQUssQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixDQUFDO0FBQzNDQSxHQUFLLENBQUMsV0FBVyxHQUFHLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQztBQUNuREEsR0FBSyxDQUFDLFVBQVUsR0FBRyxPQUFPLENBQUMsbUJBQW1CLENBQUM7QUFDL0NBLEdBQUssQ0FBQyxZQUFZLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixDQUFDO0FBQ2pEQSxHQUFLLENBQUMsZ0JBQWdCLEdBQUcsT0FBTyxDQUFDLCtCQUErQixDQUFDO0FBQ2pFQSxHQUFLLENB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