@activejs/core
Version:
Pragmatic, Reactive State Management for JavaScript Apps
142 lines • 16.7 kB
JavaScript
import { merge } from 'rxjs';
import { Base } from './abstract-base';
import { Configuration } from './configuration';
import { Stream } from './stream';
import { checkClusterItems } from '../checks/common';
import { IteratorSymbol, makeNonEnumerable } from '../utils/funcs';
/**
* A Cluster is just a wrapper, a group, of two or more ActiveJS fundamental constructs, `Units`, `Systems`, `Actions`, or even `Clusters`.
*
* It creates a master `Observable` of the combined value of its members by merging all the provided Observable constructs.
* Whenever any of these wrapped constructs emits a value, `Cluster` emits a new combined-value.
*
* See {@link https://docs.activejs.dev/fundamentals/cluster} for more details.
*
* @category 4. Utility
*/
export class Cluster extends Base {
constructor(items, config) {
super(Object.assign(Object.assign({}, Configuration.CLUSTER), config));
/**
* The items part of this cluster, stored as key-value pairs.
*/
this.items = {};
checkClusterItems(items);
this.extractItems(items);
this.startListeningAndEmitting();
makeNonEnumerable(this);
Object.freeze(this.items);
}
/**
* The count of items part of this cluster.
*/
get itemsCount() {
return this._itemsCount;
}
// tslint:enable:variable-name
/**
* Combined value of the items part of this Cluster.
*
* @category Access Value
*/
value() {
const val = this.itemsKeys.reduce((reduced, key) => {
reduced[key] = this.items[key].value();
return reduced;
}, {});
if (Configuration.ENVIRONMENT.checkImmutability === true) {
Object.freeze(val);
}
return val;
}
/**
* A helper method that creates a stream by subscribing to the Observable returned by the param `observableProducer` callback.
*
* Ideally the callback function creates an Observable by applying `Observable.pipe`.
*
* Just know that you should catch the error in a sub-pipe (ie: do not let it propagate to the main-pipe), otherwise
* as usual the stream will stop working, and will not react on any further emissions.
*
* @param observableProducer A callback function that should return an Observable.
*
* @category Common
*/
createStream(observableProducer) {
const observable = observableProducer(this);
return new Stream(observable);
}
/**
* Select a child by providing its key.
*
* @param key The key of the child.
*
* @category Custom Cluster
*/
select(key) {
return this.items[key];
}
/**
* Performs the specified action for each child of the Cluster {@link items}. \
* It's a drop-in replacement for the `forEach` method.
*
* @param callbackFn A function that accepts up to three arguments.
* forEvery calls the callbackFn function one time for each element in the list.
* @param thisArg An object to which this keyword can refer in the callbackFn function.
* If thisArg is omitted, undefined is used as this value.
*
* @category Custom Cluster
*/
forEvery(callbackFn, thisArg) {
Object.entries(this.items).forEach(([key, item], i, itemsAsEntries) => callbackFn.call(thisArg, item, key, i, itemsAsEntries));
}
/**
* @internal please do not use.
*/
[IteratorSymbol]() {
let index = 0;
const items = Object.entries(this.items);
const length = items.length;
return {
next() {
return { value: items[index++], done: index > length };
},
};
}
/**
* @internal please do not use.
*/
extractItems(items) {
this.itemsKeys = Object.keys(items).filter(key => items[key] instanceof Base);
this._itemsCount = this.itemsKeys.length;
this.itemsKeys.forEach(key => {
this.items[key] = items[key];
});
}
/**
* @internal please do not use.
*/
startListeningAndEmitting() {
this.emit();
merge(...Object.values(this.items).map(item => item.future$)).subscribe(() => this.emit());
}
/**
* @internal please do not use.
*/
emit(value = this.combinedEmittedValues()) {
if (Configuration.ENVIRONMENT.checkImmutability === true) {
Object.freeze(value);
}
super.emit(value);
}
/**
* @internal please do not use.
*/
combinedEmittedValues() {
return this.itemsKeys.reduce((reduced, key) => {
// tslint:disable-next-line:no-string-literal
reduced[key] = this.items[key]['emittedValue'];
return reduced;
}, {});
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIvaG9tZS9ydW5uZXIvd29yay9hY3RpdmVqcy9hY3RpdmVqcy9wYWNrYWdlcy9jb3JlL3NyYy8iLCJzb3VyY2VzIjpbImxpYi9jbHVzdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxLQUFLLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFDM0IsT0FBTyxFQUFDLElBQUksRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQ3JDLE9BQU8sRUFBQyxhQUFhLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUM5QyxPQUFPLEVBQUMsTUFBTSxFQUFDLE1BQU0sVUFBVSxDQUFDO0FBT2hDLE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLGtCQUFrQixDQUFDO0FBQ25ELE9BQU8sRUFBQyxjQUFjLEVBQUUsaUJBQWlCLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUVqRTs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLE9BQU8sT0FJWCxTQUFRLElBQU87SUFpRGYsWUFBWSxLQUFRLEVBQUUsTUFBc0I7UUFDMUMsS0FBSyxpQ0FDQSxhQUFhLENBQUMsT0FBTyxHQUNyQixNQUFNLEVBQ1QsQ0FBQztRQXZDTDs7V0FFRztRQUNNLFVBQUssR0FBZ0IsRUFBUyxDQUFDO1FBc0N0QyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUV6QixJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3pCLElBQUksQ0FBQyx5QkFBeUIsRUFBRSxDQUFDO1FBRWpDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3hCLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzVCLENBQUM7SUF0Q0Q7O09BRUc7SUFDSCxJQUFJLFVBQVU7UUFDWixPQUFPLElBQUksQ0FBQyxXQUFXLENBQUM7SUFDMUIsQ0FBQztJQUVELDhCQUE4QjtJQUU5Qjs7OztPQUlHO0lBQ0gsS0FBSztRQUNI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SUFBSSxDQUFDLHFCQUFxQixFQUFFO1FBQ2pELElBQUksYUFBYSxDQUFDLFdBQVcsQ0FBQyxpQkFBaUIsS0FBSyxJQUFJLEVBQUU7WUFDeEQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztTQUN0QjtRQUNELEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDcEIsQ0FBQztJQUVEOztPQUVHO0lBQ0sscUJBQXFCO1FBQzNCLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLEVBQUU7WUFDNUMsNkNBQTZDO1lBQzdDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQy9DLE9BQU8sT0FBTyxDQUFDO1FBQ2pCLENBQUMsRUFBRSxFQUFTLENBQU0sQ0FBQztJQUNyQixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge21lcmdlfSBmcm9tICdyeGpzJztcbmltcG9ydCB7QmFzZX0gZnJvbSAnLi9hYnN0cmFjdC1iYXNlJztcbmltcG9ydCB7Q29uZmlndXJhdGlvbn0gZnJvbSAnLi9jb25maWd1cmF0aW9uJztcbmltcG9ydCB7U3RyZWFtfSBmcm9tICcuL3N0cmVhbSc7XG5pbXBvcnQge1xuICBDbHVzdGVyQ29uZmlnLFxuICBDbHVzdGVySXRlbXMsXG4gIENsdXN0ZXJTdHJlYW1PYnNlcnZhYmxlUHJvZHVjZXIsXG4gIEluc3RhbmNlc01hcFRvVmFsdWVzTWFwLFxufSBmcm9tICcuLi9tb2RlbHMnO1xuaW1wb3J0IHtjaGVja0NsdXN0ZXJJdGVtc30gZnJvbSAnLi4vY2hlY2tzL2NvbW1vbic7XG5pbXBvcnQge0l0ZXJhdG9yU3ltYm9sLCBtYWtlTm9uRW51bWVyYWJsZX0gZnJvbSAnLi4vdXRpbHMvZnVuY3MnO1xuXG4vKipcbiAqIEEgQ2x1c3RlciBpcyBqdXN0IGEgd3JhcHBlciwgYSBncm91cCwgb2YgdHdvIG9yIG1vcmUgQWN0aXZlSlMgZnVuZGFtZW50YWwgY29uc3RydWN0cywgYFVuaXRzYCwgYFN5c3RlbXNgLCBgQWN0aW9uc2AsIG9yIGV2ZW4gYENsdXN0ZXJzYC5cbiAqXG4gKiBJdCBjcmVhdGVzIGEgbWFzdGVyIGBPYnNlcnZhYmxlYCBvZiB0aGUgY29tYmluZWQgdmFsdWUgb2YgaXRzIG1lbWJlcnMgYnkgbWVyZ2luZyBhbGwgdGhlIHByb3ZpZGVkIE9ic2VydmFibGUgY29uc3RydWN0cy5cbiAqIFdoZW5ldmVyIGFueSBvZiB0aGVzZSB3cmFwcGVkIGNvbnN0cnVjdHMgZW1pdHMgYSB2YWx1ZSwgYENsdXN0ZXJgIGVtaXRzIGEgbmV3IGNvbWJpbmVkLXZhbHVlLlxuICpcbiAqIFNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmFjdGl2ZWpzLmRldi9mdW5kYW1lbnRhbHMvY2x1c3Rlcn0gZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBAY2F0ZWdvcnkgNC4gVXRpbGl0eVxuICovXG5leHBvcnQgY2xhc3MgQ2x1c3RlcjxcbiAgVCBleHRlbmRzIENsdXN0ZXJJdGVtcyA9IENsdXN0ZXJJdGVtcyxcbiAgSyBleHRlbmRzIGtleW9mIFQgPSBrZXlvZiBULFxuICBWID0gSW5zdGFuY2VzTWFwVG9WYWx1ZXNNYXA8VD5cbj4gZXh0ZW5kcyBCYXNlPFY+IHtcbiAgLy8gdHNsaW50OmRpc2FibGU6dmFyaWFibGUtbmFtZVxuXG4gIC8qKlxuICAgKiBDb25maWd1cmVkIG9wdGlvbnMuIFxcXG4gICAqIENvbWJpbmF0aW9uIG9mIGdsb2JhbC1vcHRpb25zIHtAbGluayBHbG9iYWxVbml0Q29uZmlnfSBhbmQgdGhlIG9wdGlvbnMgcGFzc2VkIG9uIGluc3RhbnRpYXRpb24uXG4gICAqL1xuICByZWFkb25seSBjb25maWc6IFJlYWRvbmx5PENsdXN0ZXJDb25maWc+O1xuXG4gIC8qKlxuICAgKiBAaW50ZXJuYWwgcGxlYXNlIGRvIG5vdCB1c2UuXG4gICAqL1xuICBwcml2YXRlIGl0ZW1zS2V5czogS1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgaXRlbXMgcGFydCBvZiB0aGlzIGNsdXN0ZXIsIHN0b3JlZCBhcyBrZXktdmFsdWUgcGFpcnMuXG4gICAqL1xuICByZWFkb25seSBpdGVtczogUmVhZG9ubHk8VD4gPSB7fSBhcyBhbnk7XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbCBwbGVhc2UgZG8gbm90IHVzZS5cbiAgICovXG4gIHByaXZhdGUgX2l0ZW1zQ291bnQ6IG51bWJlcjtcblxuICAvKipcbiAgICogVGhlIGNvdW50IG9mIGl0ZW1zIHBhcnQgb2YgdGhpcyBjbHVzdGVyLlxuICAgKi9cbiAgZ2V0IGl0ZW1zQ291bnQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5faXRlbXNDb3VudDtcbiAgfVxuXG4gIC8vIHRzbGludDplbmFibGU6dmFyaWFibGUtbmFtZVxuXG4gIC8qKlxuICAgKiBDb21iaW5lZCB2YWx1ZSBvZiB0aGUgaXRlbXMgcGFydCBvZiB0aGlzIENsdXN0ZXIuXG4gICAqXG4gICAqIEBjYXRlZ29yeSBBY2Nlc3MgVmFsdWVcbiAgICovXG4gIHZhbHVlKCkge1xuICAgIGNvbnN0IHZhbCA9IHRoaXMuaXRlbXNLZXlzLnJlZHVjZSgocmVkdWNlZCwga2V5KSA9PiB7XG4gICAgICByZWR1Y2VkW2tleV0gPSB0aGlzLml0ZW1zW2tleV0udmFsdWUoKTtcbiAgICAgIHJldHVybiByZWR1Y2VkO1xuICAgIH0sIHt9IGFzIGFueSkgYXMgVjtcbiAgICBpZiAoQ29uZmlndXJhdGlvbi5FTlZJUk9OTUVOVC5jaGVja0ltbXV0YWJpbGl0eSA9PT0gdHJ1ZSkge1xuICAgICAgT2JqZWN0LmZyZWV6ZSh2YWwpO1xuICAgIH1cbiAgICByZXR1cm4gdmFsO1xuICB9XG5cbiAgY29uc3RydWN0b3IoaXRlbXM6IFQsIGNvbmZpZz86IENsdXN0ZXJDb25maWcpIHtcbiAgICBzdXBlcih7XG4gICAgICAuLi5Db25maWd1cmF0aW9uLkNMVVNURVIsXG4gICAgICAuLi5jb25maWcsXG4gICAgfSk7XG5cbiAgICBjaGVja0NsdXN0ZXJJdGVtcyhpdGVtcyk7XG5cbiAgICB0aGlzLmV4dHJhY3RJdGVtcyhpdGVtcyk7XG4gICAgdGhpcy5zdGFydExpc3RlbmluZ0FuZEVtaXR0aW5nKCk7XG5cbiAgICBtYWtlTm9uRW51bWVyYWJsZSh0aGlzKTtcbiAgICBPYmplY3QuZnJlZXplKHRoaXMuaXRlbXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgaGVscGVyIG1ldGhvZCB0aGF0IGNyZWF0ZXMgYSBzdHJlYW0gYnkgc3Vic2NyaWJpbmcgdG8gdGhlIE9ic2VydmFibGUgcmV0dXJuZWQgYnkgdGhlIHBhcmFtIGBvYnNlcnZhYmxlUHJvZHVjZXJgIGNhbGxiYWNrLlxuICAgKlxuICAgKiBJZGVhbGx5IHRoZSBjYWxsYmFjayBmdW5jdGlvbiBjcmVhdGVzIGFuIE9ic2VydmFibGUgYnkgYXBwbHlpbmcgYE9ic2VydmFibGUucGlwZWAuXG4gICAqXG4gICAqIEp1c3Qga25vdyB0aGF0IHlvdSBzaG91bGQgY2F0Y2ggdGhlIGVycm9yIGluIGEgc3ViLXBpcGUgKGllOiBkbyBub3QgbGV0IGl0IHByb3BhZ2F0ZSB0byB0aGUgbWFpbi1waXBlKSwgb3RoZXJ3aXNlXG4gICAqIGFzIHVzdWFsIHRoZSBzdHJlYW0gd2lsbCBzdG9wIHdvcmtpbmcsIGFuZCB3aWxsIG5vdCByZWFjdCBvbiBhbnkgZnVydGhlciBlbWlzc2lvbnMuXG4gICAqXG4gICAqIEBwYXJhbSBvYnNlcnZhYmxlUHJvZHVjZXIgQSBjYWxsYmFjayBmdW5jdGlvbiB0aGF0IHNob3VsZCByZXR1cm4gYW4gT2JzZXJ2YWJsZS5cbiAgICpcbiAgICogQGNhdGVnb3J5IENvbW1vblxuICAgKi9cbiAgY3JlYXRlU3RyZWFtPFI+KG9ic2VydmFibGVQcm9kdWNlcjogQ2x1c3RlclN0cmVhbU9ic2VydmFibGVQcm9kdWNlcjx0aGlzLCBSPik6IFN0cmVhbSB7XG4gICAgY29uc3Qgb2JzZXJ2YWJsZSA9IG9ic2VydmFibGVQcm9kdWNlcih0aGlzKTtcblxuICAgIHJldHVybiBuZXcgU3RyZWFtKG9ic2VydmFibGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNlbGVjdCBhIGNoaWxkIGJ5IHByb3ZpZGluZyBpdHMga2V5LlxuICAgKlxuICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIGNoaWxkLlxuICAgKlxuICAgKiBAY2F0ZWdvcnkgQ3VzdG9tIENsdXN0ZXJcbiAgICovXG4gIHNlbGVjdDxrIGV4dGVuZHMgSz4oa2V5OiBrKTogVFtrXSB7XG4gICAgcmV0dXJuIHRoaXMuaXRlbXNba2V5XTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtcyB0aGUgc3BlY2lmaWVkIGFjdGlvbiBmb3IgZWFjaCBjaGlsZCBvZiB0aGUgQ2x1c3RlciB7QGxpbmsgaXRlbXN9LiBcXFxuICAgKiBJdCdzIGEgZHJvcC1pbiByZXBsYWNlbWVudCBmb3IgdGhlIGBmb3JFYWNoYCBtZXRob2QuXG4gICAqXG4gICAqIEBwYXJhbSBjYWxsYmFja0ZuIEEgZnVuY3Rpb24gdGhhdCBhY2NlcHRzIHVwIHRvIHRocmVlIGFyZ3VtZW50cy5cbiAgICogZm9yRXZlcnkgY2FsbHMgdGhlIGNhbGxiYWNrRm4gZnVuY3Rpb24gb25lIHRpbWUgZm9yIGVhY2ggZWxlbWVudCBpbiB0aGUgbGlzdC5cbiAgICogQHBhcmFtIHRoaXNBcmcgQW4gb2JqZWN0IHRvIHdoaWNoIHRoaXMga2V5d29yZCBjYW4gcmVmZXIgaW4gdGhlIGNhbGxiYWNrRm4gZnVuY3Rpb24uXG4gICAqIElmIHRoaXNBcmcgaXMgb21pdHRlZCwgdW5kZWZpbmVkIGlzIHVzZWQgYXMgdGhpcyB2YWx1ZS5cbiAgICpcbiAgICogQGNhdGVnb3J5IEN1c3RvbSBDbHVzdGVyXG4gICAqL1xuICBmb3JFdmVyeShcbiAgICBjYWxsYmFja0ZuOiAoaXRlbTogVFtLXSwga2V5OiBLLCBpbmRleDogbnVtYmVyLCBlbnRyaWVzOiBbSywgVFtLXV1bXSkgPT4gdm9pZCxcbiAgICB0aGlzQXJnPzogYW55XG4gICk6IHZvaWQge1xuICAgIE9iamVjdC5lbnRyaWVzKHRoaXMuaXRlbXMpLmZvckVhY2goKFtrZXksIGl0ZW1dLCBpLCBpdGVtc0FzRW50cmllcykgPT5cbiAgICAgIGNhbGxiYWNrRm4uY2FsbCh0aGlzQXJnLCBpdGVtLCBrZXksIGksIGl0ZW1zQXNFbnRyaWVzKVxuICAgICk7XG4gIH1cblxuICAvKiogSXRlcmF0b3IgKi9cbiAgW1N5bWJvbC5pdGVyYXRvcl0oKTogSXRlcmF0b3I8W0ssIFRbS11dPjtcbiAgLyoqXG4gICAqIEBpbnRlcm5hbCBwbGVhc2UgZG8gbm90IHVzZS5cbiAgICovXG4gIFtJdGVyYXRvclN5bWJvbF0oKTogSXRlcmF0b3I8W0ssIFRbS11dPiB7XG4gICAgbGV0IGluZGV4ID0gMDtcbiAgICBjb25zdCBpdGVtcyA9IE9iamVjdC5lbnRyaWVzKHRoaXMuaXRlbXMpIGFzIFtLLCBUW0tdXVtdO1xuICAgIGNvbnN0IGxlbmd0aDogbnVtYmVyID0gaXRlbXMubGVuZ3RoO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIG5leHQoKTogSXRlcmF0b3JSZXN1bHQ8W0ssIFRbS11dPiB7XG4gICAgICAgIHJldHVybiB7dmFsdWU6IGl0ZW1zW2luZGV4KytdLCBkb25lOiBpbmRleCA+IGxlbmd0aH07XG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsIHBsZWFzZSBkbyBub3QgdXNlLlxuICAgKi9cbiAgcHJpdmF0ZSBleHRyYWN0SXRlbXMoaXRlbXM6IFQpOiB2b2lkIHtcbiAgICB0aGlzLml0ZW1zS2V5cyA9IE9iamVjdC5rZXlzKGl0ZW1zKS5maWx0ZXIoa2V5ID0+IGl0ZW1zW2tleV0gaW5zdGFuY2VvZiBCYXNlKSBhcyBLW107XG4gICAgdGhpcy5faXRlbXNDb3VudCA9IHRoaXMuaXRlbXNLZXlzLmxlbmd0aDtcblxuICAgIHRoaXMuaXRlbXNLZXlzLmZvckVhY2goa2V5ID0+IHtcbiAgICAgICh0aGlzLml0ZW1zIGFzIFQpW2tleV0gPSBpdGVtc1trZXldO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbCBwbGVhc2UgZG8gbm90IHVzZS5cbiAgICovXG4gIHByaXZhdGUgc3RhcnRMaXN0ZW5pbmdBbmRFbWl0dGluZygpOiB2b2lkIHtcbiAgICB0aGlzLmVtaXQoKTtcbiAgICBtZXJnZSguLi5PYmplY3QudmFsdWVzKHRoaXMuaXRlbXMpLm1hcChpdGVtID0+IGl0ZW0uZnV0dXJlJCkpLnN1YnNjcmliZSgoKSA9PiB0aGlzLmVtaXQoKSk7XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsIHBsZWFzZSBkbyBub3QgdXNlLlxuICAgKi9cbiAgcHJvdGVjdGVkIGVtaXQodmFsdWUgPSB0aGlzLmNvbWJpbmVkRW1pdHRlZFZhbHVlcygpKTogdm9pZCB7XG4gICAgaWYgKENvbmZpZ3VyYXRpb24uRU5WSVJPTk1FTlQuY2hlY2tJbW11dGFiaWxpdHkgPT09IHRydWUpIHtcbiAgICAgIE9iamVjdC5mcmVlemUodmFsdWUpO1xuICAgIH1cbiAgICBzdXBlci5lbWl0KHZhbHVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaW50ZXJuYWwgcGxlYXNlIGRvIG5vdCB1c2UuXG4gICAqL1xuICBwcml2YXRlIGNvbWJpbmVkRW1pdHRlZFZhbHVlcygpIHtcbiAgICByZXR1cm4gdGhpcy5pdGVtc0tleXMucmVkdWNlKChyZWR1Y2VkLCBrZXkpID0+IHtcbiAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1zdHJpbmctbGl0ZXJhbFxuICAgICAgcmVkdWNlZFtrZXldID0gdGhpcy5pdGVtc1trZXldWydlbWl0dGVkVmFsdWUnXTtcbiAgICAgIHJldHVybiByZWR1Y2VkO1xuICAgIH0sIHt9IGFzIGFueSkgYXMgVjtcbiAgfVxufVxuIl19