@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
215 lines • 32.8 kB
JavaScript
import { __decorate, __metadata } from "tslib";
import { Injectable, isDevMode } from '@angular/core';
import { FetchClient, TenantLoginOptionsService, ApplicationService } from '@c8y/client';
import { keys, get } from 'lodash-es';
import { BehaviorSubject, combineLatest, of } from 'rxjs';
import { distinctUntilChanged, filter, map, scan, switchMap, shareReplay, startWith, debounceTime, take } from 'rxjs/operators';
import { OptionsService } from './options.service';
import { StateService } from './state-service.abstract';
import { ApiService } from '@c8y/ngx-components/api';
import { throttle } from './throttle.decorator';
import * as i0 from "@angular/core";
import * as i1 from "@c8y/client";
import * as i2 from "@c8y/ngx-components/api";
import * as i3 from "./options.service";
export class AppStateService extends StateService {
constructor(applicationService, apiService, options, fetchClient, tenantLoginOptionsService) {
super();
this.applicationService = applicationService;
this.apiService = apiService;
this.options = options;
this.fetchClient = fetchClient;
this.tenantLoginOptionsService = tenantLoginOptionsService;
/**
* Saves the state. Should not be accessible directly. Use map or the getter to access
* the state. Use functions in the implementation to change the state.
*/
this.state$ = new BehaviorSubject({
app: {
name: this.options.name,
contextPath: this.getCurrentContextPath() || this.options.contextPath,
icon: this.options.icon
},
supportUrl: this.options.supportUrl,
lang: this.options.get('defaultLanguage', 'en'),
langs: this.getLangs(),
langsDetail: this.options.languages,
loginOptions: this.options.loginOptions,
activateSupportUserAvailable: undefined,
versions: {
backend: undefined,
ui: this.options.versions || { ngx: undefined }
},
hidePowered: this.options.hidePowered,
isLoading: false,
showRightDrawer: this.options.rightDrawer,
loginExtraLink: this.options.get('login_extra_link'),
newsletter: this.options.newsletter
});
this.currentSupportUserName = new BehaviorSubject(null);
this.currentUser = new BehaviorSubject(null);
this.currentTenant = new BehaviorSubject(null);
this.currentApplication = new BehaviorSubject(null);
this.currentApplicationConfig = this.currentApplication.pipe(filter(app => !!app), map(app => app?.config || null));
// in case of noLogin being truthy `loadManifest` is never called.
if (this.options.noLogin) {
this.currentApplication.next(this.state.app);
}
this.apiService.isLoading$.subscribe(isLoading => {
this.state.isLoading = isLoading;
});
this.assignApplicationKeyToDefaultHeaders();
this.currentAppsOfUser = this.currentAppsOfUser$();
}
assignApplicationKeyToDefaultHeaders() {
if (!isDevMode()) {
this.fetchClient.defaultHeaders = {
...(this.fetchClient.defaultHeaders || {}),
'X-Cumulocity-Application-Key': this.options.key
};
}
}
/**
* Returns the current state.
*/
get state() {
return this.state$.value;
}
getLangs() {
const { languages } = this.options;
return languages ? keys(languages).filter(k => languages[k]) : [];
}
/**
* Returns the correct UI version. In hybrid mode for angular and ngx.
*/
get uiVersion() {
const version = this.state.versions.ui;
return version.ngx || version.ng1;
}
/**
* Loads the app manifest. If no access -> throw an error to verify app access.
*/
async loadManifest() {
try {
const normalizedContextPath = this.state.app.contextPath?.split('@')[0];
const { data: application } = await this.applicationService.getManifestOfContextPath(normalizedContextPath);
this.state.app.manifest = application;
this.state.app.id = application.id;
const { data } = await this.applicationService.detail(application.id);
this.currentApplication.next(data);
await this.loadDefaultOptions();
}
catch (ex) {
this.currentApplication.next(this.state.app);
throw ex;
}
}
/**
* Dynamic options are stored on the API in a specific config: {} object. They can
* be used to configure the app dynamically.
*
* Note: To avoids conflicts with the default Config, it is recommended
* to use a certain namespace.
*/
async updateCurrentApplicationConfig(config) {
const appWithUpdatedConfig = await this.applicationService.updateApplicationConfig(this.state.app.id, config);
this.currentApplication.next(appWithUpdatedConfig);
return appWithUpdatedConfig.config;
}
/**
* When this function called, it refreshes the values of loginOptions stored within ui state object.
* Function is throttled to execute the refresh once in a time specified by params of @throttled decorator,
* it should be called on leading edge of the timeout.
*/
async refreshLoginOptions() {
const loginOptions = (await this.tenantLoginOptionsService.listForCurrentTenant()).data;
this.state$.next({ ...this.state, loginOptions });
}
/**
* Checks current users application list and matches it against given application name.
* Returns true if application is in the list.
* @param name application name
*/
async isApplicationAvailable(name) {
const apps = await this.currentAppsOfUser.pipe(take(1)).toPromise();
return apps.some(app => app.name === name || app.contextPath === name);
}
/**
* Sets current user (including support user).
* @param userInfo Info about current user and support user to be set.
*/
setUser(userInfo) {
this.currentSupportUserName.next(userInfo.supportUserName || null);
this.currentUser.next(userInfo.user);
}
/**
* Verifies if the current application is owned by the current tenant.
* @param app The application to verify.
* @returns true if it belongs to the current tenant.
*/
isOwnerOfApplication(app) {
if (!app) {
app = this.currentApplication.value;
}
const currentTenant = this.currentTenant.value;
const appOwner = get(app, 'owner.tenant.id');
return currentTenant?.name === appOwner;
}
/**
* Verifies if the current application is owned by the current tenant.
* @param app The application to verify.
* @returns true if it belongs to the current tenant.
*/
isOwnerOfApplication$(app) {
const app$ = app ? of(app) : this.currentApplication;
return combineLatest([app$, this.currentTenant]).pipe(map(([app, tenant]) => {
if (!app || !tenant) {
return false;
}
return tenant.name === get(app, 'owner.tenant.id');
}));
}
/**
* @returns The current contextPath.
*/
getCurrentContextPath() {
const match = window.location.pathname.match(/\/apps\/(public\/){0,1}(.+?)(\/|\?|#|$)/);
return match && match[2];
}
currentAppsOfUser$() {
const appChanges$ = this.onAppChangesCompletion$().pipe(startWith(undefined));
const userChanges$ = this.currentUser.pipe(map(user => user?.id), distinctUntilChanged());
return combineLatest([userChanges$, appChanges$]).pipe(filter(([userId]) => !!userId), switchMap(([userId]) => this.applicationService.listByUser(userId, {
dropOverwrittenApps: true,
noPaging: true
})), map(({ data }) => data), shareReplay({ bufferSize: 1, refCount: true }));
}
/**
* An Observable emitting once all POST, PUT, DELETE requests to the application API finished
*/
onAppChangesCompletion$() {
const methods = ['POST', 'PUT', 'DELETE'];
return this.apiService.calls.pipe(filter(({ method, url }) => methods.includes(method) && url?.includes('application/applications')), map(({ phase }) => (phase === 'start' ? 1 : -1)), scan((count, item) => count + item, 0), map(count => count === 0), distinctUntilChanged(), debounceTime(500), filter(completed => !!completed), map(() => {
return;
}));
}
async loadDefaultOptions() {
this.state.supportUrl = await this.options.getSupportUrl();
this.state.activateSupportUserAvailable = await this.options.getActivateSupportUser();
this.state.versions.backend = await this.options.getSystemOption('system', 'version');
this.emitNewState();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppStateService, deps: [{ token: i1.ApplicationService }, { token: i2.ApiService }, { token: i3.OptionsService }, { token: i1.FetchClient }, { token: i1.TenantLoginOptionsService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppStateService, providedIn: 'root' }); }
}
__decorate([
throttle(600, { trailing: false }),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], AppStateService.prototype, "refreshLoginOptions", null);
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppStateService, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: () => [{ type: i1.ApplicationService }, { type: i2.ApiService }, { type: i3.OptionsService }, { type: i1.FetchClient }, { type: i1.TenantLoginOptionsService }], propDecorators: { refreshLoginOptions: [] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidWktc3RhdGUuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2NvcmUvY29tbW9uL3VpLXN0YXRlLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3RELE9BQU8sRUFDTCxXQUFXLEVBRVgseUJBQXlCLEVBQ3pCLGtCQUFrQixFQUduQixNQUFNLGFBQWEsQ0FBQztBQUNyQixPQUFPLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUN0QyxPQUFPLEVBQUUsZUFBZSxFQUFFLGFBQWEsRUFBYyxFQUFFLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEUsT0FBTyxFQUNMLG9CQUFvQixFQUNwQixNQUFNLEVBQ04sR0FBRyxFQUNILElBQUksRUFDSixTQUFTLEVBQ1QsV0FBVyxFQUNYLFNBQVMsRUFDVCxZQUFZLEVBQ1osSUFBSSxFQUNMLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFFckQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHNCQUFzQixDQUFDOzs7OztBQUdoRCxNQUFNLE9BQU8sZUFBZ0IsU0FBUSxZQUFZO0lBMEMvQyxZQUNVLGtCQUFzQyxFQUN2QyxVQUFzQixFQUNyQixPQUF1QixFQUN2QixXQUF3QixFQUN4Qix5QkFBb0Q7UUFFNUQsS0FBSyxFQUFFLENBQUM7UUFOQSx1QkFBa0IsR0FBbEIsa0JBQWtCLENBQW9CO1FBQ3ZDLGVBQVUsR0FBVixVQUFVLENBQVk7UUFDckIsWUFBTyxHQUFQLE9BQU8sQ0FBZ0I7UUFDdkIsZ0JBQVcsR0FBWCxXQUFXLENB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Q0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLE9BQU8sR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUN0RixJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDdEIsQ0FBQzsrR0FoUFUsZUFBZTttSEFBZixlQUFlLGNBREYsTUFBTTs7QUFxSXhCO0lBREwsUUFBUSxDQUFDLEdBQUcsRUFBRSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQzs7OzswREFJbEM7NEZBdklVLGVBQWU7a0JBRDNCLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFOytNQXFJMUIsbUJBQW1CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgaXNEZXZNb2RlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBGZXRjaENsaWVudCxcbiAgSUFwcGxpY2F0aW9uLFxuICBUZW5hbnRMb2dpbk9wdGlvbnNTZXJ2aWNlLFxuICBBcHBsaWNhdGlvblNlcnZpY2UsXG4gIElDdXJyZW50VGVuYW50LFxuICBJVXNlclxufSBmcm9tICdAYzh5L2NsaWVudCc7XG5pbXBvcnQgeyBrZXlzLCBnZXQgfSBmcm9tICdsb2Rhc2gtZXMnO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBjb21iaW5lTGF0ZXN0LCBPYnNlcnZhYmxlLCBvZiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtcbiAgZGlzdGluY3RVbnRpbENoYW5nZWQsXG4gIGZpbHRlcixcbiAgbWFwLFxuICBzY2FuLFxuICBzd2l0Y2hNYXAsXG4gIHNoYXJlUmVwbGF5LFxuICBzdGFydFdpdGgsXG4gIGRlYm91bmNlVGltZSxcbiAgdGFrZVxufSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBPcHRpb25zU2VydmljZSB9IGZyb20gJy4vb3B0aW9ucy5zZXJ2aWNlJztcbmltcG9ydCB7IFN0YXRlU2VydmljZSB9IGZyb20gJy4vc3RhdGUtc2VydmljZS5hYnN0cmFjdCc7XG5pbXBvcnQgeyBBcGlTZXJ2aWNlIH0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cy9hcGknO1xuaW1wb3J0IHsgQXBwbGljYXRpb25PcHRpb25zIH0gZnJvbSAnLi9BcHBsaWNhdGlvbk9wdGlvbnMnO1xuaW1wb3J0IHsgdGhyb3R0bGUgfSBmcm9tICcuL3Rocm90dGxlLmRlY29yYXRvcic7XG5cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgQXBwU3RhdGVTZXJ2aWNlIGV4dGVuZHMgU3RhdGVTZXJ2aWNlIHtcbiAgLyoqXG4gICAqIFNhdmVzIHRoZSBzdGF0ZS4gU2hvdWxkIG5vdCBiZSBhY2Nlc3NpYmxlIGRpcmVjdGx5LiBVc2UgbWFwIG9yIHRoZSBnZXR0ZXIgdG8gYWNjZXNzXG4gICAqIHRoZSBzdGF0ZS4gVXNlIGZ1bmN0aW9ucyBpbiB0aGUgaW1wbGVtZW50YXRpb24gdG8gY2hhbmdlIHRoZSBzdGF0ZS5cbiAgICovXG4gIHN0YXRlJDogQmVoYXZpb3JTdWJqZWN0PGFueT4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGFueT4oe1xuICAgIGFwcDoge1xuICAgICAgbmFtZTogdGhpcy5vcHRpb25zLm5hbWUsXG4gICAgICBjb250ZXh0UGF0aDogdGhpcy5nZXRDdXJyZW50Q29udGV4dFBhdGgoKSB8fCB0aGlzLm9wdGlvbnMuY29udGV4dFBhdGgsXG4gICAgICBpY29uOiB0aGlzLm9wdGlvbnMuaWNvblxuICAgIH0sXG4gICAgc3VwcG9ydFVybDogdGhpcy5vcHRpb25zLnN1cHBvcnRVcmwsXG4gICAgbGFuZzogdGhpcy5vcHRpb25zLmdldCgnZGVmYXVsdExhbmd1YWdlJywgJ2VuJyksXG4gICAgbGFuZ3M6IHRoaXMuZ2V0TGFuZ3MoKSxcbiAgICBsYW5nc0RldGFpbDogdGhpcy5vcHRpb25zLmxhbmd1YWdlcyxcbiAgICBsb2dpbk9wdGlvbnM6IHRoaXMub3B0aW9ucy5sb2dpbk9wdGlvbnMsXG4gICAgYWN0aXZhdGVTdXBwb3J0VXNlckF2YWlsYWJsZTogdW5kZWZpbmVkLFxuICAgIHZlcnNpb25zOiB7XG4gICAgICBiYWNrZW5kOiB1bmRlZmluZWQsXG4gICAgICB1aTogdGhpcy5vcHRpb25zLnZlcnNpb25zIHx8IHsgbmd4OiB1bmRlZmluZWQgfVxuICAgIH0sXG4gICAgaGlkZVBvd2VyZWQ6IHRoaXMub3B0aW9ucy5oaWRlUG93ZXJlZCxcbiAgICBpc0xvYWRpbmc6IGZhbHNlLFxuICAgIHNob3dSaWdodERyYXdlcjogdGhpcy5vcHRpb25zLnJpZ2h0RHJhd2VyLFxuICAgIGxvZ2luRXh0cmFMaW5rOiB0aGlzLm9wdGlvbnMuZ2V0KCdsb2dpbl9leHRyYV9saW5rJyksXG4gICAgbmV3c2xldHRlcjogdGhpcy5vcHRpb25zLm5ld3NsZXR0ZXJcbiAgfSk7XG4gIGN1cnJlbnRTdXBwb3J0VXNlck5hbWU6IEJlaGF2aW9yU3ViamVjdDxzdHJpbmcgfCBudWxsPiA9IG5ldyBCZWhhdmlvclN1YmplY3QobnVsbCk7XG4gIGN1cnJlbnRVc2VyOiBCZWhhdmlvclN1YmplY3Q8SVVzZXIgfCBudWxsPiA9IG5ldyBCZWhhdmlvclN1YmplY3QobnVsbCk7XG4gIGN1cnJlbnRUZW5hbnQ6IEJlaGF2aW9yU3ViamVjdDxJQ3VycmVudFRlbmFudCB8IG51bGw+ID0gbmV3IEJlaGF2aW9yU3ViamVjdChudWxsKTtcbiAgY3VycmVudEFwcGxpY2F0aW9uOiBCZWhhdmlvclN1YmplY3Q8SUFwcGxpY2F0aW9uIHwgbnVsbD4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0KG51bGwpO1xuICBjdXJyZW50QXBwbGljYXRpb25Db25maWc6IE9ic2VydmFibGU8YW55PiA9IHRoaXMuY3VycmVudEFwcGxpY2F0aW9uLnBpcGUoXG4gICAgZmlsdGVyKGFwcCA9PiAhIWFwcCksXG4gICAgbWFwKGFwcCA9PiBhcHA/LmNvbmZpZyB8fCBudWxsKVxuICApO1xuICAvKipcbiAgICogQW4gT2JzZXJ2YWJsZSBvZiB0aGUgYXBwbGljYXRpb25zIGF2YWlsYWJsZSBmb3IgdGhlIGN1cnJlbnQgdXNlci5cbiAgICogVGhlIE9ic2VydmFibGUgZW1pdHMgYSBuZXcgYXJyYXkgb24gdXNlciBjaGFuZ2VzIG9yIGlmIHRoZSBhcHBsaWNhdGlvblxuICAgKiBwZXJmb3JtcyBQT1NULCBQVVQgb3IgREVMRVRFIHJlcXVlc3RzIHRvIHRoZSBhcHBsaWNhdGlvbiBBUEkuXG4gICAqL1xuICBjdXJyZW50QXBwc09mVXNlcjogT2JzZXJ2YWJsZTxJQXBwbGljYXRpb25bXT47XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBhcHBsaWNhdGlvblNlcnZpY2U6IEFwcGxpY2F0aW9uU2VydmljZSxcbiAgICBwdWJsaWMgYXBpU2VydmljZTogQXBpU2VydmljZSxcbiAgICBwcml2YXRlIG9wdGlvbnM6IE9wdGlvbnNTZXJ2aWNlLFxuICAgIHByaXZhdGUgZmV0Y2hDbGllbnQ6IEZldGNoQ2xpZW50LFxuICAgIHByaXZhdGUgdGVuYW50TG9naW5PcHRpb25zU2VydmljZTogVGVuYW50TG9naW5PcHRpb25zU2VydmljZVxuICApIHtcbiAgICBzdXBlcigpO1xuICAgIC8vIGluIGNhc2Ugb2Ygbm9Mb2dpbiBiZWluZyB0cnV0aHkgYGxvYWRNYW5pZmVzdGAgaXMgbmV2ZXIgY2FsbGVkLlxuICAgIGlmICh0aGlzLm9wdGlvbnMubm9Mb2dpbikge1xuICAgICAgdGhpcy5jdXJyZW50QXBwbGljYXRpb24ubmV4dCh0aGlzLnN0YXRlLmFwcCk7XG4gICAgfVxuICAgIHRoaXMuYXBpU2VydmljZS5pc0xvYWRpbmckLnN1YnNjcmliZShpc0xvYWRpbmcgPT4ge1xuICAgICAgdGhpcy5zdGF0ZS5pc0xvYWRpbmcgPSBpc0xvYWRpbmc7XG4gICAgfSk7XG5cbiAgICB0aGlzLmFzc2lnbkFwcGxpY2F0aW9uS2V5VG9EZWZhdWx0SGVhZGVycygpO1xuICAgIHRoaXMuY3VycmVudEFwcHNPZlVzZXIgPSB0aGlzLmN1cnJlbnRBcHBzT2ZVc2VyJCgpO1xuICB9XG5cbiAgYXNzaWduQXBwbGljYXRpb25LZXlUb0RlZmF1bHRIZWFkZXJzKCkge1xuICAgIGlmICghaXNEZXZNb2RlKCkpIHtcbiAgICAgIHRoaXMuZmV0Y2hDbGllbnQuZGVmYXVsdEhlYWRlcnMgPSB7XG4gICAgICAgIC4uLih0aGlzLmZldGNoQ2xpZW50LmRlZmF1bHRIZWFkZXJzIHx8IHt9KSxcbiAgICAgICAgJ1gtQ3VtdWxvY2l0eS1BcHBsaWNhdGlvbi1LZXknOiB0aGlzLm9wdGlvbnMua2V5XG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHN0YXRlLlxuICAgKi9cbiAgZ2V0IHN0YXRlKCkge1xuICAgIHJldHVybiB0aGlzLnN0YXRlJC52YWx1ZTtcbiAgfVxuXG4gIGdldExhbmdzKCkge1xuICAgIGNvbnN0IHsgbGFuZ3VhZ2VzIH0gPSB0aGlzLm9wdGlvbnM7XG4gICAgcmV0dXJuIGxhbmd1YWdlcyA/IGtleXMobGFuZ3VhZ2VzKS5maWx0ZXIoayA9PiBsYW5ndWFnZXNba10pIDogW107XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY29ycmVjdCBVSSB2ZXJzaW9uLiBJbiBoeWJyaWQgbW9kZSBmb3IgYW5ndWxhciBhbmQgbmd4LlxuICAgKi9cbiAgZ2V0IHVpVmVyc2lvbigpIHtcbiAgICBjb25zdCB2ZXJzaW9uID0gdGhpcy5zdGF0ZS52ZXJzaW9ucy51aTtcbiAgICByZXR1cm4gdmVyc2lvbi5uZ3ggfHwgdmVyc2lvbi5uZzE7XG4gIH1cblxuICAvKipcbiAgICogTG9hZHMgdGhlIGFwcCBtYW5pZmVzdC4gSWYgbm8gYWNjZXNzIC0+IHRocm93IGFuIGVycm9yIHRvIHZlcmlmeSBhcHAgYWNjZXNzLlxuICAgKi9cbiAgYXN5bmMgbG9hZE1hbmlmZXN0KCkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBub3JtYWxpemVkQ29udGV4dFBhdGggPSB0aGlzLnN0YXRlLmFwcC5jb250ZXh0UGF0aD8uc3BsaXQoJ0AnKVswXTtcbiAgICAgIGNvbnN0IHsgZGF0YTogYXBwbGljYXRpb24gfSA9XG4gICAgICAgIGF3YWl0IHRoaXMuYXBwbGljYXRpb25TZXJ2aWNlLmdldE1hbmlmZXN0T2ZDb250ZXh0UGF0aChub3JtYWxpemVkQ29udGV4dFBhdGgpO1xuICAgICAgdGhpcy5zdGF0ZS5hcHAubWFuaWZlc3QgPSBhcHBsaWNhdGlvbjtcbiAgICAgIHRoaXMuc3RhdGUuYXBwLmlkID0gYXBwbGljYXRpb24uaWQ7XG4gICAgICBjb25zdCB7IGRhdGEgfSA9IGF3YWl0IHRoaXMuYXBwbGljYXRpb25TZXJ2aWNlLmRldGFpbChhcHBsaWNhdGlvbi5pZCk7XG4gICAgICB0aGlzLmN1cnJlbnRBcHBsaWNhdGlvbi5uZXh0KGRhdGEpO1xuICAgICAgYXdhaXQgdGhpcy5sb2FkRGVmYXVsdE9wdGlvbnMoKTtcbiAgICB9IGNhdGNoIChleCkge1xuICAgICAgdGhpcy5jdXJyZW50QXBwbGljYXRpb24ubmV4dCh0aGlzLnN0YXRlLmFwcCk7XG4gICAgICB0aHJvdyBleDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRHluYW1pYyBvcHRpb25zIGFyZSBzdG9yZWQgb24gdGhlIEFQSSBpbiBhIHNwZWNpZmljIGNvbmZpZzoge30gb2JqZWN0LiBUaGV5IGNhblxuICAgKiBiZSB1c2VkIHRvIGNvbmZpZ3VyZSB0aGUgYXBwIGR5bmFtaWNhbGx5LlxuICAgKlxuICAgKiBOb3RlOiBUbyBhdm9pZHMgY29uZmxpY3RzIHdpdGggdGhlIGRlZmF1bHQgQ29uZmlnLCBpdCBpcyByZWNvbW1lbmRlZFxuICAgKiB0byB1c2UgYSBjZXJ0YWluIG5hbWVzcGFjZS5cbiAgICovXG4gIGFzeW5jIHVwZGF0ZUN1cnJlbnRBcHBsaWNhdGlvbkNvbmZpZzxUID0gQXBwbGljYXRpb25PcHRpb25zPihjb25maWc6IFQpOiBQcm9taXNlPFQ+IHtcbiAgICBjb25zdCBhcHBXaXRoVXBkYXRlZENvbmZpZyA9IGF3YWl0IHRoaXMuYXBwbGljYXRpb25TZXJ2aWNlLnVwZGF0ZUFwcGxpY2F0aW9uQ29uZmlnKFxuICAgICAgdGhpcy5zdGF0ZS5hcHAuaWQsXG4gICAgICBjb25maWdcbiAgICApO1xuICAgIHRoaXMuY3VycmVudEFwcGxpY2F0aW9uLm5leHQoYXBwV2l0aFVwZGF0ZWRDb25maWcpO1xuICAgIHJldHVybiBhcHBXaXRoVXBkYXRlZENvbmZpZy5jb25maWc7XG4gIH1cblxuICAvKipcbiAgICogV2hlbiB0aGlzIGZ1bmN0aW9uIGNhbGxlZCwgaXQgcmVmcmVzaGVzIHRoZSB2YWx1ZXMgb2YgbG9naW5PcHRpb25zIHN0b3JlZCB3aXRoaW4gdWkgc3RhdGUgb2JqZWN0LlxuICAgKiBGdW5jdGlvbiBpcyB0aHJvdHRsZWQgdG8gZXhlY3V0ZSB0aGUgcmVmcmVzaCBvbmNlIGluIGEgdGltZSBzcGVjaWZpZWQgYnkgcGFyYW1zIG9mIEB0aHJvdHRsZWQgZGVjb3JhdG9yLFxuICAgKiBpdCBzaG91bGQgYmUgY2FsbGVkIG9uIGxlYWRpbmcgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAgICovXG4gIEB0aHJvdHRsZSg2MDAsIHsgdHJhaWxpbmc6IGZhbHNlIH0pXG4gIGFzeW5jIHJlZnJlc2hMb2dpbk9wdGlvbnMoKSB7XG4gICAgY29uc3QgbG9naW5PcHRpb25zID0gKGF3YWl0IHRoaXMudGVuYW50TG9naW5PcHRpb25zU2VydmljZS5saXN0Rm9yQ3VycmVudFRlbmFudCgpKS5kYXRhO1xuICAgIHRoaXMuc3RhdGUkLm5leHQoeyAuLi50aGlzLnN0YXRlLCBsb2dpbk9wdGlvbnMgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGN1cnJlbnQgdXNlcnMgYXBwbGljYXRpb24gbGlzdCBhbmQgbWF0Y2hlcyBpdCBhZ2FpbnN0IGdpdmVuIGFwcGxpY2F0aW9uIG5hbWUuXG4gICAqIFJldHVybnMgdHJ1ZSBpZiBhcHBsaWNhdGlvbiBpcyBpbiB0aGUgbGlzdC5cbiAgICogQHBhcmFtIG5hbWUgYXBwbGljYXRpb24gbmFtZVxuICAgKi9cbiAgYXN5bmMgaXNBcHBsaWNhdGlvbkF2YWlsYWJsZShuYW1lOiBzdHJpbmcpIHtcbiAgICBjb25zdCBhcHBzID0gYXdhaXQgdGhpcy5jdXJyZW50QXBwc09mVXNlci5waXBlKHRha2UoMSkpLnRvUHJvbWlzZSgpO1xuICAgIHJldHVybiBhcHBzLnNvbWUoYXBwID0+IGFwcC5uYW1lID09PSBuYW1lIHx8IGFwcC5jb250ZXh0UGF0aCA9PT0gbmFtZSk7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBjdXJyZW50IHVzZXIgKGluY2x1ZGluZyBzdXBwb3J0IHVzZXIpLlxuICAgKiBAcGFyYW0gdXNlckluZm8gSW5mbyBhYm91dCBjdXJyZW50IHVzZXIgYW5kIHN1cHBvcnQgdXNlciB0byBiZSBzZXQuXG4gICAqL1xuICBzZXRVc2VyKHVzZXJJbmZvOiB7IHVzZXI6IElVc2VyOyBzdXBwb3J0VXNlck5hbWU6IHN0cmluZyB9KSB7XG4gICAgdGhpcy5jdXJyZW50U3VwcG9ydFVzZXJOYW1lLm5leHQodXNlckluZm8uc3VwcG9ydFVzZXJOYW1lIHx8IG51bGwpO1xuICAgIHRoaXMuY3VycmVudFVzZXIubmV4dCh1c2VySW5mby51c2VyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWZXJpZmllcyBpZiB0aGUgY3VycmVudCBhcHBsaWNhdGlvbiBpcyBvd25lZCBieSB0aGUgY3VycmVudCB0ZW5hbnQuXG4gICAqIEBwYXJhbSBhcHAgVGhlIGFwcGxpY2F0aW9uIHRvIHZlcmlmeS5cbiAgICogQHJldHVybnMgdHJ1ZSBpZiBpdCBiZWxvbmdzIHRvIHRoZSBjdXJyZW50IHRlbmFudC5cbiAgICovXG4gIGlzT3duZXJPZkFwcGxpY2F0aW9uKGFwcD86IElBcHBsaWNhdGlvbik6IGJvb2xlYW4ge1xuICAgIGlmICghYXBwKSB7XG4gICAgICBhcHAgPSB0aGlzLmN1cnJlbnRBcHBsaWNhdGlvbi52YWx1ZTtcbiAgICB9XG4gICAgY29uc3QgY3VycmVudFRlbmFudDogSUN1cnJlbnRUZW5hbnQgPSB0aGlzLmN1cnJlbnRUZW5hbnQudmFsdWU7XG4gICAgY29uc3QgYXBwT3duZXIgPSBnZXQoYXBwLCAnb3duZXIudGVuYW50LmlkJyk7XG4gICAgcmV0dXJuIGN1cnJlbnRUZW5hbnQ/Lm5hbWUgPT09IGFwcE93bmVyO1xuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmaWVzIGlmIHRoZSBjdXJyZW50IGFwcGxpY2F0aW9uIGlzIG93bmVkIGJ5IHRoZSBjdXJyZW50IHRlbmFudC5cbiAgICogQHBhcmFtIGFwcCBUaGUgYXBwbGljYXRpb24gdG8gdmVyaWZ5LlxuICAgKiBAcmV0dXJucyB0cnVlIGlmIGl0IGJlbG9uZ3MgdG8gdGhlIGN1cnJlbnQgdGVuYW50LlxuICAgKi9cbiAgaXNPd25lck9mQXBwbGljYXRpb24kKGFwcD86IElBcHBsaWNhdGlvbik6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IGFwcCQgPSBhcHAgPyBvZihhcHApIDogdGhpcy5jdXJyZW50QXBwbGljYXRpb247XG4gICAgcmV0dXJuIGNvbWJpbmVMYXRlc3QoW2FwcCQsIHRoaXMuY3VycmVudFRlbmFudF0pLnBpcGUoXG4gICAgICBtYXAoKFthcHAsIHRlbmFudF0pID0+IHtcbiAgICAgICAgaWYgKCFhcHAgfHwgIXRlbmFudCkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGVuYW50Lm5hbWUgPT09IGdldChhcHAsICdvd25lci50ZW5hbnQuaWQnKTtcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJucyBUaGUgY3VycmVudCBjb250ZXh0UGF0aC5cbiAgICovXG4gIGdldEN1cnJlbnRDb250ZXh0UGF0aCgpIHtcbiAgICBjb25zdCBtYXRjaCA9IHdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZS5tYXRjaCgvXFwvYXBwc1xcLyhwdWJsaWNcXC8pezAsMX0oLis/KShcXC98XFw/fCN8JCkvKTtcbiAgICByZXR1cm4gbWF0Y2ggJiYgbWF0Y2hbMl07XG4gIH1cblxuICBwcm90ZWN0ZWQgY3VycmVudEFwcHNPZlVzZXIkKCk6IE9ic2VydmFibGU8SUFwcGxpY2F0aW9uW10+IHtcbiAgICBjb25zdCBhcHBDaGFuZ2VzJCA9IHRoaXMub25BcHBDaGFuZ2VzQ29tcGxldGlvbiQoKS5waXBlKHN0YXJ0V2l0aCh1bmRlZmluZWQgYXMgdm9pZCkpO1xuICAgIGNvbnN0IHVzZXJDaGFuZ2VzJCA9IHRoaXMuY3VycmVudFVzZXIucGlwZShcbiAgICAgIG1hcCh1c2VyID0+IHVzZXI/LmlkKSxcbiAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKClcbiAgICApO1xuICAgIHJldHVybiBjb21iaW5lTGF0ZXN0KFt1c2VyQ2hhbmdlcyQsIGFwcENoYW5nZXMkXSkucGlwZShcbiAgICAgIGZpbHRlcigoW3VzZXJJZF0pID0+ICEhdXNlcklkKSxcbiAgICAgIHN3aXRjaE1hcCgoW3VzZXJJZF0pID0+XG4gICAgICAgIHRoaXMuYXBwbGljYXRpb25TZXJ2aWNlLmxpc3RCeVVzZXIodXNlcklkLCB7XG4gICAgICAgICAgZHJvcE92ZXJ3cml0dGVuQXBwczogdHJ1ZSxcbiAgICAgICAgICBub1BhZ2luZzogdHJ1ZVxuICAgICAgICB9KVxuICAgICAgKSxcbiAgICAgIG1hcCgoeyBkYXRhIH0pID0+IGRhdGEpLFxuICAgICAgc2hhcmVSZXBsYXkoeyBidWZmZXJTaXplOiAxLCByZWZDb3VudDogdHJ1ZSB9KVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQW4gT2JzZXJ2YWJsZSBlbWl0dGluZyBvbmNlIGFsbCBQT1NULCBQVVQsIERFTEVURSByZXF1ZXN0cyB0byB0aGUgYXBwbGljYXRpb24gQVBJIGZpbmlzaGVkXG4gICAqL1xuICBwcm90ZWN0ZWQgb25BcHBDaGFuZ2VzQ29tcGxldGlvbiQoKTogT2JzZXJ2YWJsZTx2b2lkPiB7XG4gICAgY29uc3QgbWV0aG9kcyA9IFsnUE9TVCcsICdQVVQnLCAnREVMRVRFJ107XG4gICAgcmV0dXJuIHRoaXMuYXBpU2VydmljZS5jYWxscy5waXBlKFxuICAgICAgZmlsdGVyKFxuICAgICAgICAoeyBtZXRob2QsIHVybCB9KSA9PiBtZXRob2RzLmluY2x1ZGVzKG1ldGhvZCkgJiYgdXJsPy5pbmNsdWRlcygnYXBwbGljYXRpb24vYXBwbGljYXRpb25zJylcbiAgICAgICksXG4gICAgICBtYXAoKHsgcGhhc2UgfSkgPT4gKHBoYXNlID09PSAnc3RhcnQnID8gMSA6IC0xKSksXG4gICAgICBzY2FuKChjb3VudCwgaXRlbSkgPT4gY291bnQgKyBpdGVtLCAwKSxcbiAgICAgIG1hcChjb3VudCA9PiBjb3VudCA9PT0gMCksXG4gICAgICBkaXN0aW5jdFVudGlsQ2hhbmdlZCgpLFxuICAgICAgZGVib3VuY2VUaW1lKDUwMCksXG4gICAgICBmaWx0ZXIoY29tcGxldGVkID0+ICEhY29tcGxldGVkKSxcbiAgICAgIG1hcCgoKSA9PiB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbG9hZERlZmF1bHRPcHRpb25zKCkge1xuICAgIHRoaXMuc3RhdGUuc3VwcG9ydFVybCA9IGF3YWl0IHRoaXMub3B0aW9ucy5nZXRTdXBwb3J0VXJsKCk7XG4gICAgdGhpcy5zdGF0ZS5hY3RpdmF0ZVN1cHBvcnRVc2VyQXZhaWxhYmxlID0gYXdhaXQgdGhpcy5vcHRpb25zLmdldEFjdGl2YXRlU3VwcG9ydFVzZXIoKTtcbiAgICB0aGlzLnN0YXRlLnZlcnNpb25zLmJhY2tlbmQgPSBhd2FpdCB0aGlzLm9wdGlvbnMuZ2V0U3lzdGVtT3B0aW9uKCdzeXN0ZW0nLCAndmVyc2lvbicpO1xuICAgIHRoaXMuZW1pdE5ld1N0YXRlKCk7XG4gIH1cbn1cbiJdfQ==