@iotize/ionic
Version:
Iotize specific building blocks on top of @ionic/angular.
299 lines • 38.1 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 {
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