UNPKG

foop

Version:

interfaces that describe their intentions.

264 lines (239 loc) 19.6 kB
var ENV_DEBUG = require('./deps/env/debug') var ChainedMap = require('./ChainedMap') var isUndefined = require('./deps/is/undefined') var isTrue = require('./deps/is/true') var newSet = require('./deps/construct/set') var ON_CHAIN_UP_DOWN_KEY = 'onChainUpDown' var ON_DONE_KEY = 'onDone' /** * @extends {ChainedMapBase} * @inheritdoc * * @since 1.0.0 * * @prop {Object} data * @prop {Set} _calls * @type {Map} * * {@link http://robdodson.me/javascript-design-patterns-factory/ abstract-factory-pattern} * @see {@link abstract-factory-pattern} * * @member FactoryChain * @category Chainable * * @tests FactoryChain * @types FactoryChain */ var FactoryChain = (function (ChainedMap) { function FactoryChain(parent) { ChainedMap.call(this, parent) this.data = {} this._calls = new Set() this.factory() .extend(['optional', 'required', ON_CHAIN_UP_DOWN_KEY, ON_DONE_KEY]) .set('len', 0) } if ( ChainedMap ) FactoryChain.__proto__ = ChainedMap; FactoryChain.prototype = Object.create( ChainedMap && ChainedMap.prototype ); FactoryChain.prototype.constructor = FactoryChain; /** * @desc chain back up to parent for any of these * @since 2.0.0 * * @param {Array<string>} methods methods to trigger `onChainUpDown` on * @return {FactoryChain} @chainable * * @memberOf FactoryChain * @emits onChainUpDown * @TODO should have a debug log for this * * @example * * const {Chain, FactoryChain, ChainedSet} = require('chain-able') * * class Things extends Chain { * constructor(parent) { * super(parent) * this.people = new ChainedSet(this) * } * person() { * const person = new FactoryChain(this) * person * .props(['name', 'age', 'email']) * .onChainUpDown(this.person) * .chainUpDowns(['person']) * .onDone(personChain => { * this.people.add(personChain) * return this * }) * * return person * } * } * * const things = new Things() * const returned = things * .person() * .name('sue') * .person() * .age(100) * .name('john') * .email('@') * */ FactoryChain.prototype.chainUpDowns = function chainUpDowns (methods) { var arguments$1 = arguments; var this$1 = this; methods.forEach(function (m) { this$1[m] = function () { // @@debugger this$1.end() return this$1.parent[m].apply(this$1.parent, arguments$1) } }) return this }; /** * @desc adds an *array* of properties, using FactoryChain.prop * @since 2.0.0 * * @memberOf FactoryChain * @param {Array<string>} names property names * @return {FactoryChain} @chainable * * @see FactoryChain.prop * * @example * * person.props(['name', 'age', 'email']) * * typeof person.name * //=> 'function' * * person.name().age() * //=> FactoryChain * * person.name().age().email() * //=> ParentChain * * // person.name().age().person() * //=> FactoryChain * //^ because .person is `chainUpDowns` * //^ so it finishes the old chain, and begins a new one * */ FactoryChain.prototype.props = function props (names) { var this$1 = this; names.forEach(function (name) { return this$1.prop(name); }) return this }; /* istanbul ignore next: sourcemaps trigger istanbul here incorrectly */ /** * @desc add property that are counted towards the call count for easy auto-ending chaining * @since 2.0.0 * * @param {Primitive} name property name * @param {Function | null | undefined} [onCall=undefined] callback for the property * @return {FactoryChain} @chainable * * @memberOf FactoryChain * * @example * * person * //.prop also accepts an optional callback, * //for nestable nestable chains * .prop('name') * .prop('age') * .prop('email') * */ FactoryChain.prototype.prop = function prop (name, onCall) { var this$1 = this; this.tap('len', function (len) { return len + 1; }) // so if we call a property twice, // chain back up to parent, // add a new chain if (!isUndefined(this[name]) && isTrue(this.has(ON_CHAIN_UP_DOWN_KEY))) { this.end() return this.get(ON_CHAIN_UP_DOWN_KEY)()[name](onCall) } // @TODO need to spread as needed this[name] = function (args) { // @@debugger /* istanbul ignore next: devs */ if (ENV_DEBUG) { console.log( ("called " + name + " with:"), args, "calls length is now:", this$1._calls.size ) } if (isUndefined(onCall)) { this$1.data[name] = args } else { onCall(args) } this$1._calls.add(name) // aka magicReturn return this$1._calls.size === this$1.get('len') ? this$1.end() : this$1 } return this }; /** * @desc access data being built when stepping through a factory * @since 2.0.0 * * @param {Primitive} [prop=undefined] key of the data, or returns all data * @return {any} this.data * * @memberOf FactoryChain * * @example * * .data['prop'] = 'eh' * .getData('prop') * //=> 'eh' * .getData() * //=> {prop: 'eh'} * * @example * * const person = new FactoryChain(this) * const age = person.props(['name', 'age']).age(10).getData('age') * expect(age).toBe(10) * */ FactoryChain.prototype.getData = function getData (prop) { /* istanbul ignore next: sourcemaps trigger istanbul here incorrectly */ return isUndefined(prop) ? this.data : this.data[prop] }; /* istanbul ignore next: sourcemaps trigger istanbul here incorrectly */ /** * @desc creates/add the `.end` method, * which checks how many methods have been called, * and decides whether to return parent or not * @modifies this.end * * @since 2.0.0 * * @param {Object} [obj={}] optional object to use for creating .end * @return {FactoryChain} @chainable * * @memberOf FactoryChain */ FactoryChain.prototype.factory = function factory (obj) { var this$1 = this; this.end = function (arg) { // @@debugger var ended if (obj && !isUndefined(obj.end)) { ended = obj.end } else if (this$1.has(ON_DONE_KEY)) { ended = this$1.get(ON_DONE_KEY) } if (ended) { ended = ended.call(this$1, this$1.data, this$1.parent, this$1, arg) } if (ended && ended !== this$1) { return ended } else { return this$1.parent } } return this }; return FactoryChain; }(ChainedMap)); module.exports = FactoryChain //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmFjdG9yeUNoYWluLmpzIiwic291cmNlcyI6WyJGYWN0b3J5Q2hhaW4uanMiXSwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgRU5WX0RFQlVHID0gcmVxdWlyZSgnLi9kZXBzL2Vudi9kZWJ1ZycpXG5jb25zdCBDaGFpbmVkTWFwID0gcmVxdWlyZSgnLi9DaGFpbmVkTWFwJylcbmNvbnN0IGlzVW5kZWZpbmVkID0gcmVxdWlyZSgnLi9kZXBzL2lzL3VuZGVmaW5lZCcpXG5jb25zdCBpc1RydWUgPSByZXF1aXJlKCcuL2RlcHMvaXMvdHJ1ZScpXG5jb25zdCBuZXdTZXQgPSByZXF1aXJlKCcuL2RlcHMvY29uc3RydWN0L3NldCcpXG5cbmNvbnN0IE9OX0NIQUlOX1VQX0RPV05fS0VZID0gJ29uQ2hhaW5VcERvd24nXG5jb25zdCBPTl9ET05FX0tFWSA9ICdvbkRvbmUnXG5cbi8qKlxuICogQGV4dGVuZHMge0NoYWluZWRNYXBCYXNlfVxuICogQGluaGVyaXRkb2NcbiAqXG4gKiBAc2luY2UgMS4wLjBcbiAqXG4gKiBAcHJvcCB7T2JqZWN0fSBkYXRhXG4gKiBAcHJvcCB7U2V0fSBfY2FsbHNcbiAqIEB0eXBlIHtNYXB9XG4gKlxuICoge0BsaW5rIGh0dHA6Ly9yb2Jkb2Rzb24ubWUvamF2YXNjcmlwdC1kZXNpZ24tcGF0dGVybnMtZmFjdG9yeS8gYWJzdHJhY3QtZmFjdG9yeS1wYXR0ZXJufVxuICogQHNlZSB7QGxpbmsgYWJzdHJhY3QtZmFjdG9yeS1wYXR0ZXJufVxuICpcbiAqIEBtZW1iZXIgRmFjdG9yeUNoYWluXG4gKiBAY2F0ZWdvcnkgQ2hhaW5hYmxlXG4gKlxuICogQHRlc3RzIEZhY3RvcnlDaGFpblxuICogQHR5cGVzIEZhY3RvcnlDaGFpblxuICovXG5jbGFzcyBGYWN0b3J5Q2hhaW4gZXh0ZW5kcyBDaGFpbmVkTWFwIHtcbiAgY29uc3RydWN0b3IocGFyZW50KSB7XG4gICAgc3VwZXIocGFyZW50KVxuXG4gICAgdGhpcy5kYXRhID0ge31cbiAgICB0aGlzLl9jYWxscyA9IG5ldyBTZXQoKVxuXG4gICAgdGhpcy5mYWN0b3J5KClcbiAgICAgIC5leHRlbmQoWydvcHRpb25hbCcsICdyZXF1aXJlZCcsIE9OX0NIQUlOX1VQX0RPV05fS0VZLCBPTl9ET05FX0tFWV0pXG4gICAgICAuc2V0KCdsZW4nLCAwKVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjIGNoYWluIGJhY2sgdXAgdG8gcGFyZW50IGZvciBhbnkgb2YgdGhlc2VcbiAgICogQHNpbmNlIDIuMC4wXG4gICAqXG4gICAqIEBwYXJhbSAge0FycmF5PHN0cmluZz59IG1ldGhvZHMgbWV0aG9kcyB0byB0cmlnZ2VyIGBvbkNoYWluVXBEb3duYCBvblxuICAgKiBAcmV0dXJuIHtGYWN0b3J5Q2hhaW59IEBjaGFpbmFibGVcbiAgICpcbiAgICogQG1lbWJlck9mIEZhY3RvcnlDaGFpblxuICAgKiBAZW1pdHMgb25DaGFpblVwRG93blxuICAgKiBAVE9ETyBzaG91bGQgaGF2ZSBhIGRlYnVnIGxvZyBmb3IgdGhpc1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKlxuICAgKiAgICBjb25zdCB7Q2hhaW4sIEZhY3RvcnlDaGFpbiwgQ2hhaW5lZFNldH0gPSByZXF1aXJlKCdjaGFpbi1hYmxlJylcbiAgICpcbiAgICogICAgY2xhc3MgVGhpbmdzIGV4dGVuZHMgQ2hhaW4ge1xuICAgKiAgICAgIGNvbnN0cnVjdG9yKHBhcmVudCkge1xuICAgKiAgICAgICAgc3VwZXIocGFyZW50KVxuICAgKiAgICAgICAgdGhpcy5wZW9wbGUgPSBuZXcgQ2hhaW5lZFNldCh0aGlzKVxuICAgKiAgICAgIH1cbiAgICogICAgICBwZXJzb24oKSB7XG4gICAqICAgICAgICBjb25zdCBwZXJzb24gPSBuZXcgRmFjdG9yeUNoYWluKHRoaXMpXG4gICAqICAgICAgICBwZXJzb25cbiAgICogICAgICAgICAgLnByb3BzKFsnbmFtZScsICdhZ2UnLCAnZW1haWwnXSlcbiAgICogICAgICAgICAgLm9uQ2hhaW5VcERvd24odGhpcy5wZXJzb24pXG4gICAqICAgICAgICAgIC5jaGFpblVwRG93bnMoWydwZXJzb24nXSlcbiAgICogICAgICAgICAgLm9uRG9uZShwZXJzb25DaGFpbiA9PiB7XG4gICAqICAgICAgICAgICAgdGhpcy5wZW9wbGUuYWRkKHBlcnNvbkNoYWluKVxuICAgKiAgICAgICAgICAgIHJldHVybiB0aGlzXG4gICAqICAgICAgICAgIH0pXG4gICAqXG4gICAqICAgICAgICByZXR1cm4gcGVyc29uXG4gICAqICAgICAgfVxuICAgKiAgICB9XG4gICAqXG4gICAqICAgIGNvbnN0IHRoaW5ncyA9IG5ldyBUaGluZ3MoKVxuICAgKiAgICBjb25zdCByZXR1cm5lZCA9IHRoaW5nc1xuICAgKiAgICAgICAgLnBlcnNvbigpXG4gICAqICAgICAgICAgIC5uYW1lKCdzdWUnKVxuICAgKiAgICAgICAgLnBlcnNvbigpXG4gICAqICAgICAgICAgIC5hZ2UoMTAwKVxuICAgKiAgICAgICAgICAubmFtZSgnam9obicpXG4gICAqICAgICAgICAgIC5lbWFpbCgnQCcpXG4gICAqXG4gICAqL1xuICBjaGFpblVwRG93bnMobWV0aG9kcykge1xuICAgIG1ldGhvZHMuZm9yRWFjaChtID0+IHtcbiAgICAgIHRoaXNbbV0gPSAoKSA9PiB7XG4gICAgICAgIC8vIEBAZGVidWdnZXJcbiAgICAgICAgdGhpcy5lbmQoKVxuICAgICAgICByZXR1cm4gdGhpcy5wYXJlbnRbbV0uYXBwbHkodGhpcy5wYXJlbnQsIGFyZ3VtZW50cylcbiAgICAgIH1cbiAgICB9KVxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICAvKipcbiAgICogQGRlc2MgYWRkcyBhbiAqYXJyYXkqIG9mIHByb3BlcnRpZXMsIHVzaW5nIEZhY3RvcnlDaGFpbi5wcm9wXG4gICAqIEBzaW5jZSAyLjAuMFxuICAgKlxuICAgKiBAbWVtYmVyT2YgRmFjdG9yeUNoYWluXG4gICAqIEBwYXJhbSAge0FycmF5PHN0cmluZz59IG5hbWVzIHByb3BlcnR5IG5hbWVzXG4gICAqIEByZXR1cm4ge0ZhY3RvcnlDaGFpbn0gQGNoYWluYWJsZVxuICAgKlxuICAgKiBAc2VlIEZhY3RvcnlDaGFpbi5wcm9wXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqICAgIHBlcnNvbi5wcm9wcyhbJ25hbWUnLCAnYWdlJywgJ2VtYWlsJ10pXG4gICAqXG4gICAqICAgIHR5cGVvZiBwZXJzb24ubmFtZVxuICAgKiAgICAvLz0+ICdmdW5jdGlvbidcbiAgICpcbiAgICogICAgcGVyc29uLm5hbWUoKS5hZ2UoKVxuICAgKiAgICAvLz0+IEZhY3RvcnlDaGFpblxuICAgKlxuICAgKiAgICBwZXJzb24ubmFtZSgpLmFnZSgpLmVtYWlsKClcbiAgICogICAgLy89PiBQYXJlbnRDaGFpblxuICAgKlxuICAgKiAgICAvLyBwZXJzb24ubmFtZSgpLmFnZSgpLnBlcnNvbigpXG4gICAqICAgIC8vPT4gRmFjdG9yeUNoYWluXG4gICAqICAgIC8vXiBiZWNhdXNlIC5wZXJzb24gaXMgYGNoYWluVXBEb3duc2BcbiAgICogICAgLy9eIHNvIGl0IGZpbmlzaGVzIHRoZSBvbGQgY2hhaW4sIGFuZCBiZWdpbnMgYSBuZXcgb25lXG4gICAqXG4gICAqL1xuICBwcm9wcyhuYW1lcykge1xuICAgIG5hbWVzLmZvckVhY2gobmFtZSA9PiB0aGlzLnByb3AobmFtZSkpXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBzb3VyY2VtYXBzIHRyaWdnZXIgaXN0YW5idWwgaGVyZSBpbmNvcnJlY3RseSAqL1xuICAvKipcbiAgICogQGRlc2MgYWRkIHByb3BlcnR5IHRoYXQgYXJlIGNvdW50ZWQgdG93YXJkcyB0aGUgY2FsbCBjb3VudCBmb3IgZWFzeSBhdXRvLWVuZGluZyBjaGFpbmluZ1xuICAgKiBAc2luY2UgMi4wLjBcbiAgICpcbiAgICogQHBhcmFtICB7UHJpbWl0aXZlfSBuYW1lIHByb3BlcnR5IG5hbWVcbiAgICogQHBhcmFtICB7RnVuY3Rpb24gfCBudWxsIHwgdW5kZWZpbmVkfSBbb25DYWxsPXVuZGVmaW5lZF0gY2FsbGJhY2sgZm9yIHRoZSBwcm9wZXJ0eVxuICAgKiBAcmV0dXJuIHtGYWN0b3J5Q2hhaW59IEBjaGFpbmFibGVcbiAgICpcbiAgICogQG1lbWJlck9mIEZhY3RvcnlDaGFpblxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKlxuICAgKiAgICBwZXJzb25cbiAgICogICAgICAvLy5wcm9wIGFsc28gYWNjZXB0cyBhbiBvcHRpb25hbCBjYWxsYmFjayxcbiAgICogICAgICAvL2ZvciBuZXN0YWJsZSBuZXN0YWJsZSBjaGFpbnNcbiAgICogICAgICAucHJvcCgnbmFtZScpXG4gICAqICAgICAgLnByb3AoJ2FnZScpXG4gICAqICAgICAgLnByb3AoJ2VtYWlsJylcbiAgICpcbiAgICovXG4gIHByb3AobmFtZSwgb25DYWxsKSB7XG4gICAgdGhpcy50YXAoJ2xlbicsIGxlbiA9PiBsZW4gKyAxKVxuXG4gICAgLy8gc28gaWYgd2UgY2FsbCBhIHByb3BlcnR5IHR3aWNlLFxuICAgIC8vIGNoYWluIGJhY2sgdXAgdG8gcGFyZW50LFxuICAgIC8vIGFkZCBhIG5ldyBjaGFpblxuICAgIGlmICghaXNVbmRlZmluZWQodGhpc1tuYW1lXSkgJiYgaXNUcnVlKHRoaXMuaGFzKE9OX0NIQUlOX1VQX0RPV05fS0VZKSkpIHtcbiAgICAgIHRoaXMuZW5kKClcbiAgICAgIHJldHVybiB0aGlzLmdldChPTl9DSEFJTl9VUF9ET1dOX0tFWSkoKVtuYW1lXShvbkNhbGwpXG4gICAgfVxuXG4gICAgLy8gQFRPRE8gbmVlZCB0byBzcHJlYWQgYXMgbmVlZGVkXG4gICAgdGhpc1tuYW1lXSA9IGFyZ3MgPT4ge1xuICAgICAgLy8gQEBkZWJ1Z2dlclxuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQ6IGRldnMgKi9cbiAgICAgIGlmIChFTlZfREVCVUcpIHtcbiAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgYGNhbGxlZCAke25hbWV9IHdpdGg6YCxcbiAgICAgICAgICBhcmdzLFxuICAgICAgICAgIGBjYWxscyBsZW5ndGggaXMgbm93OmAsXG4gICAgICAgICAgdGhpcy5fY2FsbHMuc2l6ZVxuICAgICAgICApXG4gICAgICB9XG4gICAgICBpZiAoaXNVbmRlZmluZWQob25DYWxsKSkgdGhpcy5kYXRhW25hbWVdID0gYXJnc1xuICAgICAgZWxzZSBvbkNhbGwoYXJncylcblxuICAgICAgdGhpcy5fY2FsbHMuYWRkKG5hbWUpXG5cbiAgICAgIC8vIGFrYSBtYWdpY1JldHVyblxuICAgICAgcmV0dXJuIHRoaXMuX2NhbGxzLnNpemUgPT09IHRoaXMuZ2V0KCdsZW4nKSA/IHRoaXMuZW5kKCkgOiB0aGlzXG4gICAgfVxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICAvKipcbiAgICogQGRlc2MgYWNjZXNzIGRhdGEgYmVpbmcgYnVpbHQgd2hlbiBzdGVwcGluZyB0aHJvdWdoIGEgZmFjdG9yeVxuICAgKiBAc2luY2UgMi4wLjBcbiAgICpcbiAgICogQHBhcmFtICB7UHJpbWl0aXZlfSBbcHJvcD11bmRlZmluZWRdIGtleSBvZiB0aGUgZGF0YSwgb3IgcmV0dXJucyBhbGwgZGF0YVxuICAgKiBAcmV0dXJuIHthbnl9IHRoaXMuZGF0YVxuICAgKlxuICAgKiBAbWVtYmVyT2YgRmFjdG9yeUNoYWluXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqICAgIC5kYXRhWydwcm9wJ10gPSAnZWgnXG4gICAqICAgIC5nZXREYXRhKCdwcm9wJylcbiAgICogICAgLy89PiAnZWgnXG4gICAqICAgIC5nZXREYXRhKClcbiAgICogICAgLy89PiB7cHJvcDogJ2VoJ31cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICpcbiAgICogICAgY29uc3QgcGVyc29uID0gbmV3IEZhY3RvcnlDaGFpbih0aGlzKVxuICAgKiAgICBjb25zdCBhZ2UgPSBwZXJzb24ucHJvcHMoWyduYW1lJywgJ2FnZSddKS5hZ2UoMTApLmdldERhdGEoJ2FnZScpXG4gICAqICAgIGV4cGVjdChhZ2UpLnRvQmUoMTApXG4gICAqXG4gICAqL1xuICBnZXREYXRhKHByb3ApIHtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogc291cmNlbWFwcyB0cmlnZ2VyIGlzdGFuYnVsIGhlcmUgaW5jb3JyZWN0bHkgKi9cbiAgICByZXR1cm4gaXNVbmRlZmluZWQocHJvcCkgPyB0aGlzLmRhdGEgOiB0aGlzLmRhdGFbcHJvcF1cbiAgfVxuXG4gIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBzb3VyY2VtYXBzIHRyaWdnZXIgaXN0YW5idWwgaGVyZSBpbmNvcnJlY3RseSAqL1xuICAvKipcbiAgICogQGRlc2MgY3JlYXRlcy9hZGQgdGhlIGAuZW5kYCBtZXRob2QsXG4gICAqICAgICAgIHdoaWNoIGNoZWNrcyBob3cgbWFueSBtZXRob2RzIGhhdmUgYmVlbiBjYWxsZWQsXG4gICAqICAgICAgIGFuZCBkZWNpZGVzIHdoZXRoZXIgdG8gcmV0dXJuIHBhcmVudCBvciBub3RcbiAgICogICAgICAgQG1vZGlmaWVzIHRoaXMuZW5kXG4gICAqXG4gICAqIEBzaW5jZSAyLjAuMFxuICAgKlxuICAgKiBAcGFyYW0gIHtPYmplY3R9IFtvYmo9e31dIG9wdGlvbmFsIG9iamVjdCB0byB1c2UgZm9yIGNyZWF0aW5nIC5lbmRcbiAgICogQHJldHVybiB7RmFjdG9yeUNoYWlufSBAY2hhaW5hYmxlXG4gICAqXG4gICAqIEBtZW1iZXJPZiBGYWN0b3J5Q2hhaW5cbiAgICovXG4gIGZhY3Rvcnkob2JqKSB7XG4gICAgdGhpcy5lbmQgPSBhcmcgPT4ge1xuICAgICAgLy8gQEBkZWJ1Z2dlclxuICAgICAgbGV0IGVuZGVkXG5cbiAgICAgIGlmIChvYmogJiYgIWlzVW5kZWZpbmVkKG9iai5lbmQpKSBlbmRlZCA9IG9iai5lbmRcbiAgICAgIGVsc2UgaWYgKHRoaXMuaGFzKE9OX0RPTkVfS0VZKSkgZW5kZWQgPSB0aGlzLmdldChPTl9ET05FX0tFWSlcblxuICAgICAgaWYgKGVuZGVkKSBlbmRlZCA9IGVuZGVkLmNhbGwodGhpcywgdGhpcy5kYXRhLCB0aGlzLnBhcmVudCwgdGhpcywgYXJnKVxuXG4gICAgICBpZiAoZW5kZWQgJiYgZW5kZWQgIT09IHRoaXMpIHJldHVybiBlbmRlZFxuICAgICAgZWxzZSByZXR1cm4gdGhpcy5wYXJlbnRcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpc1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gRmFjdG9yeUNoYWluXG4iXSwibmFtZXMiOlsiY29uc3QiLCJzdXBlciIsInRoaXMiLCJhcmd1bWVudHMiLCJsZXQiXSwibWFwcGluZ3MiOiJBQUFBQSxHQUFLLENBQUMsU0FBUyxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQztBQUM3Q0EsR0FBSyxDQUFDLFVBQVUsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDO0FBQzFDQSxHQUFLLENBQUMsV0FBVyxHQUFHLE9BQU8sQ0FBQyxxQkFBcUIsQ0FBQztBQUNsREEsR0FBSyxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsZ0JBQWdCLENBQUM7QUFDeENBLEdBQUssQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLHNCQUFzQixDQUFDOztBQUU5Q0EsR0FBSyxDQUFDLG9CQUFvQixHQUFHLGVBQWU7QUFDNUNBLEdBQUssQ0FBQyxXQUFXLEdBQUcsUUFBUTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBcUI1QixJQUFNLFlBQVksR0FBbUI7RUFBQyxBQUNwQyxxQkFBVyxDQUFDLE1BQU0sRUFBRTtJQUNsQkMsVUFBSyxLQUFBLENBQUMsTUFBQSxNQUFNLENBQUM7O0lBRWIsSUFBSSxDQUFDLElBQUksR0FBRyxFQUFFO0lBQ2QsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLEdBQUcsRUFBRTs7SUFFdkIsSUFBSSxDQUFDLE9BQU8sRUFBRTtPQUNYLE1BQU0sQ0FBQyxDQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUUsb0JBQW9CLEVBQUUsV0FBVyxDQUFDLENBQUM7T0FDbkUsR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7R0FDakI7Ozs7b0RBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7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