UNPKG

@iotize/ionic

Version:

Iotize specific building blocks on top of @ionic/angular.

299 lines 38.1 kB
import { Inject, Injectable } from '@angular/core'; import { isCodeError } from '@iotize/common/error'; import { TapClientError } from '@iotize/tap/client/impl'; import { Observable, Subject, throwError } from 'rxjs'; import { share } from 'rxjs/operators'; import { isTapUserNotAuthorizedError } from '../error-utility'; import { debug } from '../logger'; import { TASK_MANAGER_RESOLUTION_SERVICE, } from './provider'; import * as i0 from "@angular/core"; const TAG = 'TaskManager'; const characters = 'abcdefghijklmnopqrstuvwxyz0123456789'; export function randomId() { let result = ''; const charactersLength = characters.length; for (let i = 0; i < 20; i++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; } export class TaskManagerService { taskErrorResolutionService; _tasks; _events; get events() { return this._events.asObservable(); } get tasks() { return this._tasks.map((container) => container.task); } constructor(taskErrorResolutionService) { this.taskErrorResolutionService = taskErrorResolutionService; debug(TAG, 'new instance!'); this._tasks = []; this._events = new Subject(); } createTask(task, options = {}) { if (this.hasTask(task.id)) { this.clearTask(task.id); } const taskContainer = { task: task, meta: { state: 'pending', }, events: new Subject(), }; let position; if (options.position !== undefined) { this._tasks[options.position] = taskContainer; position = options.position; } else { const newLength = this._tasks.push(taskContainer); position = newLength - 1; } debug(TAG, 'createTask', task.id, 'position', position); return taskContainer; } removeTask(id) { const index = this.getTaskPosition(id); if (index >= 0) { const [task] = this._tasks.splice(index, 1); this._cancel(task); debug(TAG, 'removed task', task.task.id, 'position', index); } } hasTask(id) { return this.getTaskPosition(id) !== -1; } task(id) { const container = this.container(id); if (container) { return container.task; } return undefined; } container(id) { const index = this.getTaskPosition(id); if (index >= 0) { return this._tasks[index]; } return undefined; } cancel(id) { const index = this.getTaskPosition(id); if (index >= 0) { this._cancel(this._tasks[index]); } else { debug(TAG, 'task ', id, 'does not exist. Cannot cancel'); } } taskMeta(id) { const container = this.container(id); if (container) { return container.meta; } return undefined; } addTaskContainer(container) { this._tasks.push(container); } addTask$(task, options = {}) { const taskContainer = this.createTask(task, options); return taskContainer.events; } clearTask(id) { const taskIndex = this.getTaskPosition(id); if (taskIndex !== -1) { const removed = this._tasks.splice(taskIndex, 1); if (removed.length !== 1) { throw new Error(`Internal error: clear task removed ${removed.length} task(s). Clear task must removed exactly 1 task. It's probably a bug.`); } debug(TAG, `${removed[0].task.id}: cleared`); } else { debug(TAG, `${id}: does not exist, cannot remove`); } } cancelAll() { this._tasks.forEach((task) => { this._cancel(task); }); } clearAll() { this._tasks = []; } exec(taskId, context) { const container = this.container(taskId); if (!container) { return throwError(new Error(`Task with id "${taskId}" does not exist`)); } container.meta.context = context; return this.execAsObservable(container); } execAsObservable(task) { return new Observable((emitter) => { (async () => { try { await this._exec(task, emitter); emitter.complete(); } catch (err) { emitter.error(err); } })(); }).pipe(share()); } async retry(container) { return (await this.execAsObservable(container).toPromise()).result; } execNext() { return new Observable((emitter) => { (async () => { try { if (this._tasks.length > 0) { await this._exec(this._tasks[0], emitter); } emitter.complete(); } catch (err) { emitter.error(err); } })(); }).pipe(share()); } execDelayedTasks() { return this.execTasksByState('delayed'); } execPendingTasks() { return this.execTasksByState('pending'); } execTasksByState(state) { const obs = new Observable((emitter) => { let stop = false; (async () => { try { const pendingTasks = this._tasks.filter((container) => container.meta.state === state); debug(TAG, `execAll() with ${pendingTasks.length} task(s) (state == ${state}): ${pendingTasks .map((task) => task.task.id) .join(', ')}`); for (const pendingTask of pendingTasks) { if (!stop) { await this._exec(pendingTask, emitter); } } debug(TAG, 'execAll() COMPLETED'); emitter.complete(); } catch (err) { debug(TAG, 'execAll() ERROR'); emitter.error(err); } })(); return () => { stop = true; // Nothing to do when unsubscribing }; }); return obs.pipe(share()); } getTaskPosition(id) { // Reversed for LIFO management of tasks with the same id. // TO VALIDATE return this._tasks .reverse() .findIndex((container) => container.task.id === id); } async _exec(taskContainer, emitter) { const task = taskContainer.task; try { debug(TAG, `${task.id} _exec() starting`); taskContainer.meta.state = 'running'; this._emit({ type: 'BEFORE_TASK', task: task, }, [emitter, taskContainer.events]); const result = await task.exec(taskContainer.meta.context); // this.clearTask(task.id); this._emit({ type: 'AFTER_TASK', task: task, result: result, }, [emitter, taskContainer.events]); taskContainer.meta.result = result; taskContainer.meta.state = 'done'; debug(TAG, `${task.id} _exec() DONE`); // taskContainer.meta.obs.complete(); } catch (initialError) { try { await this._onTaskExecError(taskContainer, initialError); } catch (err) { const typedError = err; taskContainer.meta.error = typedError; const isDelayed = this._isDelayError(typedError); const newState = isDelayed ? 'delayed' : 'done'; debug(TAG, taskContainer.task.id, '_onTaskError newState: ', newState); taskContainer.meta.state = newState; taskContainer.events.next({ type: 'ERROR_TASK', error: typedError, delayed: isDelayed, task: taskContainer.task, }); throw err; } } } async _onTaskExecError(taskContainer, err) { return await this.taskErrorResolutionService.onTaskError(taskContainer, err); } async _cancel(taskContainer) { try { debug(TAG, 'cancel task: ', taskContainer.task.id); const task = taskContainer.task; if (task.cancel) { await task.cancel(); this._emit({ type: 'CANCEL_TASK', task: task, }); } taskContainer.meta.state = 'pending'; } catch (err) { this._onError(err); } } _emit(event, emitters = []) { this._events.next(event); emitters.forEach((emitter) => { emitter.next(event); }); } _onError(err) { console.warn('Error task', err); // TODO } _isDelayError(err) { debug(TAG, '_isDelayError', err); if (isTapUserNotAuthorizedError(err)) { return true; } return (isCodeError(TapClientError.Code.NotConnectedError, err) || isCodeError('NfcTagLostError', err) || isCodeError('NfcNotConnectedError', err)); } /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TaskManagerService, deps: [{ token: TASK_MANAGER_RESOLUTION_SERVICE }], target: i0.ɵɵFactoryTarget.Injectable }); /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TaskManagerService }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TaskManagerService, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Inject, args: [TASK_MANAGER_RESOLUTION_SERVICE] }] }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFzay1tYW5hZ2VyLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9pb3RpemUtaW9uaWMvc3JjL2xpYi90YXNrLW1hbmFnZXIvdGFzay1tYW5hZ2VyLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbkQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBYyxVQUFVLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDbkUsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3ZDLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQy9ELE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFbEMsT0FBTyxFQUVMLCtCQUErQixHQUNoQyxNQUFNLFlBQVksQ0FBQzs7QUFFcEIsTUFBTSxHQUFHLEdBQUcsYUFBYSxDQUFDO0FBTzFCLE1BQU0sVUFBVSxHQUFHLHNDQUFzQyxDQUFDO0FBRTFELE1BQU0sVUFBVSxRQUFRO0lBQ3RCLElBQUksTUFBTSxHQUFHLEVBQUUsQ0FBQztJQUNoQixNQUFNLGdCQUFnQixHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUM7SUFDM0MsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQzVCLE1BQU0sSUFBSSxVQUFVLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLGdCQUFnQixDQUFDLENBQUMsQ0FBQztJQUM1RSxD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M0IsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN0QixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxRQUFRLENBQUMsR0FBVTtRQUN6QixPQUFPLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNoQyxPQUFPO0lBQ1QsQ0FBQztJQUVPLGFBQWEsQ0FBQyxHQUFVO1FBQzlCLEtBQUssQ0FBQyxHQUFHLEVBQUUsZUFBZSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ2pDLElBQUksMkJBQTJCLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNyQyxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFDRCxPQUFPLENBQ0wsV0FBVyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsR0FBRyxDQUFDO1lBQ3ZELFdBQVcsQ0FBQyxpQkFBaUIsRUFBRSxHQUFHLENBQUM7WUFDbkMsV0FBVyxDQUFDLHNCQUFzQixFQUFFLEdBQUcsQ0FBQyxDQUN6QyxDQUFDO0lBQ0osQ0FBQzsySEF6V1Usa0JBQWtCLGtCQWNuQiwrQkFBK0I7K0hBZDlCLGtCQUFrQjs7NEZBQWxCLGtCQUFrQjtrQkFEOUIsVUFBVTs7MEJBZU4sTUFBTTsyQkFBQywrQkFBK0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3QsIEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGlzQ29kZUVycm9yIH0gZnJvbSAnQGlvdGl6ZS9jb21tb24vZXJyb3InO1xuaW1wb3J0IHsgVGFwQ2xpZW50RXJyb3IgfSBmcm9tICdAaW90aXplL3RhcC9jbGllbnQvaW1wbCc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBTdWJqZWN0LCBTdWJzY3JpYmVyLCB0aHJvd0Vycm9yIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBzaGFyZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IGlzVGFwVXNlck5vdEF1dGhvcml6ZWRFcnJvciB9IGZyb20gJy4uL2Vycm9yLXV0aWxpdHknO1xuaW1wb3J0IHsgZGVidWcgfSBmcm9tICcuLi9sb2dnZXInO1xuaW1wb3J0IHsgVGFza01hbmFnZXIgfSBmcm9tICcuL2RlZmluaXRpb25zJztcbmltcG9ydCB7XG4gIFRhc2tFcnJvclJlc29sdXRpb25TZXJ2aWNlSW50ZXJmYWNlLFxuICBUQVNLX01BTkFHRVJfUkVTT0xVVElPTl9TRVJWSUNFLFxufSBmcm9tICcuL3Byb3ZpZGVyJztcblxuY29uc3QgVEFHID0gJ1Rhc2tNYW5hZ2VyJztcblxudHlwZSBUYXNrQ29udGFpbmVyPFRhc2tDb250ZXh0LCBUYXNrUmVzdWx0PiA9IFRhc2tNYW5hZ2VyLlRhc2tDb250YWluZXI8XG4gIFRhc2tDb250ZXh0LFxuICBUYXNrUmVzdWx0XG4+O1xuXG5jb25zdCBjaGFyYWN0ZXJzID0gJ2FiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSc7XG5cbmV4cG9ydCBmdW5jdGlvbiByYW5kb21JZCgpIHtcbiAgbGV0IHJlc3VsdCA9ICcnO1xuICBjb25zdCBjaGFyYWN0ZXJzTGVuZ3RoID0gY2hhcmFjdGVycy5sZW5ndGg7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgMjA7IGkrKykge1xuICAgIHJlc3VsdCArPSBjaGFyYWN0ZXJzLmNoYXJBdChNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBjaGFyYWN0ZXJzTGVuZ3RoKSk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFRhc2tNYW5hZ2VyU2VydmljZSB7XG4gIHByaXZhdGUgX3Rhc2tzOiBUYXNrQ29udGFpbmVyPHVua25vd24sIHVua25vd24+W107XG5cbiAgcHJpdmF0ZSBfZXZlbnRzOiBTdWJqZWN0PFRhc2tNYW5hZ2VyLkV2ZW50PHVua25vd24+PjtcblxuICBwdWJsaWMgZ2V0IGV2ZW50cygpIHtcbiAgICByZXR1cm4gdGhpcy5fZXZlbnRzLmFzT2JzZXJ2YWJsZSgpO1xuICB9XG5cbiAgcHVibGljIGdldCB0YXNrcygpOiBUYXNrTWFuYWdlci5UYXNrPHVua25vd24+W10ge1xuICAgIHJldHVybiB0aGlzLl90YXNrcy5tYXAoKGNvbnRhaW5lcikgPT4gY29udGFpbmVyLnRhc2spO1xuICB9XG5cbiAgY29uc3RydWN0b3IoXG4gICAgQEluamVjdChUQVNLX01BTkFHRVJfUkVTT0xVVElPTl9TRVJWSUNFKVxuICAgIHByaXZhdGUgdGFza0Vycm9yUmVzb2x1dGlvblNlcnZpY2U6IFRhc2tFcnJvclJlc29sdXRpb25TZXJ2aWNlSW50ZXJmYWNlXG4gICkge1xuICAgIGRlYnVnKFRBRywgJ25ldyBpbnN0YW5jZSEnKTtcbiAgICB0aGlzLl90YXNrcyA9IFtdO1xuICAgIHRoaXMuX2V2ZW50cyA9IG5ldyBTdWJqZWN0KCk7XG4gIH1cblxuICBjcmVhdGVUYXNrPFRhc2tDb250ZXh0LCBUYXNrUmVzdWx0ID0gdW5rbm93bj4oXG4gICAgdGFzazogVGFza01hbmFnZXIuVGFzazxUYXNrQ29udGV4dCwgVGFza1Jlc3VsdD4sXG4gICAgb3B0aW9uczoge1xuICAgICAgcG9zaXRpb24/OiBudW1iZXI7XG4gICAgfSA9IHt9XG4gICk6IFRhc2tNYW5hZ2VyLlRhc2tDb250YWluZXI8VGFza0NvbnRleHQsIFRhc2tSZXN1bHQ+IHtcbiAgICBpZiAodGhpcy5oYXNUYXNrKHRhc2suaWQpKSB7XG4gICAgICB0aGlzLmNsZWFyVGFzayh0YXNrLmlkKTtcbiAgICB9XG4gICAgY29uc3QgdGFza0NvbnRhaW5lcjogVGFza0NvbnRhaW5lcjxUYXNrQ29udGV4dCwgVGFza1Jlc3VsdD4gPSB7XG4gICAgICB0YXNrOiB0YXNrLFxuICAgICAgbWV0YToge1xuICAgICAgICBzdGF0ZTogJ3BlbmRpbmcnLFxuICAgICAgfSxcbiAgICAgIGV2ZW50czogbmV3IFN1YmplY3Q8VGFza01hbmFnZXIuRXZlbnQ8VGFza0NvbnRleHQsIFRhc2tSZXN1bHQ+PigpLFxuICAgIH07XG4gICAgbGV0IHBvc2l0aW9uOiBudW1iZXI7XG4gICAgaWYgKG9wdGlvbnMucG9zaXRpb24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5fdGFza3Nbb3B0aW9ucy5wb3NpdGlvbl0gPSB0YXNrQ29udGFpbmVyIGFzIFRhc2tDb250YWluZXI8XG4gICAgICAgIHVua25vd24sXG4gICAgICAgIHVua25vd25cbiAgICAgID47XG4gICAgICBwb3NpdGlvbiA9IG9wdGlvbnMucG9zaXRpb247XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IG5ld0xlbmd0aCA9IHRoaXMuX3Rhc2tzLnB1c2goXG4gICAgICAgIHRhc2tDb250YWluZXIgYXMgVGFza0NvbnRhaW5lcjx1bmtub3duLCB1bmtub3duPlxuICAgICAgKTtcbiAgICAgIHBvc2l0aW9uID0gbmV3TGVuZ3RoIC0gMTtcbiAgICB9XG4gICAgZGVidWcoVEFHLCAnY3JlYXRlVGFzaycsIHRhc2suaWQsICdwb3NpdGlvbicsIHBvc2l0aW9uKTtcbiAgICByZXR1cm4gdGFza0NvbnRhaW5lcjtcbiAgfVxuXG4gIHJlbW92ZVRhc2soaWQ6IHN0cmluZykge1xuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5nZXRUYXNrUG9zaXRpb24oaWQpO1xuICAgIGlmIChpbmRleCA+PSAwKSB7XG4gICAgICBjb25zdCBbdGFza10gPSB0aGlzLl90YXNrcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgdGhpcy5fY2FuY2VsKHRhc2spO1xuICAgICAgZGVidWcoVEFHLCAncmVtb3ZlZCB0YXNrJywgdGFzay50YXNrLmlkLCAncG9zaXRpb24nLCBpbmRleCk7XG4gICAgfVxuICB9XG5cbiAgaGFzVGFzayhpZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0VGFza1Bvc2l0aW9uKGlkKSAhPT0gLTE7XG4gIH1cblxuICB0YXNrPFRhc2tDb250ZXh0PihpZDogc3RyaW5nKTogVGFza01hbmFnZXIuVGFzazxUYXNrQ29udGV4dD4gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGNvbnRhaW5lciA9IHRoaXMuY29udGFpbmVyKGlkKTtcbiAgICBpZiAoY29udGFpbmVyKSB7XG4gICAgICByZXR1cm4gY29udGFpbmVyLnRhc2s7XG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb250YWluZXI8VGFza0NvbnRleHQsIFRhc2tSZXN1bHQgPSB1bmtub3duPihcbiAgICBpZDogc3RyaW5nXG4gICk6IFRhc2tDb250YWluZXI8VGFza0NvbnRleHQsIFRhc2tSZXN1bHQ+IHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBpbmRleCA9IHRoaXMuZ2V0VGFza1Bvc2l0aW9uKGlkKTtcbiAgICBpZiAoaW5kZXggPj0gMCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3Rhc2tzW2luZGV4XSBhcyBUYXNrQ29udGFpbmVyPFRhc2tDb250ZXh0LCBUYXNrUmVzdWx0PjtcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGNhbmNlbChpZDogc3RyaW5nKSB7XG4gICAgY29uc3QgaW5kZXggPSB0aGlzLmdldFRhc2tQb3NpdGlvbihpZCk7XG4gICAgaWYgKGluZGV4ID49IDApIHtcbiAgICAgIHRoaXMuX2NhbmNlbCh0aGlzLl90YXNrc1tpbmRleF0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBkZWJ1ZyhUQUcsICd0YXNrICcsIGlkLCAnZG9lcyBub3QgZXhpc3QuIENhbm5vdCBjYW5jZWwnKTtcbiAgICB9XG4gIH1cblxuICB0YXNrTWV0YShpZDogc3RyaW5nKSB7XG4gICAgY29uc3QgY29udGFpbmVyID0gdGhpcy5jb250YWluZXIoaWQpO1xuICAgIGlmIChjb250YWluZXIpIHtcbiAgICAgIHJldHVybiBjb250YWluZXIubWV0YTtcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGFkZFRhc2tDb250YWluZXI8VGFza0NvbnRleHQ+KFxuICAgIGNvbnRhaW5lcjogVGFza01hbmFnZXIuVGFza0NvbnRhaW5lcjxUYXNrQ29udGV4dD5cbiAgKSB7XG4gICAgdGhpcy5fdGFza3MucHVzaChjb250YWluZXIpO1xuICB9XG5cbiAgYWRkVGFzayQ8VGFza0NvbnRleHQ+KFxuICAgIHRhc2s6IFRhc2tNYW5hZ2VyLlRhc2s8VGFza0NvbnRleHQ+LFxuICAgIG9wdGlvbnM6IHtcbiAgICAgIHBvc2l0aW9uPzogbnVtYmVyO1xuICAgIH0gPSB7fVxuICApOiBPYnNlcnZhYmxlPFRhc2tNYW5hZ2VyLkV2ZW50PFRhc2tDb250ZXh0Pj4ge1xuICAgIGNvbnN0IHRhc2tDb250YWluZXIgPSB0aGlzLmNyZWF0ZVRhc2sodGFzaywgb3B0aW9ucyk7XG4gICAgcmV0dXJuIHRhc2tDb250YWluZXIuZXZlbnRzO1xuICB9XG5cbiAgY2xlYXJUYXNrKGlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCB0YXNrSW5kZXggPSB0aGlzLmdldFRhc2tQb3NpdGlvbihpZCk7XG4gICAgaWYgKHRhc2tJbmRleCAhPT0gLTEpIHtcbiAgICAgIGNvbnN0IHJlbW92ZWQgPSB0aGlzLl90YXNrcy5zcGxpY2UodGFza0luZGV4LCAxKTtcbiAgICAgIGlmIChyZW1vdmVkLmxlbmd0aCAhPT0gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYEludGVybmFsIGVycm9yOiBjbGVhciB0YXNrIHJlbW92ZWQgJHtyZW1vdmVkLmxlbmd0aH0gdGFzayhzKS4gQ2xlYXIgdGFzayBtdXN0IHJlbW92ZWQgZXhhY3RseSAxIHRhc2suIEl0J3MgcHJvYmFibHkgYSBidWcuYFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgZGVidWcoVEFHLCBgJHtyZW1vdmVkWzBdLnRhc2suaWR9OiBjbGVhcmVkYCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRlYnVnKFRBRywgYCR7aWR9OiBkb2VzIG5vdCBleGlzdCwgY2Fubm90IHJlbW92ZWApO1xuICAgIH1cbiAgfVxuXG4gIGNhbmNlbEFsbCgpIHtcbiAgICB0aGlzLl90YXNrcy5mb3JFYWNoKCh0YXNrKSA9PiB7XG4gICAgICB0aGlzLl9jYW5jZWwodGFzayk7XG4gICAgfSk7XG4gIH1cblxuICBjbGVhckFsbCgpIHtcbiAgICB0aGlzLl90YXNrcyA9IFtdO1xuICB9XG5cbiAgZXhlYzxUYXNrQ29udGV4dD4oXG4gICAgdGFza0lkOiBzdHJpbmcsXG4gICAgY29udGV4dDogVGFza0NvbnRleHRcbiAgKTogT2JzZXJ2YWJsZTxUYXNrTWFuYWdlci5FdmVudDxUYXNrQ29udGV4dD4+IHtcbiAgICBjb25zdCBjb250YWluZXIgPSB0aGlzLmNvbnRhaW5lcih0YXNrSWQpO1xuICAgIGlmICghY29udGFpbmVyKSB7XG4gICAgICByZXR1cm4gdGhyb3dFcnJvcihuZXcgRXJyb3IoYFRhc2sgd2l0aCBpZCBcIiR7dGFza0lkfVwiIGRvZXMgbm90IGV4aXN0YCkpO1xuICAgIH1cbiAgICBjb250YWluZXIubWV0YS5jb250ZXh0ID0gY29udGV4dDtcbiAgICByZXR1cm4gdGhpcy5leGVjQXNPYnNlcnZhYmxlKGNvbnRhaW5lcik7XG4gIH1cblxuICBwcml2YXRlIGV4ZWNBc09ic2VydmFibGU8VGFza0NvbnRleHQsIFRhc2tSZXN1bHQ+KFxuICAgIHRhc2s6IFRhc2tDb250YWluZXI8VGFza0NvbnRleHQsIFRhc2tSZXN1bHQ+XG4gICkge1xuICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZTxUYXNrTWFuYWdlci5FdmVudDxUYXNrQ29udGV4dCwgVGFza1Jlc3VsdD4+KFxuICAgICAgKGVtaXR0ZXIpID0+IHtcbiAgICAgICAgKGFzeW5jICgpID0+IHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5fZXhlYyh0YXNrLCBlbWl0dGVyKTtcbiAgICAgICAgICAgIGVtaXR0ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGVtaXR0ZXIuZXJyb3IoZXJyKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pKCk7XG4gICAgICB9XG4gICAgKS5waXBlKHNoYXJlKCkpO1xuICB9XG5cbiAgYXN5bmMgcmV0cnk8VGFza0NvbnRleHQsIFRhc2tSZXN1bHQ+KFxuICAgIGNvbnRhaW5lcjogVGFza01hbmFnZXIuVGFza0NvbnRhaW5lcjxUYXNrQ29udGV4dCwgVGFza1Jlc3VsdD5cbiAgKTogUHJvbWlzZTxUYXNrUmVzdWx0PiB7XG4gICAgcmV0dXJuIChcbiAgICAgIChhd2FpdCB0aGlzLmV4ZWNBc09ic2VydmFibGUoXG4gICAgICAgIGNvbnRhaW5lclxuICAgICAgKS50b1Byb21pc2UoKSkgYXMgVGFza01hbmFnZXIuQWZ0ZXJUYXNrRXZlbnQ8VGFza0NvbnRleHQsIFRhc2tSZXN1bHQ+XG4gICAgKS5yZXN1bHQ7XG4gIH1cblxuICBleGVjTmV4dCgpIHtcbiAgICByZXR1cm4gbmV3IE9ic2VydmFibGU8VGFza01hbmFnZXIuRXZlbnQ8dW5rbm93bj4+KChlbWl0dGVyKSA9PiB7XG4gICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGlmICh0aGlzLl90YXNrcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLl9leGVjKHRoaXMuX3Rhc2tzWzBdLCBlbWl0dGVyKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZW1pdHRlci5jb21wbGV0ZSgpO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBlbWl0dGVyLmVycm9yKGVycik7XG4gICAgICAgIH1cbiAgICAgIH0pKCk7XG4gICAgfSkucGlwZShzaGFyZSgpKTtcbiAgfVxuXG4gIGV4ZWNEZWxheWVkVGFza3MoKSB7XG4gICAgcmV0dXJuIHRoaXMuZXhlY1Rhc2tzQnlTdGF0ZSgnZGVsYXllZCcpO1xuICB9XG5cbiAgZXhlY1BlbmRpbmdUYXNrcygpOiBPYnNlcnZhYmxlPFRhc2tNYW5hZ2VyLkV2ZW50PHVua25vd24+PiB7XG4gICAgcmV0dXJuIHRoaXMuZXhlY1Rhc2tzQnlTdGF0ZSgncGVuZGluZycpO1xuICB9XG5cbiAgZXhlY1Rhc2tzQnlTdGF0ZShcbiAgICBzdGF0ZTogVGFza01hbmFnZXIuVGFza1N0YXRlXG4gICk6IE9ic2VydmFibGU8VGFza01hbmFnZXIuRXZlbnQ8dW5rbm93bj4+IHtcbiAgICBjb25zdCBvYnMgPSBuZXcgT2JzZXJ2YWJsZShcbiAgICAgIChlbWl0dGVyOiBTdWJzY3JpYmVyPFRhc2tNYW5hZ2VyLkV2ZW50PHVua25vd24+PikgPT4ge1xuICAgICAgICBsZXQgc3RvcCA9IGZhbHNlO1xuICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBwZW5kaW5nVGFza3MgPSB0aGlzLl90YXNrcy5maWx0ZXIoXG4gICAgICAgICAgICAgIChjb250YWluZXIpID0+IGNvbnRhaW5lci5tZXRhLnN0YXRlID09PSBzdGF0ZVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGRlYnVnKFxuICAgICAgICAgICAgICBUQUcsXG4gICAgICAgICAgICAgIGBleGVjQWxsKCkgd2l0aCAke1xuICAgICAgICAgICAgICAgIHBlbmRpbmdUYXNrcy5sZW5ndGhcbiAgICAgICAgICAgICAgfSB0YXNrKHMpIChzdGF0ZSA9PSAke3N0YXRlfSk6ICR7cGVuZGluZ1Rhc2tzXG4gICAgICAgICAgICAgICAgLm1hcCgodGFzaykgPT4gdGFzay50YXNrLmlkKVxuICAgICAgICAgICAgICAgIC5qb2luKCcsICcpfWBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHBlbmRpbmdUYXNrIG9mIHBlbmRpbmdUYXNrcykge1xuICAgICAgICAgICAgICBpZiAoIXN0b3ApIHtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLl9leGVjKHBlbmRpbmdUYXNrLCBlbWl0dGVyKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVidWcoVEFHLCAnZXhlY0FsbCgpIENPTVBMRVRFRCcpO1xuICAgICAgICAgICAgZW1pdHRlci5jb21wbGV0ZSgpO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgZGVidWcoVEFHLCAnZXhlY0FsbCgpIEVSUk9SJyk7XG4gICAgICAgICAgICBlbWl0dGVyLmVycm9yKGVycik7XG4gICAgICAgICAgfVxuICAgICAgICB9KSgpO1xuICAgICAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICAgIHN0b3AgPSB0cnVlO1xuICAgICAgICAgIC8vIE5vdGhpbmcgdG8gZG8gd2hlbiB1bnN1YnNjcmliaW5nXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgKTtcbiAgICByZXR1cm4gb2JzLnBpcGUoc2hhcmUoKSk7XG4gIH1cblxuICBnZXRUYXNrUG9zaXRpb24oaWQ6IHN0cmluZyk6IG51bWJlciB7XG4gICAgLy8gUmV2ZXJzZWQgZm9yIExJRk8gbWFuYWdlbWVudCBvZiB0YXNrcyB3aXRoIHRoZSBzYW1lIGlkLlxuICAgIC8vIFRPIFZBTElEQVRFXG4gICAgcmV0dXJuIHRoaXMuX3Rhc2tzXG4gICAgICAucmV2ZXJzZSgpXG4gICAgICAuZmluZEluZGV4KChjb250YWluZXIpID0+IGNvbnRhaW5lci50YXNrLmlkID09PSBpZCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIF9leGVjPFRhc2tDb250ZXh0LCBUYXNrUmVzdWx0PihcbiAgICB0YXNrQ29udGFpbmVyOiBUYXNrQ29udGFpbmVyPFRhc2tDb250ZXh0LCBUYXNrUmVzdWx0PixcbiAgICBlbWl0dGVyOiBTdWJzY3JpYmVyPFRhc2tNYW5hZ2VyLkV2ZW50PFRhc2tDb250ZXh0LCBUYXNrUmVzdWx0Pj5cbiAgKSB7XG4gICAgY29uc3QgdGFzayA9IHRhc2tDb250YWluZXIudGFzaztcbiAgICB0cnkge1xuICAgICAgZGVidWcoVEFHLCBgJHt0YXNrLmlkfSBfZXhlYygpIHN0YXJ0aW5nYCk7XG4gICAgICB0YXNrQ29udGFpbmVyLm1ldGEuc3RhdGUgPSAncnVubmluZyc7XG4gICAgICB0aGlzLl9lbWl0KFxuICAgICAgICB7XG4gICAgICAgICAgdHlwZTogJ0JFRk9SRV9UQVNLJyxcbiAgICAgICAgICB0YXNrOiB0YXNrLFxuICAgICAgICB9LFxuICAgICAgICBbZW1pdHRlciwgdGFza0NvbnRhaW5lci5ldmVudHNdXG4gICAgICApO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGFzay5leGVjKHRhc2tDb250YWluZXIubWV0YS5jb250ZXh0KTtcbiAgICAgIC8vIHRoaXMuY2xlYXJUYXNrKHRhc2suaWQpO1xuICAgICAgdGhpcy5fZW1pdChcbiAgICAgICAge1xuICAgICAgICAgIHR5cGU6ICdBRlRFUl9UQVNLJyxcbiAgICAgICAgICB0YXNrOiB0YXNrLFxuICAgICAgICAgIHJlc3VsdDogcmVzdWx0LFxuICAgICAgICB9LFxuICAgICAgICBbZW1pdHRlciwgdGFza0NvbnRhaW5lci5ldmVudHNdXG4gICAgICApO1xuICAgICAgdGFza0NvbnRhaW5lci5tZXRhLnJlc3VsdCA9IHJlc3VsdDtcbiAgICAgIHRhc2tDb250YWluZXIubWV0YS5zdGF0ZSA9ICdkb25lJztcbiAgICAgIGRlYnVnKFRBRywgYCR7dGFzay5pZH0gX2V4ZWMoKSBET05FYCk7XG4gICAgICAvLyB0YXNrQ29udGFpbmVyLm1ldGEub2JzLmNvbXBsZXRlKCk7XG4gICAgfSBjYXRjaCAoaW5pdGlhbEVycm9yOiBhbnkpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHRoaXMuX29uVGFza0V4ZWNFcnJvcih0YXNrQ29udGFpbmVyLCBpbml0aWFsRXJyb3IpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGNvbnN0IHR5cGVkRXJyb3IgPSBlcnIgYXMgRXJyb3I7XG4gICAgICAgIHRhc2tDb250YWluZXIubWV0YS5lcnJvciA9IHR5cGVkRXJyb3I7XG4gICAgICAgIGNvbnN0IGlzRGVsYXllZCA9IHRoaXMuX2lzRGVsYXlFcnJvcih0eXBlZEVycm9yKTtcbiAgICAgICAgY29uc3QgbmV3U3RhdGU6IFRhc2tNYW5hZ2VyLlRhc2tTdGF0ZSA9IGlzRGVsYXllZCA/ICdkZWxheWVkJyA6ICdkb25lJztcbiAgICAgICAgZGVidWcoVEFHLCB0YXNrQ29udGFpbmVyLnRhc2suaWQsICdfb25UYXNrRXJyb3IgbmV3U3RhdGU6ICcsIG5ld1N0YXRlKTtcbiAgICAgICAgdGFza0NvbnRhaW5lci5tZXRhLnN0YXRlID0gbmV3U3RhdGU7XG4gICAgICAgIHRhc2tDb250YWluZXIuZXZlbnRzLm5leHQoe1xuICAgICAgICAgIHR5cGU6ICdFUlJPUl9UQVNLJyxcbiAgICAgICAgICBlcnJvcjogdHlwZWRFcnJvcixcbiAgICAgICAgICBkZWxheWVkOiBpc0RlbGF5ZWQsXG4gICAgICAgICAgdGFzazogdGFza0NvbnRhaW5lci50YXNrLFxuICAgICAgICB9KTtcbiAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgX29uVGFza0V4ZWNFcnJvcjxUYXNrQ29udGV4dCwgVGFza1Jlc3VsdD4oXG4gICAgdGFza0NvbnRhaW5lcjogVGFza0NvbnRhaW5lcjxUYXNrQ29udGV4dCwgVGFza1Jlc3VsdD4sXG4gICAgZXJyOiBFcnJvclxuICApIHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy50YXNrRXJyb3JSZXNvbHV0aW9uU2VydmljZS5vblRhc2tFcnJvcihcbiAgICAgIHRhc2tDb250YWluZXIsXG4gICAgICBlcnJcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBfY2FuY2VsPFRhc2tDb250ZXh0LCBUYXNrUmVzdWx0PihcbiAgICB0YXNrQ29udGFpbmVyOiBUYXNrQ29udGFpbmVyPFRhc2tDb250ZXh0LCBUYXNrUmVzdWx0PlxuICApIHtcbiAgICB0cnkge1xuICAgICAgZGVidWcoVEFHLCAnY2FuY2VsIHRhc2s6ICcsIHRhc2tDb250YWluZXIudGFzay5pZCk7XG4gICAgICBjb25zdCB0YXNrID0gdGFza0NvbnRhaW5lci50YXNrO1xuICAgICAgaWYgKHRhc2suY2FuY2VsKSB7XG4gICAgICAgIGF3YWl0IHRhc2suY2FuY2VsKCk7XG4gICAgICAgIHRoaXMuX2VtaXQoe1xuICAgICAgICAgIHR5cGU6ICdDQU5DRUxfVEFTSycsXG4gICAgICAgICAgdGFzazogdGFzayxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICB0YXNrQ29udGFpbmVyLm1ldGEuc3RhdGUgPSAncGVuZGluZyc7XG4gICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgIHRoaXMuX29uRXJyb3IoZXJyKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9lbWl0PFRhc2tDb250ZXh0LCBUYXNrUmVzdWx0ID0gdW5rbm93bj4oXG4gICAgZXZlbnQ6IFRhc2tNYW5hZ2VyLkV2ZW50PFRhc2tDb250ZXh0LCBUYXNrUmVzdWx0PixcbiAgICBlbWl0dGVyczogKFxuICAgICAgfCBTdWJzY3JpYmVyPFRhc2tNYW5hZ2VyLkV2ZW50PFRhc2tDb250ZXh0LCBUYXNrUmVzdWx0Pj5cbiAgICAgIHwgU3ViamVjdDxUYXNrTWFuYWdlci5FdmVudDxUYXNrQ29udGV4dCwgVGFza1Jlc3VsdD4+XG4gICAgKVtdID0gW11cbiAgKSB7XG4gICAgdGhpcy5fZXZlbnRzLm5leHQoZXZlbnQpO1xuICAgIGVtaXR0ZXJzLmZvckVhY2goKGVtaXR0ZXIpID0+IHtcbiAgICAgIGVtaXR0ZXIubmV4dChldmVudCk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9vbkVycm9yKGVycjogRXJyb3IpIHtcbiAgICBjb25zb2xlLndhcm4oJ0Vycm9yIHRhc2snLCBlcnIpO1xuICAgIC8vIFRPRE9cbiAgfVxuXG4gIHByaXZhdGUgX2lzRGVsYXlFcnJvcihlcnI6IEVycm9yKSB7XG4gICAgZGVidWcoVEFHLCAnX2lzRGVsYXlFcnJvcicsIGVycik7XG4gICAgaWYgKGlzVGFwVXNlck5vdEF1dGhvcml6ZWRFcnJvcihlcnIpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIChcbiAgICAgIGlzQ29kZUVycm9yKFRhcENsaWVudEVycm9yLkNvZGUuTm90Q29ubmVjdGVkRXJyb3IsIGVycikgfHxcbiAgICAgIGlzQ29kZUVycm9yKCdOZmNUYWdMb3N0RXJyb3InLCBlcnIpIHx8XG4gICAgICBpc0NvZGVFcnJvcignTmZjTm90Q29ubmVjdGVkRXJyb3InLCBlcnIpXG4gICAgKTtcbiAgfVxufVxuIl19