@ssv/ngx.command
Version:
Command pattern implementation for angular. Command used to encapsulate information which is needed to perform an action.
160 lines • 23.2 kB
JavaScript
/* eslint-disable @typescript-eslint/no-explicit-any */
import { combineLatest, Subscription, Subject, BehaviorSubject, of, EMPTY, tap, map, filter, switchMap, catchError, finalize, take, } from "rxjs";
import { assertInInjectionContext, computed, DestroyRef, inject, Injector, isSignal } from "@angular/core";
import { toObservable } from "@angular/core/rxjs-interop";
const COMMAND_ASYNC_DEFAULT_OPTIONS = { isAsync: true };
/** Creates an async {@link Command}. Must be used within an injection context.
* NOTE: this auto injects `DestroyRef` and handles auto destroy. {@link ICommand.autoDestroy} should not be used.
*/
export function commandAsync(execute, canExecute$, opts) {
return command(execute, canExecute$, opts ? { ...opts, ...COMMAND_ASYNC_DEFAULT_OPTIONS } : COMMAND_ASYNC_DEFAULT_OPTIONS);
}
/** Creates a {@link Command}. Must be used within an injection context.
* NOTE: this auto injects `DestroyRef` and handles auto destroy. {@link ICommand.autoDestroy} should not be used.
*/
export function command(execute, canExecute$, opts) {
if (!opts?.injector) {
assertInInjectionContext(command);
}
const injector = opts?.injector ?? inject(Injector);
const isAsync = opts?.isAsync ?? false;
const destroyRef = injector.get(DestroyRef);
const cmd = new Command(execute, canExecute$, isAsync);
cmd.autoDestroy = false;
destroyRef.onDestroy(() => {
// console.warn("[command::destroy]");
cmd.destroy();
});
return cmd;
}
/**
* Command object used to encapsulate information which is needed to perform an action.
* @deprecated Use {@link command} or {@link commandAsync} instead for creating instances.
*/
export class Command {
/** Determines whether the command is currently executing, as a snapshot value. */
get isExecuting() {
return this._isExecuting;
}
/** Determines whether the command can execute or not, as a snapshot value. */
get canExecute() {
return this._canExecute;
}
/** Determines whether the command is currently executing, as an observable. */
get isExecuting$() {
return this._isExecuting$.asObservable();
}
/** Determines whether to auto destroy when having 0 subscribers. */
autoDestroy = true;
/** Determines whether the command can execute or not, as an observable. */
canExecute$;
_isExecuting$ = new BehaviorSubject(false);
_isExecuting = false;
_canExecute = true;
executionPipe$ = new Subject();
isExecuting$$ = Subscription.EMPTY;
canExecute$$ = Subscription.EMPTY;
executionPipe$$ = Subscription.EMPTY;
subscribersCount = 0;
/**
* Creates an instance of Command.
*
* @param execute Execute function to invoke - use `isAsync: true` when `Observable<any>`.
* @param canExecute Observable which determines whether it can execute or not.
* @param isAsync Indicates that the execute function is async e.g. Observable.
*/
constructor(execute, canExecute$, isAsync, injector) {
if (canExecute$) {
const canExecute = typeof canExecute$ === "function"
? computed(canExecute$)
: canExecute$;
this.canExecute$ = combineLatest([
this._isExecuting$,
isSignal(canExecute) ? toObservable(canExecute, { injector }) : canExecute
]).pipe(map(([isExecuting, canExecuteResult]) => {
// console.log("[command::combineLatest$] update!", { isExecuting, canExecuteResult });
this._isExecuting = isExecuting;
this._canExecute = !isExecuting && !!canExecuteResult;
return this._canExecute;
}));
this.canExecute$$ = this.canExecute$.subscribe();
}
else {
this.canExecute$ = this._isExecuting$.pipe(map(x => {
const canExecute = !x;
this._canExecute = canExecute;
return canExecute;
}));
this.isExecuting$$ = this._isExecuting$
.pipe(tap(x => this._isExecuting = x))
.subscribe();
}
this.executionPipe$$ = this.buildExecutionPipe(execute, isAsync).subscribe();
}
/** Execute function to invoke. */
execute(...args) {
// console.warn("[command::execute]", args);
this.executionPipe$.next(args);
}
/** Disposes all resources held by subscriptions. */
destroy() {
// console.warn("[command::destroy]");
this.executionPipe$$.unsubscribe();
this.canExecute$$.unsubscribe();
this.isExecuting$$.unsubscribe();
}
subscribe() {
this.subscribersCount++;
}
unsubscribe() {
this.subscribersCount--;
// console.log("[command::unsubscribe]", { autoDestroy: this.autoDestroy, subscribersCount: this.subscribersCount });
if (this.autoDestroy && this.subscribersCount <= 0) {
this.destroy();
}
}
buildExecutionPipe(execute, isAsync) {
let pipe$ = this.executionPipe$.pipe(
// tap(x => console.warn(">>>> executionPipe", this._canExecute)),
filter(() => this._canExecute), tap(() => {
// console.log("[command::executionPipe$] do#1 - set execute", { args: x });
this._isExecuting$.next(true);
}));
const execFn = isAsync
? switchMap(args => {
if (args) {
return execute(...args);
}
return execute();
})
: tap((args) => {
if (args) {
execute(...args);
return;
}
execute();
});
pipe$ = pipe$.pipe(switchMap(args => of(args).pipe(execFn, finalize(() => {
// console.log("[command::executionPipe$] finalize inner#1 - set idle");
this._isExecuting$.next(false);
}), take(1), catchError(error => {
console.error("Unhandled execute error", error);
return EMPTY;
}))), tap(() => {
// console.log("[command::executionPipe$] tap#2 - set idle");
this._isExecuting$.next(false);
}));
return pipe$;
}
}
/**
* Async Command object used to encapsulate information which is needed to perform an action,
* which takes an execute function as Observable/Promise.
* @deprecated Use {@link commandAsync} instead.
*/
export class CommandAsync extends Command {
constructor(execute, canExecute$) {
super(execute, canExecute$, true);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbWFuZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYnMvbmd4LmNvbW1hbmQvc3JjL2NvbW1hbmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsdURBQXVEO0FBQ3ZELE9BQU8sRUFDTSxhQUFhLEVBQUUsWUFBWSxFQUFFLE9BQU8sRUFBRSxlQUFlLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFDNUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsSUFBSSxHQUN2RCxNQUFNLE1BQU0sQ0FBQztBQUVkLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFlLE1BQU0sZUFBZSxDQUFDO0FBQ3hILE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQVcxRCxNQUFNLDZCQUE2QixHQUF5QixFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQztBQUU5RTs7R0FFRztBQUNILE1BQU0sVUFBVSxZQUFZLENBQzNCLE9BQXVCLEVBQ3ZCLFdBQXdCLEVBQ3hCLElBQTRDO0lBRTVDLE9BQU8sT0FBTyxDQUFDLE9BQU8sRUFBRSxXQUFXLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsSUFBSSxFQUFFLEdBQUcsNkJBQTZCLEVBQUUsQ0FBQyxDQUFDLENBQUMsNkJBQTZCLENBQUMsQ0FBQztBQUM1SCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLFVBQVUsT0FBTyxDQUN0QixPQUFrQixFQUNsQixXQUF3QixFQUN4QixJQUEyQjtJQUUzQixJQUFJLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxDQUFDO1FBQ3JCLHdCQUF3QixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFDRCxNQUFNLFFBQVEsR0FBRyxJQUFJLEVBQUUsUUFBUSxJQUFJLE1BQU0s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Q0YsR0FBRyxDQUNGLEdBQUcsRUFBRTtZQUNKLDZEQUE2RDtZQUM3RCxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNoQyxDQUFDLENBQ0QsQ0FDRCxDQUFDO1FBQ0YsT0FBTyxLQUFLLENBQUM7SUFDZCxDQUFDO0NBRUQ7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxPQUFPLFlBQWEsU0FBUSxPQUFPO0lBRXhDLFlBQ0MsT0FBdUIsRUFDdkIsV0FBd0I7UUFFeEIsS0FBSyxDQUFDLE9BQU8sRUFBRSxXQUFXLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDbkMsQ0FBQztDQUVEIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSAqL1xuaW1wb3J0IHtcblx0T2JzZXJ2YWJsZSwgY29tYmluZUxhdGVzdCwgU3Vic2NyaXB0aW9uLCBTdWJqZWN0LCBCZWhhdmlvclN1YmplY3QsIG9mLCBFTVBUWSxcblx0dGFwLCBtYXAsIGZpbHRlciwgc3dpdGNoTWFwLCBjYXRjaEVycm9yLCBmaW5hbGl6ZSwgdGFrZSxcbn0gZnJvbSBcInJ4anNcIjtcbmltcG9ydCB0eXBlIHsgSUNvbW1hbmQgfSBmcm9tIFwiLi9jb21tYW5kLm1vZGVsXCI7XG5pbXBvcnQgeyBhc3NlcnRJbkluamVjdGlvbkNvbnRleHQsIGNvbXB1dGVkLCBEZXN0cm95UmVmLCBpbmplY3QsIEluamVjdG9yLCBpc1NpZ25hbCwgdHlwZSBTaWduYWwgfSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgdG9PYnNlcnZhYmxlIH0gZnJvbSBcIkBhbmd1bGFyL2NvcmUvcnhqcy1pbnRlcm9wXCI7XG5cbmV4cG9ydCB0eXBlIEV4ZWN1dGVGbiA9ICguLi5hcmdzOiBhbnlbXSkgPT4gdW5rbm93bjtcbmV4cG9ydCB0eXBlIEV4ZWN1dGVBc3luY0ZuID0gKC4uLmFyZ3M6IGFueVtdKSA9PiBPYnNlcnZhYmxlPHVua25vd24+IHwgUHJvbWlzZTx1bmtub3duPjtcbmV4cG9ydCB0eXBlIENhbkV4ZWN1dGUgPSAoKCkgPT4gYm9vbGVhbikgfCBTaWduYWw8Ym9vbGVhbj4gfCBPYnNlcnZhYmxlPGJvb2xlYW4+O1xuXG5leHBvcnQgaW50ZXJmYWNlIENvbW1hbmRDcmVhdGVPcHRpb25zIHtcblx0aXNBc3luYzogYm9vbGVhbixcblx0aW5qZWN0b3I/OiBJbmplY3Rvcjtcbn1cblxuY29uc3QgQ09NTUFORF9BU1lOQ19ERUZBVUxUX09QVElPTlM6IENvbW1hbmRDcmVhdGVPcHRpb25zID0geyBpc0FzeW5jOiB0cnVlIH07XG5cbi8qKiBDcmVhdGVzIGFuIGFzeW5jIHtAbGluayBDb21tYW5kfS4gTXVzdCBiZSB1c2VkIHdpdGhpbiBhbiBpbmplY3Rpb24gY29udGV4dC5cbiAqIE5PVEU6IHRoaXMgYXV0byBpbmplY3RzIGBEZXN0cm95UmVmYCBhbmQgaGFuZGxlcyBhdXRvIGRlc3Ryb3kuIHtAbGluayBJQ29tbWFuZC5hdXRvRGVzdHJveX0gc2hvdWxkIG5vdCBiZSB1c2VkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY29tbWFuZEFzeW5jKFxuXHRleGVjdXRlOiBFeGVjdXRlQXN5bmNGbixcblx0Y2FuRXhlY3V0ZSQ/OiBDYW5FeGVjdXRlLFxuXHRvcHRzPzogT21pdDxDb21tYW5kQ3JlYXRlT3B0aW9ucywgXCJpc0FzeW5jXCI+LFxuKTogQ29tbWFuZCB7XG5cdHJldHVybiBjb21tYW5kKGV4ZWN1dGUsIGNhbkV4ZWN1dGUkLCBvcHRzID8geyAuLi5vcHRzLCAuLi5DT01NQU5EX0FTWU5DX0RFRkFVTFRfT1BUSU9OUyB9IDogQ09NTUFORF9BU1lOQ19ERUZBVUxUX09QVElPTlMpO1xufVxuXG4vKiogQ3JlYXRlcyBhIHtAbGluayBDb21tYW5kfS4gTXVzdCBiZSB1c2VkIHdpdGhpbiBhbiBpbmplY3Rpb24gY29udGV4dC5cbiAqIE5PVEU6IHRoaXMgYXV0byBpbmplY3RzIGBEZXN0cm95UmVmYCBhbmQgaGFuZGxlcyBhdXRvIGRlc3Ryb3kuIHtAbGluayBJQ29tbWFuZC5hdXRvRGVzdHJveX0gc2hvdWxkIG5vdCBiZSB1c2VkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY29tbWFuZChcblx0ZXhlY3V0ZTogRXhlY3V0ZUZuLFxuXHRjYW5FeGVjdXRlJD86IENhbkV4ZWN1dGUsXG5cdG9wdHM/OiBDb21tYW5kQ3JlYXRlT3B0aW9ucyxcbik6IENvbW1hbmQge1xuXHRpZiAoIW9wdHM/LmluamVjdG9yKSB7XG5cdFx0YXNzZXJ0SW5JbmplY3Rpb25Db250ZXh0KGNvbW1hbmQpO1xuXHR9XG5cdGNvbnN0IGluamVjdG9yID0gb3B0cz8uaW5qZWN0b3IgPz8gaW5qZWN0KEluamVjdG9yKTtcblx0Y29uc3QgaXNBc3luYyA9IG9wdHM/LmlzQXN5bmMgPz8gZmFsc2U7XG5cdGNvbnN0IGRlc3Ryb3lSZWYgPSBpbmplY3Rvci5nZXQoRGVzdHJveVJlZik7XG5cdGNvbnN0IGNtZCA9IG5ldyBDb21tYW5kKGV4ZWN1dGUsIGNhbkV4ZWN1dGUkLCBpc0FzeW5jKTtcblx0Y21kLmF1dG9EZXN0cm95ID0gZmFsc2U7XG5cblx0ZGVzdHJveVJlZi5vbkRlc3Ryb3koKCkgPT4ge1xuXHRcdC8vIGNvbnNvbGUud2FybihcIltjb21tYW5kOjpkZXN0cm95XVwiKTtcblx0XHRjbWQuZGVzdHJveSgpO1xuXHR9KTtcblx0cmV0dXJuIGNtZDtcbn1cblxuLyoqXG4gKiBDb21tYW5kIG9iamVjdCB1c2VkIHRvIGVuY2Fwc3VsYXRlIGluZm9ybWF0aW9uIHdoaWNoIGlzIG5lZWRlZCB0byBwZXJmb3JtIGFuIGFjdGlvbi5cbiAqIEBkZXByZWNhdGVkIFVzZSB7QGxpbmsgY29tbWFuZH0gb3Ige0BsaW5rIGNvbW1hbmRBc3luY30gaW5zdGVhZCBmb3IgY3JlYXRpbmcgaW5zdGFuY2VzLlxuICovXG5leHBvcnQgY2xhc3MgQ29tbWFuZCBpbXBsZW1lbnRzIElDb21tYW5kIHtcblxuXHQvKiogRGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBjb21tYW5kIGlzIGN1cnJlbnRseSBleGVjdXRpbmcsIGFzIGEgc25hcHNob3QgdmFsdWUuICovXG5cdGdldCBpc0V4ZWN1dGluZygpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gdGhpcy5faXNFeGVjdXRpbmc7XG5cdH1cblxuXHQvKiogRGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBjb21tYW5kIGNhbiBleGVjdXRlIG9yIG5vdCwgYXMgYSBzbmFwc2hvdCB2YWx1ZS4gKi9cblx0Z2V0IGNhbkV4ZWN1dGUoKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHRoaXMuX2NhbkV4ZWN1dGU7XG5cdH1cblxuXHQvKiogRGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBjb21tYW5kIGlzIGN1cnJlbnRseSBleGVjdXRpbmcsIGFzIGFuIG9ic2VydmFibGUuICovXG5cdGdldCBpc0V4ZWN1dGluZyQoKTogT2JzZXJ2YWJsZTxib29sZWFuPiB7XG5cdFx0cmV0dXJuIHRoaXMuX2lzRXhlY3V0aW5nJC5hc09ic2VydmFibGUoKTtcblx0fVxuXG5cdC8qKiBEZXRlcm1pbmVzIHdoZXRoZXIgdG8gYXV0byBkZXN0cm95IHdoZW4gaGF2aW5nIDAgc3Vic2NyaWJlcnMuICovXG5cdGF1dG9EZXN0cm95ID0gdHJ1ZTtcblxuXHQvKiogRGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBjb21tYW5kIGNhbiBleGVjdXRlIG9yIG5vdCwgYXMgYW4gb2JzZXJ2YWJsZS4gKi9cblx0cmVhZG9ubHkgY2FuRXhlY3V0ZSQ6IE9ic2VydmFibGU8Ym9vbGVhbj47XG5cblx0cHJpdmF0ZSBfaXNFeGVjdXRpbmckID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihmYWxzZSk7XG5cdHByaXZhdGUgX2lzRXhlY3V0aW5nID0gZmFsc2U7XG5cdHByaXZhdGUgX2NhbkV4ZWN1dGUgPSB0cnVlO1xuXHRwcml2YXRlIGV4ZWN1dGlvblBpcGUkID0gbmV3IFN1YmplY3Q8dW5rbm93bltdIHwgdW5kZWZpbmVkPigpO1xuXHRwcml2YXRlIGlzRXhlY3V0aW5nJCQgPSBTdWJzY3JpcHRpb24uRU1QVFk7XG5cdHByaXZhdGUgY2FuRXhlY3V0ZSQkID0gU3Vic2NyaXB0aW9uLkVNUFRZO1xuXHRwcml2YXRlIGV4ZWN1dGlvblBpcGUkJCA9IFN1YnNjcmlwdGlvbi5FTVBUWTtcblx0cHJpdmF0ZSBzdWJzY3JpYmVyc0NvdW50ID0gMDtcblxuXHQvKipcblx0ICogQ3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBDb21tYW5kLlxuXHQgKlxuXHQgKiBAcGFyYW0gZXhlY3V0ZSBFeGVjdXRlIGZ1bmN0aW9uIHRvIGludm9rZSAtIHVzZSBgaXNBc3luYzogdHJ1ZWAgd2hlbiBgT2JzZXJ2YWJsZTxhbnk+YC5cblx0ICogQHBhcmFtIGNhbkV4ZWN1dGUgT2JzZXJ2YWJsZSB3aGljaCBkZXRlcm1pbmVzIHdoZXRoZXIgaXQgY2FuIGV4ZWN1dGUgb3Igbm90LlxuXHQgKiBAcGFyYW0gaXNBc3luYyBJbmRpY2F0ZXMgdGhhdCB0aGUgZXhlY3V0ZSBmdW5jdGlvbiBpcyBhc3luYyBlLmcuIE9ic2VydmFibGUuXG5cdCAqL1xuXHRjb25zdHJ1Y3Rvcihcblx0XHRleGVjdXRlOiBFeGVjdXRlRm4sXG5cdFx0Y2FuRXhlY3V0ZSQ/OiBDYW5FeGVjdXRlLFxuXHRcdGlzQXN5bmM/OiBib29sZWFuLFxuXHRcdGluamVjdG9yPzogSW5qZWN0b3IsXG5cdCkge1xuXHRcdGlmIChjYW5FeGVjdXRlJCkge1xuXHRcdFx0Y29uc3QgY2FuRXhlY3V0ZSA9IHR5cGVvZiBjYW5FeGVjdXRlJCA9PT0gXCJmdW5jdGlvblwiXG5cdFx0XHRcdD8gY29tcHV0ZWQoY2FuRXhlY3V0ZSQpXG5cdFx0XHRcdDogY2FuRXhlY3V0ZSQ7XG5cdFx0XHR0aGlzLmNhbkV4ZWN1dGUkID0gY29tYmluZUxhdGVzdChbXG5cdFx0XHRcdHRoaXMuX2lzRXhlY3V0aW5nJCxcblx0XHRcdFx0aXNTaWduYWwoY2FuRXhlY3V0ZSkgPyB0b09ic2VydmFibGUoY2FuRXhlY3V0ZSwgeyBpbmplY3RvciB9KSA6IGNhbkV4ZWN1dGVcblx0XHRcdF0pLnBpcGUoXG5cdFx0XHRcdG1hcCgoW2lzRXhlY3V0aW5nLCBjYW5FeGVjdXRlUmVzdWx0XSkgPT4ge1xuXHRcdFx0XHRcdC8vIGNvbnNvbGUubG9nKFwiW2NvbW1hbmQ6OmNvbWJpbmVMYXRlc3QkXSB1cGRhdGUhXCIsIHsgaXNFeGVjdXRpbmcsIGNhbkV4ZWN1dGVSZXN1bHQgfSk7XG5cdFx0XHRcdFx0dGhpcy5faXNFeGVjdXRpbmcgPSBpc0V4ZWN1dGluZztcblx0XHRcdFx0XHR0aGlzLl9jYW5FeGVjdXRlID0gIWlzRXhlY3V0aW5nICYmICEhY2FuRXhlY3V0ZVJlc3VsdDtcblx0XHRcdFx0XHRyZXR1cm4gdGhpcy5fY2FuRXhlY3V0ZTtcblx0XHRcdFx0fSksXG5cdFx0XHQpO1xuXHRcdFx0dGhpcy5jYW5FeGVjdXRlJCQgPSB0aGlzLmNhbkV4ZWN1dGUkLnN1YnNjcmliZSgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLmNhbkV4ZWN1dGUkID0gdGhpcy5faXNFeGVjdXRpbmckLnBpcGUoXG5cdFx0XHRcdG1hcCh4ID0+IHtcblx0XHRcdFx0XHRjb25zdCBjYW5FeGVjdXRlID0gIXg7XG5cdFx0XHRcdFx0dGhpcy5fY2FuRXhlY3V0ZSA9IGNhbkV4ZWN1dGU7XG5cdFx0XHRcdFx0cmV0dXJuIGNhbkV4ZWN1dGU7XG5cdFx0XHRcdH0pXG5cdFx0XHQpO1xuXHRcdFx0dGhpcy5pc0V4ZWN1dGluZyQkID0gdGhpcy5faXNFeGVjdXRpbmckXG5cdFx0XHRcdC5waXBlKHRhcCh4ID0+IHRoaXMuX2lzRXhlY3V0aW5nID0geCkpXG5cdFx0XHRcdC5zdWJzY3JpYmUoKTtcblx0XHR9XG5cdFx0dGhpcy5leGVjdXRpb25QaXBlJCQgPSB0aGlzLmJ1aWxkRXhlY3V0aW9uUGlwZShleGVjdXRlLCBpc0FzeW5jKS5zdWJzY3JpYmUoKTtcblx0fVxuXG5cdC8qKiBFeGVjdXRlIGZ1bmN0aW9uIHRvIGludm9rZS4gKi9cblx0ZXhlY3V0ZSguLi5hcmdzOiB1bmtub3duW10pOiB2b2lkIHtcblx0XHQvLyBjb25zb2xlLndhcm4oXCJbY29tbWFuZDo6ZXhlY3V0ZV1cIiwgYXJncyk7XG5cdFx0dGhpcy5leGVjdXRpb25QaXBlJC5uZXh0KGFyZ3MpO1xuXHR9XG5cblx0LyoqIERpc3Bvc2VzIGFsbCByZXNvdXJjZXMgaGVsZCBieSBzdWJzY3JpcHRpb25zLiAqL1xuXHRkZXN0cm95KCk6IHZvaWQge1xuXHRcdC8vIGNvbnNvbGUud2FybihcIltjb21tYW5kOjpkZXN0cm95XVwiKTtcblx0XHR0aGlzLmV4ZWN1dGlvblBpcGUkJC51bnN1YnNjcmliZSgpO1xuXHRcdHRoaXMuY2FuRXhlY3V0ZSQkLnVuc3Vic2NyaWJlKCk7XG5cdFx0dGhpcy5pc0V4ZWN1dGluZyQkLnVuc3Vic2NyaWJlKCk7XG5cdH1cblxuXHRzdWJzY3JpYmUoKTogdm9pZCB7XG5cdFx0dGhpcy5zdWJzY3JpYmVyc0NvdW50Kys7XG5cdH1cblxuXHR1bnN1YnNjcmliZSgpOiB2b2lkIHtcblx0XHR0aGlzLnN1YnNjcmliZXJzQ291bnQtLTtcblx0XHQvLyBjb25zb2xlLmxvZyhcIltjb21tYW5kOjp1bnN1YnNjcmliZV1cIiwgeyBhdXRvRGVzdHJveTogdGhpcy5hdXRvRGVzdHJveSwgc3Vic2NyaWJlcnNDb3VudDogdGhpcy5zdWJzY3JpYmVyc0NvdW50IH0pO1xuXHRcdGlmICh0aGlzLmF1dG9EZXN0cm95ICYmIHRoaXMuc3Vic2NyaWJlcnNDb3VudCA8PSAwKSB7XG5cdFx0XHR0aGlzLmRlc3Ryb3koKTtcblx0XHR9XG5cdH1cblxuXHRwcml2YXRlIGJ1aWxkRXhlY3V0aW9uUGlwZShleGVjdXRlOiAoLi4uYXJnczogdW5rbm93bltdKSA9PiBhbnksIGlzQXN5bmM/OiBib29sZWFuKTogT2JzZXJ2YWJsZTx1bmtub3duPiB7XG5cdFx0bGV0IHBpcGUkID0gdGhpcy5leGVjdXRpb25QaXBlJC5waXBlKFxuXHRcdFx0Ly8gdGFwKHggPT4gY29uc29sZS53YXJuKFwiPj4+PiBleGVjdXRpb25QaXBlXCIsIHRoaXMuX2NhbkV4ZWN1dGUpKSxcblx0XHRcdGZpbHRlcigoKSA9PiB0aGlzLl9jYW5FeGVjdXRlKSxcblx0XHRcdHRhcCgoKSA9PiB7XG5cdFx0XHRcdC8vIGNvbnNvbGUubG9nKFwiW2NvbW1hbmQ6OmV4ZWN1dGlvblBpcGUkXSBkbyMxIC0gc2V0IGV4ZWN1dGVcIiwgeyBhcmdzOiB4IH0pO1xuXHRcdFx0XHR0aGlzLl9pc0V4ZWN1dGluZyQubmV4dCh0cnVlKTtcblx0XHRcdH0pXG5cdFx0KTtcblxuXHRcdGNvbnN0IGV4ZWNGbiA9IGlzQXN5bmNcblx0XHRcdD8gc3dpdGNoTWFwPHVua25vd25bXSB8IHVuZGVmaW5lZCwgYW55W10+KGFyZ3MgPT4ge1xuXHRcdFx0XHRpZiAoYXJncykge1xuXHRcdFx0XHRcdHJldHVybiBleGVjdXRlKC4uLmFyZ3MpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiBleGVjdXRlKCk7XG5cdFx0XHR9KVxuXHRcdFx0OiB0YXAoKGFyZ3M6IHVua25vd25bXSB8IHVuZGVmaW5lZCkgPT4ge1xuXHRcdFx0XHRpZiAoYXJncykge1xuXHRcdFx0XHRcdGV4ZWN1dGUoLi4uYXJncyk7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGV4ZWN1dGUoKTtcblx0XHRcdH0pO1xuXG5cdFx0cGlwZSQgPSBwaXBlJC5waXBlKFxuXHRcdFx0c3dpdGNoTWFwKGFyZ3MgPT4gb2YoYXJncykucGlwZShcblx0XHRcdFx0ZXhlY0ZuLFxuXHRcdFx0XHRmaW5hbGl6ZSgoKSA9PiB7XG5cdFx0XHRcdFx0Ly8gY29uc29sZS5sb2coXCJbY29tbWFuZDo6ZXhlY3V0aW9uUGlwZSRdICBmaW5hbGl6ZSBpbm5lciMxIC0gc2V0IGlkbGVcIik7XG5cdFx0XHRcdFx0dGhpcy5faXNFeGVjdXRpbmckLm5leHQoZmFsc2UpO1xuXHRcdFx0XHR9KSxcblx0XHRcdFx0dGFrZSgxKSxcblx0XHRcdFx0Y2F0Y2hFcnJvcihlcnJvciA9PiB7XG5cdFx0XHRcdFx0Y29uc29sZS5lcnJvcihcIlVuaGFuZGxlZCBleGVjdXRlIGVycm9yXCIsIGVycm9yKTtcblx0XHRcdFx0XHRyZXR1cm4gRU1QVFk7XG5cdFx0XHRcdH0pLFxuXHRcdFx0KSksXG5cdFx0XHR0YXAoXG5cdFx0XHRcdCgpID0+IHtcblx0XHRcdFx0XHQvLyBjb25zb2xlLmxvZyhcIltjb21tYW5kOjpleGVjdXRpb25QaXBlJF0gdGFwIzIgLSBzZXQgaWRsZVwiKTtcblx0XHRcdFx0XHR0aGlzLl9pc0V4ZWN1dGluZyQubmV4dChmYWxzZSk7XG5cdFx0XHRcdH0sXG5cdFx0XHQpXG5cdFx0KTtcblx0XHRyZXR1cm4gcGlwZSQ7XG5cdH1cblxufVxuXG4vKipcbiAqIEFzeW5jIENvbW1hbmQgb2JqZWN0IHVzZWQgdG8gZW5jYXBzdWxhdGUgaW5mb3JtYXRpb24gd2hpY2ggaXMgbmVlZGVkIHRvIHBlcmZvcm0gYW4gYWN0aW9uLFxuICogd2hpY2ggdGFrZXMgYW4gZXhlY3V0ZSBmdW5jdGlvbiBhcyBPYnNlcnZhYmxlL1Byb21pc2UuXG4gKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rIGNvbW1hbmRBc3luY30gaW5zdGVhZC5cbiAqL1xuZXhwb3J0IGNsYXNzIENvbW1hbmRBc3luYyBleHRlbmRzIENvbW1hbmQge1xuXG5cdGNvbnN0cnVjdG9yKFxuXHRcdGV4ZWN1dGU6IEV4ZWN1dGVBc3luY0ZuLFxuXHRcdGNhbkV4ZWN1dGUkPzogQ2FuRXhlY3V0ZSxcblx0KSB7XG5cdFx0c3VwZXIoZXhlY3V0ZSwgY2FuRXhlY3V0ZSQsIHRydWUpO1xuXHR9XG5cbn1cbiJdfQ==