UNPKG

@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
/* 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==