@iotize/ionic
Version:
Iotize specific building blocks on top of @ionic/angular.
296 lines • 38 kB
JavaScript
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 {
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 */ TaskManagerService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TaskManagerService, deps: [{ token: TASK_MANAGER_RESOLUTION_SERVICE }], target: i0.ɵɵFactoryTarget.Injectable });
/** @nocollapse */ TaskManagerService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TaskManagerService });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TaskManagerService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Inject,
args: [TASK_MANAGER_RESOLUTION_SERVICE]
}] }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFzay1tYW5hZ2VyLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9pb3RpemUtaW9uaWMvc3JjL2xpYi90YXNrLW1hbmFnZXIvdGFzay1tYW5hZ2VyLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbkQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBYyxVQUFVLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDbkUsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3ZDLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQy9ELE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFbEMsT0FBTyxFQUVMLCtCQUErQixHQUNoQyxNQUFNLFlBQVksQ0FBQzs7QUFFcEIsTUFBTSxHQUFHLEdBQUcsYUFBYSxDQUFDO0FBTzFCLE1BQU0sVUFBVSxHQUFHLHNDQUFzQyxDQUFDO0FBRTFELE1BQU0sVUFBVSxRQUFRO0lBQ3RCLElBQUksTUFBTSxHQUFHLEVBQUUsQ0FBQztJQUNoQixNQUFNLGdCQUFnQixHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUM7SUFDM0MsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRTtRQUMzQixNQUFNLElBQUksVUFBVSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUM7S0FDM0U7SUFDRCxP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LGlCQUFpQixFQUFFLEdBQUcsQ0FBQztZQUN2RCxXQUFXLENBQUMsaUJBQWlCLEVBQUUsR0FBRyxDQUFDO1lBQ25DLFdBQVcsQ0FBQyxzQkFBc0IsRUFBRSxHQUFHLENBQUMsQ0FDekMsQ0FBQztJQUNKLENBQUM7O21JQXpXVSxrQkFBa0Isa0JBY25CLCtCQUErQjt1SUFkOUIsa0JBQWtCOzRGQUFsQixrQkFBa0I7a0JBRDlCLFVBQVU7OzBCQWVOLE1BQU07MkJBQUMsK0JBQStCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0LCBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBpc0NvZGVFcnJvciB9IGZyb20gJ0Bpb3RpemUvY29tbW9uL2Vycm9yJztcbmltcG9ydCB7IFRhcENsaWVudEVycm9yIH0gZnJvbSAnQGlvdGl6ZS90YXAvY2xpZW50L2ltcGwnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgU3ViamVjdCwgU3Vic2NyaWJlciwgdGhyb3dFcnJvciB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgc2hhcmUgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBpc1RhcFVzZXJOb3RBdXRob3JpemVkRXJyb3IgfSBmcm9tICcuLi9lcnJvci11dGlsaXR5JztcbmltcG9ydCB7IGRlYnVnIH0gZnJvbSAnLi4vbG9nZ2VyJztcbmltcG9ydCB7IFRhc2tNYW5hZ2VyIH0gZnJvbSAnLi9kZWZpbml0aW9ucyc7XG5pbXBvcnQge1xuICBUYXNrRXJyb3JSZXNvbHV0aW9uU2VydmljZUludGVyZmFjZSxcbiAgVEFTS19NQU5BR0VSX1JFU09MVVRJT05fU0VSVklDRSxcbn0gZnJvbSAnLi9wcm92aWRlcic7XG5cbmNvbnN0IFRBRyA9ICdUYXNrTWFuYWdlcic7XG5cbnR5cGUgVGFza0NvbnRhaW5lcjxUYXNrQ29udGV4dCwgVGFza1Jlc3VsdD4gPSBUYXNrTWFuYWdlci5UYXNrQ29udGFpbmVyPFxuICBUYXNrQ29udGV4dCxcbiAgVGFza1Jlc3VsdFxuPjtcblxuY29uc3QgY2hhcmFjdGVycyA9ICdhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODknO1xuXG5leHBvcnQgZnVuY3Rpb24gcmFuZG9tSWQoKSB7XG4gIGxldCByZXN1bHQgPSAnJztcbiAgY29uc3QgY2hhcmFjdGVyc0xlbmd0aCA9IGNoYXJhY3RlcnMubGVuZ3RoO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IDIwOyBpKyspIHtcbiAgICByZXN1bHQgKz0gY2hhcmFjdGVycy5jaGFyQXQoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogY2hhcmFjdGVyc0xlbmd0aCkpO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBUYXNrTWFuYWdlclNlcnZpY2Uge1xuICBwcml2YXRlIF90YXNrczogVGFza0NvbnRhaW5lcjx1bmtub3duLCB1bmtub3duPltdO1xuXG4gIHByaXZhdGUgX2V2ZW50czogU3ViamVjdDxUYXNrTWFuYWdlci5FdmVudDx1bmtub3duPj47XG5cbiAgcHVibGljIGdldCBldmVudHMoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2V2ZW50cy5hc09ic2VydmFibGUoKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgdGFza3MoKTogVGFza01hbmFnZXIuVGFzazx1bmtub3duPltdIHtcbiAgICByZXR1cm4gdGhpcy5fdGFza3MubWFwKChjb250YWluZXIpID0+IGNvbnRhaW5lci50YXNrKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIEBJbmplY3QoVEFTS19NQU5BR0VSX1JFU09MVVRJT05fU0VSVklDRSlcbiAgICBwcml2YXRlIHRhc2tFcnJvclJlc29sdXRpb25TZXJ2aWNlOiBUYXNrRXJyb3JSZXNvbHV0aW9uU2VydmljZUludGVyZmFjZVxuICApIHtcbiAgICBkZWJ1ZyhUQUcsICduZXcgaW5zdGFuY2UhJyk7XG4gICAgdGhpcy5fdGFza3MgPSBbXTtcbiAgICB0aGlzLl9ldmVudHMgPSBuZXcgU3ViamVjdCgpO1xuICB9XG5cbiAgY3JlYXRlVGFzazxUYXNrQ29udGV4dCwgVGFza1Jlc3VsdCA9IHVua25vd24+KFxuICAgIHRhc2s6IFRhc2tNYW5hZ2VyLlRhc2s8VGFza0NvbnRleHQsIFRhc2tSZXN1bHQ+LFxuICAgIG9wdGlvbnM6IHtcbiAgICAgIHBvc2l0aW9uPzogbnVtYmVyO1xuICAgIH0gPSB7fVxuICApOiBUYXNrTWFuYWdlci5UYXNrQ29udGFpbmVyPFRhc2tDb250ZXh0LCBUYXNrUmVzdWx0PiB7XG4gICAgaWYgKHRoaXMuaGFzVGFzayh0YXNrLmlkKSkge1xuICAgICAgdGhpcy5jbGVhclRhc2sodGFzay5pZCk7XG4gICAgfVxuICAgIGNvbnN0IHRhc2tDb250YWluZXI6IFRhc2tDb250YWluZXI8VGFza0NvbnRleHQsIFRhc2tSZXN1bHQ+ID0ge1xuICAgICAgdGFzazogdGFzayxcbiAgICAgIG1ldGE6IHtcbiAgICAgICAgc3RhdGU6ICdwZW5kaW5nJyxcbiAgICAgIH0sXG4gICAgICBldmVudHM6IG5ldyBTdWJqZWN0PFRhc2tNYW5hZ2VyLkV2ZW50PFRhc2tDb250ZXh0LCBUYXNrUmVzdWx0Pj4oKSxcbiAgICB9O1xuICAgIGxldCBwb3NpdGlvbjogbnVtYmVyO1xuICAgIGlmIChvcHRpb25zLnBvc2l0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuX3Rhc2tzW29wdGlvbnMucG9zaXRpb25dID0gdGFza0NvbnRhaW5lciBhcyBUYXNrQ29udGFpbmVyPFxuICAgICAgICB1bmtub3duLFxuICAgICAgICB1bmtub3duXG4gICAgICA+O1xuICAgICAgcG9zaXRpb24gPSBvcHRpb25zLnBvc2l0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBuZXdMZW5ndGggPSB0aGlzLl90YXNrcy5wdXNoKFxuICAgICAgICB0YXNrQ29udGFpbmVyIGFzIFRhc2tDb250YWluZXI8dW5rbm93biwgdW5rbm93bj5cbiAgICAgICk7XG4gICAgICBwb3NpdGlvbiA9IG5ld0xlbmd0aCAtIDE7XG4gICAgfVxuICAgIGRlYnVnKFRBRywgJ2NyZWF0ZVRhc2snLCB0YXNrLmlkLCAncG9zaXRpb24nLCBwb3NpdGlvbik7XG4gICAgcmV0dXJuIHRhc2tDb250YWluZXI7XG4gIH1cblxuICByZW1vdmVUYXNrKGlkOiBzdHJpbmcpIHtcbiAgICBjb25zdCBpbmRleCA9IHRoaXMuZ2V0VGFza1Bvc2l0aW9uKGlkKTtcbiAgICBpZiAoaW5kZXggPj0gMCkge1xuICAgICAgY29uc3QgW3Rhc2tdID0gdGhpcy5fdGFza3Muc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgIHRoaXMuX2NhbmNlbCh0YXNrKTtcbiAgICAgIGRlYnVnKFRBRywgJ3JlbW92ZWQgdGFzaycsIHRhc2sudGFzay5pZCwgJ3Bvc2l0aW9uJywgaW5kZXgpO1xuICAgIH1cbiAgfVxuXG4gIGhhc1Rhc2soaWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmdldFRhc2tQb3NpdGlvbihpZCkgIT09IC0xO1xuICB9XG5cbiAgdGFzazxUYXNrQ29udGV4dD4oaWQ6IHN0cmluZyk6IFRhc2tNYW5hZ2VyLlRhc2s8VGFza0NvbnRleHQ+IHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBjb250YWluZXIgPSB0aGlzLmNvbnRhaW5lcihpZCk7XG4gICAgaWYgKGNvbnRhaW5lcikge1xuICAgICAgcmV0dXJuIGNvbnRhaW5lci50YXNrO1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgY29udGFpbmVyPFRhc2tDb250ZXh0LCBUYXNrUmVzdWx0ID0gdW5rbm93bj4oXG4gICAgaWQ6IHN0cmluZ1xuICApOiBUYXNrQ29udGFpbmVyPFRhc2tDb250ZXh0LCBUYXNrUmVzdWx0PiB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgaW5kZXggPSB0aGlzLmdldFRhc2tQb3NpdGlvbihpZCk7XG4gICAgaWYgKGluZGV4ID49IDApIHtcbiAgICAgIHJldHVybiB0aGlzLl90YXNrc1tpbmRleF0gYXMgVGFza0NvbnRhaW5lcjxUYXNrQ29udGV4dCwgVGFza1Jlc3VsdD47XG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBjYW5jZWwoaWQ6IHN0cmluZykge1xuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5nZXRUYXNrUG9zaXRpb24oaWQpO1xuICAgIGlmIChpbmRleCA+PSAwKSB7XG4gICAgICB0aGlzLl9jYW5jZWwodGhpcy5fdGFza3NbaW5kZXhdKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGVidWcoVEFHLCAndGFzayAnLCBpZCwgJ2RvZXMgbm90IGV4aXN0LiBDYW5ub3QgY2FuY2VsJyk7XG4gICAgfVxuICB9XG5cbiAgdGFza01ldGEoaWQ6IHN0cmluZykge1xuICAgIGNvbnN0IGNvbnRhaW5lciA9IHRoaXMuY29udGFpbmVyKGlkKTtcbiAgICBpZiAoY29udGFpbmVyKSB7XG4gICAgICByZXR1cm4gY29udGFpbmVyLm1ldGE7XG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBhZGRUYXNrQ29udGFpbmVyPFRhc2tDb250ZXh0PihcbiAgICBjb250YWluZXI6IFRhc2tNYW5hZ2VyLlRhc2tDb250YWluZXI8VGFza0NvbnRleHQ+XG4gICkge1xuICAgIHRoaXMuX3Rhc2tzLnB1c2goY29udGFpbmVyKTtcbiAgfVxuXG4gIGFkZFRhc2skPFRhc2tDb250ZXh0PihcbiAgICB0YXNrOiBUYXNrTWFuYWdlci5UYXNrPFRhc2tDb250ZXh0PixcbiAgICBvcHRpb25zOiB7XG4gICAgICBwb3NpdGlvbj86IG51bWJlcjtcbiAgICB9ID0ge31cbiAgKTogT2JzZXJ2YWJsZTxUYXNrTWFuYWdlci5FdmVudDxUYXNrQ29udGV4dD4+IHtcbiAgICBjb25zdCB0YXNrQ29udGFpbmVyID0gdGhpcy5jcmVhdGVUYXNrKHRhc2ssIG9wdGlvbnMpO1xuICAgIHJldHVybiB0YXNrQ29udGFpbmVyLmV2ZW50cztcbiAgfVxuXG4gIGNsZWFyVGFzayhpZDogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgdGFza0luZGV4ID0gdGhpcy5nZXRUYXNrUG9zaXRpb24oaWQpO1xuICAgIGlmICh0YXNrSW5kZXggIT09IC0xKSB7XG4gICAgICBjb25zdCByZW1vdmVkID0gdGhpcy5fdGFza3Muc3BsaWNlKHRhc2tJbmRleCwgMSk7XG4gICAgICBpZiAocmVtb3ZlZC5sZW5ndGggIT09IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBJbnRlcm5hbCBlcnJvcjogY2xlYXIgdGFzayByZW1vdmVkICR7cmVtb3ZlZC5sZW5ndGh9IHRhc2socykuIENsZWFyIHRhc2sgbXVzdCByZW1vdmVkIGV4YWN0bHkgMSB0YXNrLiBJdCdzIHByb2JhYmx5IGEgYnVnLmBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGRlYnVnKFRBRywgYCR7cmVtb3ZlZFswXS50YXNrLmlkfTogY2xlYXJlZGApO1xuICAgIH0gZWxzZSB7XG4gICAgICBkZWJ1ZyhUQUcsIGAke2lkfTogZG9lcyBub3QgZXhpc3QsIGNhbm5vdCByZW1vdmVgKTtcbiAgICB9XG4gIH1cblxuICBjYW5jZWxBbGwoKSB7XG4gICAgdGhpcy5fdGFza3MuZm9yRWFjaCgodGFzaykgPT4ge1xuICAgICAgdGhpcy5fY2FuY2VsKHRhc2spO1xuICAgIH0pO1xuICB9XG5cbiAgY2xlYXJBbGwoKSB7XG4gICAgdGhpcy5fdGFza3MgPSBbXTtcbiAgfVxuXG4gIGV4ZWM8VGFza0NvbnRleHQ+KFxuICAgIHRhc2tJZDogc3RyaW5nLFxuICAgIGNvbnRleHQ6IFRhc2tDb250ZXh0XG4gICk6IE9ic2VydmFibGU8VGFza01hbmFnZXIuRXZlbnQ8VGFza0NvbnRleHQ+PiB7XG4gICAgY29uc3QgY29udGFpbmVyID0gdGhpcy5jb250YWluZXIodGFza0lkKTtcbiAgICBpZiAoIWNvbnRhaW5lcikge1xuICAgICAgcmV0dXJuIHRocm93RXJyb3IobmV3IEVycm9yKGBUYXNrIHdpdGggaWQgXCIke3Rhc2tJZH1cIiBkb2VzIG5vdCBleGlzdGApKTtcbiAgICB9XG4gICAgY29udGFpbmVyLm1ldGEuY29udGV4dCA9IGNvbnRleHQ7XG4gICAgcmV0dXJuIHRoaXMuZXhlY0FzT2JzZXJ2YWJsZShjb250YWluZXIpO1xuICB9XG5cbiAgcHJpdmF0ZSBleGVjQXNPYnNlcnZhYmxlPFRhc2tDb250ZXh0LCBUYXNrUmVzdWx0PihcbiAgICB0YXNrOiBUYXNrQ29udGFpbmVyPFRhc2tDb250ZXh0LCBUYXNrUmVzdWx0PlxuICApIHtcbiAgICByZXR1cm4gbmV3IE9ic2VydmFibGU8VGFza01hbmFnZXIuRXZlbnQ8VGFza0NvbnRleHQsIFRhc2tSZXN1bHQ+PihcbiAgICAgIChlbWl0dGVyKSA9PiB7XG4gICAgICAgIChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuX2V4ZWModGFzaywgZW1pdHRlcik7XG4gICAgICAgICAgICBlbWl0dGVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBlbWl0dGVyLmVycm9yKGVycik7XG4gICAgICAgICAgfVxuICAgICAgICB9KSgpO1xuICAgICAgfVxuICAgICkucGlwZShzaGFyZSgpKTtcbiAgfVxuXG4gIGFzeW5jIHJldHJ5PFRhc2tDb250ZXh0LCBUYXNrUmVzdWx0PihcbiAgICBjb250YWluZXI6IFRhc2tNYW5hZ2VyLlRhc2tDb250YWluZXI8VGFza0NvbnRleHQsIFRhc2tSZXN1bHQ+XG4gICk6IFByb21pc2U8VGFza1Jlc3VsdD4ge1xuICAgIHJldHVybiAoXG4gICAgICAoYXdhaXQgdGhpcy5leGVjQXNPYnNlcnZhYmxlKFxuICAgICAgICBjb250YWluZXJcbiAgICAgICkudG9Qcm9taXNlKCkpIGFzIFRhc2tNYW5hZ2VyLkFmdGVyVGFza0V2ZW50PFRhc2tDb250ZXh0LCBUYXNrUmVzdWx0PlxuICAgICkucmVzdWx0O1xuICB9XG5cbiAgZXhlY05leHQoKSB7XG4gICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlPFRhc2tNYW5hZ2VyLkV2ZW50PHVua25vd24+PigoZW1pdHRlcikgPT4ge1xuICAgICAgKGFzeW5jICgpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBpZiAodGhpcy5fdGFza3MubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5fZXhlYyh0aGlzLl90YXNrc1swXSwgZW1pdHRlcik7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVtaXR0ZXIuY29tcGxldGUoKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgZW1pdHRlci5lcnJvcihlcnIpO1xuICAgICAgICB9XG4gICAgICB9KSgpO1xuICAgIH0pLnBpcGUoc2hhcmUoKSk7XG4gIH1cblxuICBleGVjRGVsYXllZFRhc2tzKCkge1xuICAgIHJldHVybiB0aGlzLmV4ZWNUYXNrc0J5U3RhdGUoJ2RlbGF5ZWQnKTtcbiAgfVxuXG4gIGV4ZWNQZW5kaW5nVGFza3MoKTogT2JzZXJ2YWJsZTxUYXNrTWFuYWdlci5FdmVudDx1bmtub3duPj4ge1xuICAgIHJldHVybiB0aGlzLmV4ZWNUYXNrc0J5U3RhdGUoJ3BlbmRpbmcnKTtcbiAgfVxuXG4gIGV4ZWNUYXNrc0J5U3RhdGUoXG4gICAgc3RhdGU6IFRhc2tNYW5hZ2VyLlRhc2tTdGF0ZVxuICApOiBPYnNlcnZhYmxlPFRhc2tNYW5hZ2VyLkV2ZW50PHVua25vd24+PiB7XG4gICAgY29uc3Qgb2JzID0gbmV3IE9ic2VydmFibGUoXG4gICAgICAoZW1pdHRlcjogU3Vic2NyaWJlcjxUYXNrTWFuYWdlci5FdmVudDx1bmtub3duPj4pID0+IHtcbiAgICAgICAgbGV0IHN0b3AgPSBmYWxzZTtcbiAgICAgICAgKGFzeW5jICgpID0+IHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcGVuZGluZ1Rhc2tzID0gdGhpcy5fdGFza3MuZmlsdGVyKFxuICAgICAgICAgICAgICAoY29udGFpbmVyKSA9PiBjb250YWluZXIubWV0YS5zdGF0ZSA9PT0gc3RhdGVcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBkZWJ1ZyhcbiAgICAgICAgICAgICAgVEFHLFxuICAgICAgICAgICAgICBgZXhlY0FsbCgpIHdpdGggJHtcbiAgICAgICAgICAgICAgICBwZW5kaW5nVGFza3MubGVuZ3RoXG4gICAgICAgICAgICAgIH0gdGFzayhzKSAoc3RhdGUgPT0gJHtzdGF0ZX0pOiAke3BlbmRpbmdUYXNrc1xuICAgICAgICAgICAgICAgIC5tYXAoKHRhc2spID0+IHRhc2sudGFzay5pZClcbiAgICAgICAgICAgICAgICAuam9pbignLCAnKX1gXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgZm9yIChjb25zdCBwZW5kaW5nVGFzayBvZiBwZW5kaW5nVGFza3MpIHtcbiAgICAgICAgICAgICAgaWYgKCFzdG9wKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5fZXhlYyhwZW5kaW5nVGFzaywgZW1pdHRlcik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlYnVnKFRBRywgJ2V4ZWNBbGwoKSBDT01QTEVURUQnKTtcbiAgICAgICAgICAgIGVtaXR0ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGRlYnVnKFRBRywgJ2V4ZWNBbGwoKSBFUlJPUicpO1xuICAgICAgICAgICAgZW1pdHRlci5lcnJvcihlcnIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSkoKTtcbiAgICAgICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgICBzdG9wID0gdHJ1ZTtcbiAgICAgICAgICAvLyBOb3RoaW5nIHRvIGRvIHdoZW4gdW5zdWJzY3JpYmluZ1xuICAgICAgICB9O1xuICAgICAgfVxuICAgICk7XG4gICAgcmV0dXJuIG9icy5waXBlKHNoYXJlKCkpO1xuICB9XG5cbiAgZ2V0VGFza1Bvc2l0aW9uKGlkOiBzdHJpbmcpOiBudW1iZXIge1xuICAgIC8vIFJldmVyc2VkIGZvciBMSUZPIG1hbmFnZW1lbnQgb2YgdGFza3Mgd2l0aCB0aGUgc2FtZSBpZC5cbiAgICAvLyBUTyBWQUxJREFURVxuICAgIHJldHVybiB0aGlzLl90YXNrc1xuICAgICAgLnJldmVyc2UoKVxuICAgICAgLmZpbmRJbmRleCgoY29udGFpbmVyKSA9PiBjb250YWluZXIudGFzay5pZCA9PT0gaWQpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBfZXhlYzxUYXNrQ29udGV4dCwgVGFza1Jlc3VsdD4oXG4gICAgdGFza0NvbnRhaW5lcjogVGFza0NvbnRhaW5lcjxUYXNrQ29udGV4dCwgVGFza1Jlc3VsdD4sXG4gICAgZW1pdHRlcjogU3Vic2NyaWJlcjxUYXNrTWFuYWdlci5FdmVudDxUYXNrQ29udGV4dCwgVGFza1Jlc3VsdD4+XG4gICkge1xuICAgIGNvbnN0IHRhc2sgPSB0YXNrQ29udGFpbmVyLnRhc2s7XG4gICAgdHJ5IHtcbiAgICAgIGRlYnVnKFRBRywgYCR7dGFzay5pZH0gX2V4ZWMoKSBzdGFydGluZ2ApO1xuICAgICAgdGFza0NvbnRhaW5lci5tZXRhLnN0YXRlID0gJ3J1bm5pbmcnO1xuICAgICAgdGhpcy5fZW1pdChcbiAgICAgICAge1xuICAgICAgICAgIHR5cGU6ICdCRUZPUkVfVEFTSycsXG4gICAgICAgICAgdGFzazogdGFzayxcbiAgICAgICAgfSxcbiAgICAgICAgW2VtaXR0ZXIsIHRhc2tDb250YWluZXIuZXZlbnRzXVxuICAgICAgKTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRhc2suZXhlYyh0YXNrQ29udGFpbmVyLm1ldGEuY29udGV4dCk7XG4gICAgICAvLyB0aGlzLmNsZWFyVGFzayh0YXNrLmlkKTtcbiAgICAgIHRoaXMuX2VtaXQoXG4gICAgICAgIHtcbiAgICAgICAgICB0eXBlOiAnQUZURVJfVEFTSycsXG4gICAgICAgICAgdGFzazogdGFzayxcbiAgICAgICAgICByZXN1bHQ6IHJlc3VsdCxcbiAgICAgICAgfSxcbiAgICAgICAgW2VtaXR0ZXIsIHRhc2tDb250YWluZXIuZXZlbnRzXVxuICAgICAgKTtcbiAgICAgIHRhc2tDb250YWluZXIubWV0YS5yZXN1bHQgPSByZXN1bHQ7XG4gICAgICB0YXNrQ29udGFpbmVyLm1ldGEuc3RhdGUgPSAnZG9uZSc7XG4gICAgICBkZWJ1ZyhUQUcsIGAke3Rhc2suaWR9IF9leGVjKCkgRE9ORWApO1xuICAgICAgLy8gdGFza0NvbnRhaW5lci5tZXRhLm9icy5jb21wbGV0ZSgpO1xuICAgIH0gY2F0Y2ggKGluaXRpYWxFcnJvcjogYW55KSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLl9vblRhc2tFeGVjRXJyb3IodGFza0NvbnRhaW5lciwgaW5pdGlhbEVycm9yKTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBjb25zdCB0eXBlZEVycm9yID0gZXJyIGFzIEVycm9yO1xuICAgICAgICB0YXNrQ29udGFpbmVyLm1ldGEuZXJyb3IgPSB0eXBlZEVycm9yO1xuICAgICAgICBjb25zdCBpc0RlbGF5ZWQgPSB0aGlzLl9pc0RlbGF5RXJyb3IodHlwZWRFcnJvcik7XG4gICAgICAgIGNvbnN0IG5ld1N0YXRlOiBUYXNrTWFuYWdlci5UYXNrU3RhdGUgPSBpc0RlbGF5ZWQgPyAnZGVsYXllZCcgOiAnZG9uZSc7XG4gICAgICAgIGRlYnVnKFRBRywgdGFza0NvbnRhaW5lci50YXNrLmlkLCAnX29uVGFza0Vycm9yIG5ld1N0YXRlOiAnLCBuZXdTdGF0ZSk7XG4gICAgICAgIHRhc2tDb250YWluZXIubWV0YS5zdGF0ZSA9IG5ld1N0YXRlO1xuICAgICAgICB0YXNrQ29udGFpbmVyLmV2ZW50cy5uZXh0KHtcbiAgICAgICAgICB0eXBlOiAnRVJST1JfVEFTSycsXG4gICAgICAgICAgZXJyb3I6IHR5cGVkRXJyb3IsXG4gICAgICAgICAgZGVsYXllZDogaXNEZWxheWVkLFxuICAgICAgICAgIHRhc2s6IHRhc2tDb250YWluZXIudGFzayxcbiAgICAgICAgfSk7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIF9vblRhc2tFeGVjRXJyb3I8VGFza0NvbnRleHQsIFRhc2tSZXN1bHQ+KFxuICAgIHRhc2tDb250YWluZXI6IFRhc2tDb250YWluZXI8VGFza0NvbnRleHQsIFRhc2tSZXN1bHQ+LFxuICAgIGVycjogRXJyb3JcbiAgKSB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMudGFza0Vycm9yUmVzb2x1dGlvblNlcnZpY2Uub25UYXNrRXJyb3IoXG4gICAgICB0YXNrQ29udGFpbmVyLFxuICAgICAgZXJyXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgX2NhbmNlbDxUYXNrQ29udGV4dCwgVGFza1Jlc3VsdD4oXG4gICAgdGFza0NvbnRhaW5lcjogVGFza0NvbnRhaW5lcjxUYXNrQ29udGV4dCwgVGFza1Jlc3VsdD5cbiAgKSB7XG4gICAgdHJ5IHtcbiAgICAgIGRlYnVnKFRBRywgJ2NhbmNlbCB0YXNrOiAnLCB0YXNrQ29udGFpbmVyLnRhc2suaWQpO1xuICAgICAgY29uc3QgdGFzayA9IHRhc2tDb250YWluZXIudGFzaztcbiAgICAgIGlmICh0YXNrLmNhbmNlbCkge1xuICAgICAgICBhd2FpdCB0YXNrLmNhbmNlbCgpO1xuICAgICAgICB0aGlzLl9lbWl0KHtcbiAgICAgICAgICB0eXBlOiAnQ0FOQ0VMX1RBU0snLFxuICAgICAgICAgIHRhc2s6IHRhc2ssXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgdGFza0NvbnRhaW5lci5tZXRhLnN0YXRlID0gJ3BlbmRpbmcnO1xuICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICB0aGlzLl9vbkVycm9yKGVycik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfZW1pdDxUYXNrQ29udGV4dCwgVGFza1Jlc3VsdCA9IHVua25vd24+KFxuICAgIGV2ZW50OiBUYXNrTWFuYWdlci5FdmVudDxUYXNrQ29udGV4dCwgVGFza1Jlc3VsdD4sXG4gICAgZW1pdHRlcnM6IChcbiAgICAgIHwgU3Vic2NyaWJlcjxUYXNrTWFuYWdlci5FdmVudDxUYXNrQ29udGV4dCwgVGFza1Jlc3VsdD4+XG4gICAgICB8IFN1YmplY3Q8VGFza01hbmFnZXIuRXZlbnQ8VGFza0NvbnRleHQsIFRhc2tSZXN1bHQ+PlxuICAgIClbXSA9IFtdXG4gICkge1xuICAgIHRoaXMuX2V2ZW50cy5uZXh0KGV2ZW50KTtcbiAgICBlbWl0dGVycy5mb3JFYWNoKChlbWl0dGVyKSA9PiB7XG4gICAgICBlbWl0dGVyLm5leHQoZXZlbnQpO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfb25FcnJvcihlcnI6IEVycm9yKSB7XG4gICAgY29uc29sZS53YXJuKCdFcnJvciB0YXNrJywgZXJyKTtcbiAgICAvLyBUT0RPXG4gIH1cblxuICBwcml2YXRlIF9pc0RlbGF5RXJyb3IoZXJyOiBFcnJvcikge1xuICAgIGRlYnVnKFRBRywgJ19pc0RlbGF5RXJyb3InLCBlcnIpO1xuICAgIGlmIChpc1RhcFVzZXJOb3RBdXRob3JpemVkRXJyb3IoZXJyKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiAoXG4gICAgICBpc0NvZGVFcnJvcihUYXBDbGllbnRFcnJvci5Db2RlLk5vdENvbm5lY3RlZEVycm9yLCBlcnIpIHx8XG4gICAgICBpc0NvZGVFcnJvcignTmZjVGFnTG9zdEVycm9yJywgZXJyKSB8fFxuICAgICAgaXNDb2RlRXJyb3IoJ05mY05vdENvbm5lY3RlZEVycm9yJywgZXJyKVxuICAgICk7XG4gIH1cbn1cbiJdfQ==