UNPKG

chain-able

Version:

interfaces that describe their intentions.

256 lines (231 loc) 19.2 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 ON_CHAIN_UP_DOWN_KEY = 'onChainUpDown' var ON_DONE_KEY = 'onDone' /** * @extends {ChainedMapBase} * @inheritdoc * @prop {Object} data * @prop {Set} _calls * @type {Map} * * {@link http://robdodson.me/javascript-design-patterns-factory/ 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={}] optiona 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmFjdG9yeUNoYWluLmpzIiwic291cmNlcyI6WyJGYWN0b3J5Q2hhaW4uanMiXSwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgRU5WX0RFQlVHID0gcmVxdWlyZSgnLi9kZXBzL2Vudi9kZWJ1ZycpXG5jb25zdCBDaGFpbmVkTWFwID0gcmVxdWlyZSgnLi9DaGFpbmVkTWFwJylcbmNvbnN0IGlzVW5kZWZpbmVkID0gcmVxdWlyZSgnLi9kZXBzL2lzL3VuZGVmaW5lZCcpXG5jb25zdCBpc1RydWUgPSByZXF1aXJlKCcuL2RlcHMvaXMvdHJ1ZScpXG5cbmNvbnN0IE9OX0NIQUlOX1VQX0RPV05fS0VZID0gJ29uQ2hhaW5VcERvd24nXG5jb25zdCBPTl9ET05FX0tFWSA9ICdvbkRvbmUnXG5cbi8qKlxuICogQGV4dGVuZHMge0NoYWluZWRNYXBCYXNlfVxuICogQGluaGVyaXRkb2NcbiAqIEBwcm9wIHtPYmplY3R9IGRhdGFcbiAqIEBwcm9wIHtTZXR9IF9jYWxsc1xuICogQHR5cGUge01hcH1cbiAqXG4gKiB7QGxpbmsgaHR0cDovL3JvYmRvZHNvbi5tZS9qYXZhc2NyaXB0LWRlc2lnbi1wYXR0ZXJucy1mYWN0b3J5LyBhYnN0cmFjdC1mYWN0b3J5LXBhdHRlcm59XG4gKlxuICogQG1lbWJlciBGYWN0b3J5Q2hhaW5cbiAqIEBjYXRlZ29yeSBDaGFpbmFibGVcbiAqIEB0ZXN0cyBGYWN0b3J5Q2hhaW5cbiAqIEB0eXBlcyBGYWN0b3J5Q2hhaW5cbiAqL1xuY2xhc3MgRmFjdG9yeUNoYWluIGV4dGVuZHMgQ2hhaW5lZE1hcCB7XG4gIGNvbnN0cnVjdG9yKHBhcmVudCkge1xuICAgIHN1cGVyKHBhcmVudClcblxuICAgIHRoaXMuZGF0YSA9IHt9XG4gICAgdGhpcy5fY2FsbHMgPSBuZXcgU2V0KClcblxuICAgIHRoaXMuZmFjdG9yeSgpXG4gICAgICAuZXh0ZW5kKFsnb3B0aW9uYWwnLCAncmVxdWlyZWQnLCBPTl9DSEFJTl9VUF9ET1dOX0tFWSwgT05fRE9ORV9LRVldKVxuICAgICAgLnNldCgnbGVuJywgMClcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzYyBjaGFpbiBiYWNrIHVwIHRvIHBhcmVudCBmb3IgYW55IG9mIHRoZXNlXG4gICAqIEBzaW5jZSAyLjAuMFxuICAgKlxuICAgKiBAcGFyYW0gIHtBcnJheTxzdHJpbmc+fSBtZXRob2RzIG1ldGhvZHMgdG8gdHJpZ2dlciBgb25DaGFpblVwRG93bmAgb25cbiAgICogQHJldHVybiB7RmFjdG9yeUNoYWlufSBAY2hhaW5hYmxlXG4gICAqXG4gICAqIEBtZW1iZXJPZiBGYWN0b3J5Q2hhaW5cbiAgICogQGVtaXRzIG9uQ2hhaW5VcERvd25cbiAgICogQFRPRE8gc2hvdWxkIGhhdmUgYSBkZWJ1ZyBsb2cgZm9yIHRoaXNcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICpcbiAgICogICAgY29uc3Qge0NoYWluLCBGYWN0b3J5Q2hhaW4sIENoYWluZWRTZXR9ID0gcmVxdWlyZSgnY2hhaW4tYWJsZScpXG4gICAqXG4gICAqICAgIGNsYXNzIFRoaW5ncyBleHRlbmRzIENoYWluIHtcbiAgICogICAgICBjb25zdHJ1Y3RvcihwYXJlbnQpIHtcbiAgICogICAgICAgIHN1cGVyKHBhcmVudClcbiAgICogICAgICAgIHRoaXMucGVvcGxlID0gbmV3IENoYWluZWRTZXQodGhpcylcbiAgICogICAgICB9XG4gICAqICAgICAgcGVyc29uKCkge1xuICAgKiAgICAgICAgY29uc3QgcGVyc29uID0gbmV3IEZhY3RvcnlDaGFpbih0aGlzKVxuICAgKiAgICAgICAgcGVyc29uXG4gICAqICAgICAgICAgIC5wcm9wcyhbJ25hbWUnLCAnYWdlJywgJ2VtYWlsJ10pXG4gICAqICAgICAgICAgIC5vbkNoYWluVXBEb3duKHRoaXMucGVyc29uKVxuICAgKiAgICAgICAgICAuY2hhaW5VcERvd25zKFsncGVyc29uJ10pXG4gICAqICAgICAgICAgIC5vbkRvbmUocGVyc29uQ2hhaW4gPT4ge1xuICAgKiAgICAgICAgICAgIHRoaXMucGVvcGxlLmFkZChwZXJzb25DaGFpbilcbiAgICogICAgICAgICAgICByZXR1cm4gdGhpc1xuICAgKiAgICAgICAgICB9KVxuICAgKlxuICAgKiAgICAgICAgcmV0dXJuIHBlcnNvblxuICAgKiAgICAgIH1cbiAgICogICAgfVxuICAgKlxuICAgKiAgICBjb25zdCB0aGluZ3MgPSBuZXcgVGhpbmdzKClcbiAgICogICAgY29uc3QgcmV0dXJuZWQgPSB0aGluZ3NcbiAgICogICAgICAgIC5wZXJzb24oKVxuICAgKiAgICAgICAgICAubmFtZSgnc3VlJylcbiAgICogICAgICAgIC5wZXJzb24oKVxuICAgKiAgICAgICAgICAuYWdlKDEwMClcbiAgICogICAgICAgICAgLm5hbWUoJ2pvaG4nKVxuICAgKiAgICAgICAgICAuZW1haWwoJ0AnKVxuICAgKlxuICAgKi9cbiAgY2hhaW5VcERvd25zKG1ldGhvZHMpIHtcbiAgICBtZXRob2RzLmZvckVhY2gobSA9PiB7XG4gICAgICB0aGlzW21dID0gKCkgPT4ge1xuICAgICAgICAvLyBAQGRlYnVnZ2VyXG4gICAgICAgIHRoaXMuZW5kKClcbiAgICAgICAgcmV0dXJuIHRoaXMucGFyZW50W21dLmFwcGx5KHRoaXMucGFyZW50LCBhcmd1bWVudHMpXG4gICAgICB9XG4gICAgfSlcbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjIGFkZHMgYW4gKmFycmF5KiBvZiBwcm9wZXJ0aWVzLCB1c2luZyBGYWN0b3J5Q2hhaW4ucHJvcFxuICAgKiBAc2luY2UgMi4wLjBcbiAgICpcbiAgICogQG1lbWJlck9mIEZhY3RvcnlDaGFpblxuICAgKiBAcGFyYW0gIHtBcnJheTxzdHJpbmc+fSBuYW1lcyBwcm9wZXJ0eSBuYW1lc1xuICAgKiBAcmV0dXJuIHtGYWN0b3J5Q2hhaW59IEBjaGFpbmFibGVcbiAgICpcbiAgICogQHNlZSBGYWN0b3J5Q2hhaW4ucHJvcFxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKlxuICAgKiAgICBwZXJzb24ucHJvcHMoWyduYW1lJywgJ2FnZScsICdlbWFpbCddKVxuICAgKlxuICAgKiAgICB0eXBlb2YgcGVyc29uLm5hbWVcbiAgICogICAgLy89PiAnZnVuY3Rpb24nXG4gICAqXG4gICAqICAgIHBlcnNvbi5uYW1lKCkuYWdlKClcbiAgICogICAgLy89PiBGYWN0b3J5Q2hhaW5cbiAgICpcbiAgICogICAgcGVyc29uLm5hbWUoKS5hZ2UoKS5lbWFpbCgpXG4gICAqICAgIC8vPT4gUGFyZW50Q2hhaW5cbiAgICpcbiAgICogICAgLy8gcGVyc29uLm5hbWUoKS5hZ2UoKS5wZXJzb24oKVxuICAgKiAgICAvLz0+IEZhY3RvcnlDaGFpblxuICAgKiAgICAvL14gYmVjYXVzZSAucGVyc29uIGlzIGBjaGFpblVwRG93bnNgXG4gICAqICAgIC8vXiBzbyBpdCBmaW5pc2hlcyB0aGUgb2xkIGNoYWluLCBhbmQgYmVnaW5zIGEgbmV3IG9uZVxuICAgKlxuICAgKi9cbiAgcHJvcHMobmFtZXMpIHtcbiAgICBuYW1lcy5mb3JFYWNoKG5hbWUgPT4gdGhpcy5wcm9wKG5hbWUpKVxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogc291cmNlbWFwcyB0cmlnZ2VyIGlzdGFuYnVsIGhlcmUgaW5jb3JyZWN0bHkgKi9cbiAgLyoqXG4gICAqIEBkZXNjIGFkZCBwcm9wZXJ0eSB0aGF0IGFyZSBjb3VudGVkIHRvd2FyZHMgdGhlIGNhbGwgY291bnQgZm9yIGVhc3kgYXV0by1lbmRpbmcgY2hhaW5pbmdcbiAgICogQHNpbmNlIDIuMC4wXG4gICAqXG4gICAqIEBwYXJhbSAge1ByaW1pdGl2ZX0gbmFtZSBwcm9wZXJ0eSBuYW1lXG4gICAqIEBwYXJhbSAge0Z1bmN0aW9uIHwgbnVsbCB8IHVuZGVmaW5lZH0gW29uQ2FsbD11bmRlZmluZWRdIGNhbGxiYWNrIGZvciB0aGUgcHJvcGVydHlcbiAgICogQHJldHVybiB7RmFjdG9yeUNoYWlufSBAY2hhaW5hYmxlXG4gICAqXG4gICAqIEBtZW1iZXJPZiBGYWN0b3J5Q2hhaW5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICpcbiAgICogICAgcGVyc29uXG4gICAqICAgICAgLy8ucHJvcCBhbHNvIGFjY2VwdHMgYW4gb3B0aW9uYWwgY2FsbGJhY2ssXG4gICAqICAgICAgLy9mb3IgbmVzdGFibGUgbmVzdGFibGUgY2hhaW5zXG4gICAqICAgICAgLnByb3AoJ25hbWUnKVxuICAgKiAgICAgIC5wcm9wKCdhZ2UnKVxuICAgKiAgICAgIC5wcm9wKCdlbWFpbCcpXG4gICAqXG4gICAqL1xuICBwcm9wKG5hbWUsIG9uQ2FsbCkge1xuICAgIHRoaXMudGFwKCdsZW4nLCBsZW4gPT4gbGVuICsgMSlcblxuICAgIC8vIHNvIGlmIHdlIGNhbGwgYSBwcm9wZXJ0eSB0d2ljZSxcbiAgICAvLyBjaGFpbiBiYWNrIHVwIHRvIHBhcmVudCxcbiAgICAvLyBhZGQgYSBuZXcgY2hhaW5cbiAgICBpZiAoIWlzVW5kZWZpbmVkKHRoaXNbbmFtZV0pICYmIGlzVHJ1ZSh0aGlzLmhhcyhPTl9DSEFJTl9VUF9ET1dOX0tFWSkpKSB7XG4gICAgICB0aGlzLmVuZCgpXG4gICAgICByZXR1cm4gdGhpcy5nZXQoT05fQ0hBSU5fVVBfRE9XTl9LRVkpKClbbmFtZV0ob25DYWxsKVxuICAgIH1cblxuICAgIC8vIEBUT0RPIG5lZWQgdG8gc3ByZWFkIGFzIG5lZWRlZFxuICAgIHRoaXNbbmFtZV0gPSBhcmdzID0+IHtcbiAgICAgIC8vIEBAZGVidWdnZXJcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBkZXZzICovXG4gICAgICBpZiAoRU5WX0RFQlVHKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgIGBjYWxsZWQgJHtuYW1lfSB3aXRoOmAsXG4gICAgICAgICAgYXJncyxcbiAgICAgICAgICBgY2FsbHMgbGVuZ3RoIGlzIG5vdzpgLFxuICAgICAgICAgIHRoaXMuX2NhbGxzLnNpemVcbiAgICAgICAgKVxuICAgICAgfVxuICAgICAgaWYgKGlzVW5kZWZpbmVkKG9uQ2FsbCkpIHRoaXMuZGF0YVtuYW1lXSA9IGFyZ3NcbiAgICAgIGVsc2Ugb25DYWxsKGFyZ3MpXG5cbiAgICAgIHRoaXMuX2NhbGxzLmFkZChuYW1lKVxuXG4gICAgICAvLyBha2EgbWFnaWNSZXR1cm5cbiAgICAgIHJldHVybiB0aGlzLl9jYWxscy5zaXplID09PSB0aGlzLmdldCgnbGVuJykgPyB0aGlzLmVuZCgpIDogdGhpc1xuICAgIH1cbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjIGFjY2VzcyBkYXRhIGJlaW5nIGJ1aWx0IHdoZW4gc3RlcHBpbmcgdGhyb3VnaCBhIGZhY3RvcnlcbiAgICogQHNpbmNlIDIuMC4wXG4gICAqXG4gICAqIEBwYXJhbSAge1ByaW1pdGl2ZX0gW3Byb3A9dW5kZWZpbmVkXSBrZXkgb2YgdGhlIGRhdGEsIG9yIHJldHVybnMgYWxsIGRhdGFcbiAgICogQHJldHVybiB7YW55fSB0aGlzLmRhdGFcbiAgICpcbiAgICogQG1lbWJlck9mIEZhY3RvcnlDaGFpblxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKlxuICAgKiAgICAuZGF0YVsncHJvcCddID0gJ2VoJ1xuICAgKiAgICAuZ2V0RGF0YSgncHJvcCcpXG4gICAqICAgIC8vPT4gJ2VoJ1xuICAgKiAgICAuZ2V0RGF0YSgpXG4gICAqICAgIC8vPT4ge3Byb3A6ICdlaCd9XG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqICAgIGNvbnN0IHBlcnNvbiA9IG5ldyBGYWN0b3J5Q2hhaW4odGhpcylcbiAgICogICAgY29uc3QgYWdlID0gcGVyc29uLnByb3BzKFsnbmFtZScsICdhZ2UnXSkuYWdlKDEwKS5nZXREYXRhKCdhZ2UnKVxuICAgKiAgICBleHBlY3QoYWdlKS50b0JlKDEwKVxuICAgKlxuICAgKi9cbiAgZ2V0RGF0YShwcm9wKSB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQ6IHNvdXJjZW1hcHMgdHJpZ2dlciBpc3RhbmJ1bCBoZXJlIGluY29ycmVjdGx5ICovXG4gICAgcmV0dXJuIGlzVW5kZWZpbmVkKHByb3ApID8gdGhpcy5kYXRhIDogdGhpcy5kYXRhW3Byb3BdXG4gIH1cblxuICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogc291cmNlbWFwcyB0cmlnZ2VyIGlzdGFuYnVsIGhlcmUgaW5jb3JyZWN0bHkgKi9cbiAgLyoqXG4gICAqIEBkZXNjIGNyZWF0ZXMvYWRkIHRoZSBgLmVuZGAgbWV0aG9kLCB3aGljaCBjaGVja3MgaG93IG1hbnkgbWV0aG9kcyBoYXZlIGJlZW4gY2FsbGVkLCBhbmQgZGVjaWRlcyB3aGV0aGVyIHRvIHJldHVybiBwYXJlbnQgb3Igbm90XG4gICAqICAgICAgIEBtb2RpZmllcyB0aGlzLmVuZFxuICAgKlxuICAgKiBAc2luY2UgMi4wLjBcbiAgICpcbiAgICogQHBhcmFtICB7T2JqZWN0fSBbb2JqPXt9XSBvcHRpb25hIG9iamVjdCB0byB1c2UgZm9yIGNyZWF0aW5nIC5lbmRcbiAgICogQHJldHVybiB7RmFjdG9yeUNoYWlufSBAY2hhaW5hYmxlXG4gICAqXG4gICAqIEBtZW1iZXJPZiBGYWN0b3J5Q2hhaW5cbiAgICovXG4gIGZhY3Rvcnkob2JqKSB7XG4gICAgdGhpcy5lbmQgPSBhcmcgPT4ge1xuICAgICAgLy8gQEBkZWJ1Z2dlclxuICAgICAgbGV0IGVuZGVkXG5cbiAgICAgIGlmIChvYmogJiYgIWlzVW5kZWZpbmVkKG9iai5lbmQpKSBlbmRlZCA9IG9iai5lbmRcbiAgICAgIGVsc2UgaWYgKHRoaXMuaGFzKE9OX0RPTkVfS0VZKSkgZW5kZWQgPSB0aGlzLmdldChPTl9ET05FX0tFWSlcblxuICAgICAgaWYgKGVuZGVkKSBlbmRlZCA9IGVuZGVkLmNhbGwodGhpcywgdGhpcy5kYXRhLCB0aGlzLnBhcmVudCwgdGhpcywgYXJnKVxuXG4gICAgICBpZiAoZW5kZWQgJiYgZW5kZWQgIT09IHRoaXMpIHJldHVybiBlbmRlZFxuICAgICAgZWxzZSByZXR1cm4gdGhpcy5wYXJlbnRcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpc1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gRmFjdG9yeUNoYWluXG4iXSwibmFtZXMiOlsiY29uc3QiLCJzdXBlciIsInRoaXMiLCJhcmd1bWVudHMiLCJsZXQiXSwibWFwcGluZ3MiOiJBQUFBQSxHQUFLLENBQUMsU0FBUyxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQztBQUM3Q0EsR0FBSyxDQUFDLFVBQVUsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDO0FBQzFDQSxHQUFLLENBQUMsV0FBVyxHQUFHLE9BQU8sQ0FBQyxxQkFBcUIsQ0FBQztBQUNsREEsR0FBSyxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsZ0JBQWdCLENBQUM7O0FBRXhDQSxHQUFLLENBQUMsb0JBQW9CLEdBQUcsZUFBZTtBQUM1Q0EsR0FBSyxDQUFDLFdBQVcsR0FBRyxRQUFROzs7Ozs7Ozs7Ozs7Ozs7O0FBZ0I1QixJQUFNLFlBQVksR0FBbUI7RUFBQyxBQUNwQyxxQkFBVyxDQUFDLE1BQU0sRUFBRTtJQUNsQkMsVUFBSyxLQUFBLENBQUMsTUFBQSxNQUFNLENBQUM7O0lBRWIsSUFBSSxDQUFDLElBQUksR0FBRyxFQUFFO0lBQ2QsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLEdBQUcsRUFBRTs7SUFFdkIsSUFBSSxDQUFDLE9BQU8sRUFBRTtPQUNYLE1BQU0sQ0FBQyxDQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUUsb0JBQW9CLEVBQUUsV0FBVyxDQUFDLENBQUM7T0FDbkUsR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7R0FDakI7Ozs7b0RBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0VBK0NELHVCQUFBLFlBQVkseUJBQUEsQ0FBQyxPQUFPLEVBQUUsQ0FBQzs7O0FBQUE7SUFDckIsT0FBTyxDQUFDLE9BQU8sQ0FBQyxVQUFBLENBQUMsQ0FBQSxDQUFDLEFBQUc7TUFDbkJDLE1BQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxTQUFBLEdBQUcsQUFBRzs7UUFFZEEsTUFBSSxDQUFDLEdBQUcsRUFBRTtR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