@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
242 lines • 30.3 kB
JavaScript
import { InjectionToken, Optional, Inject, Injectable } from '@angular/core';
import { camelCase, isUndefined, isEqual } from 'lodash-es';
import { ApplicationOptions } from './ApplicationOptions';
import { hookGeneric } from './extension-hooks';
import { SystemOptionsService, TenantOptionsService } from '@c8y/client';
import { Subject } from 'rxjs';
import { distinctUntilChanged, map, startWith } from 'rxjs/operators';
import * as i0 from "@angular/core";
import * as i1 from "@c8y/client";
/**
* @deprecated Consider using the `hookOptions` function instead.
*/
export const HOOK_OPTIONS = new InjectionToken('HOOK_OPTIONS');
/**
* You can either provide a single `ApplicationOptions` as parameter:
* ```typescript
* hookOptions(...)
* ```
*
* Or an array to directly register multiple:
* ```typescript
* hookOptions([...])
* ```
*
* Or you provide an Service that implements `ExtensionFactory<ApplicationOptions>`
* ```typescript
* export class MyApplicationOptionsFactory implements ExtensionFactory<ApplicationOptions> {...}
* ...
* hookOptions(MyApplicationOptionsFactory)
* ```
* A typed alternative to `HOOK_OPTIONS`.
* @param options The `ApplicationOptions`'s or `ExtensionFactory` to be provided.
* @returns An `Provider` to be provided in your module.
*/
export function hookOptions(options, hookOptions) {
return hookGeneric(options, HOOK_OPTIONS, hookOptions);
}
/**
* A service that allows to set or get application options
* which configure the default behavior of the UI.
*/
export class OptionsService extends ApplicationOptions {
constructor(options, systemOptionsService, tenantOptionService) {
super();
this.systemOptionsService = systemOptionsService;
this.tenantOptionService = tenantOptionService;
this._optionsUpdated$ = new Subject();
this.optionsUpdated$ = this._optionsUpdated$.asObservable();
this.setupOptions(options);
}
/**
* Returns an application option used to configure the UI.
* @param optionKey The application options key.
* @param defaultValue A value to return if non is set.
* @param attemptParse Indicates whether the value should be parsed with JSON.parse.
*/
get(optionKey, defaultValue, attemptParse) {
let value = this[optionKey];
if (typeof value === 'undefined') {
value = this[camelCase(optionKey)];
}
if (attemptParse) {
return this.parseOptionRawValue(value, defaultValue);
}
return typeof value !== 'undefined' ? value : defaultValue;
}
/**
* Returns an observable of an application option used to configure the UI.
* @param optionKey The application options key.
* @param defaultValue A value to return if non is set.
* @param attemptParse Indicates whether the value should be parsed with JSON.parse.
*/
get$(optionKey, defaultValue, attemptParse) {
const fn = () => this.get(optionKey, defaultValue, attemptParse);
return this.optionsUpdated$.pipe(map(fn), startWith(fn()), distinctUntilChanged());
}
/**
* Sets an application option.
* @param key The key to set.
* @param value The value to set.
*/
set(key, value) {
const camelCasedKey = camelCase(key);
const previousValue = this[camelCasedKey];
this[camelCasedKey] = value;
if (!isEqual(previousValue, value)) {
this._optionsUpdated$.next();
}
}
/**
* Deletes an application option.
* @param key The key to remove.
*/
delete(key) {
const camelCasedKey = camelCase(key);
const previousValue = this[camelCasedKey];
delete this[camelCasedKey];
const newValue = this[camelCasedKey];
if (!isEqual(previousValue, newValue)) {
this._optionsUpdated$.next();
}
}
/**
* Gets support URL from:
* - application option `supportUrl`,
* - or current tenant's option `configuration / system.support.url`,
* - or current tenant's inherited option `configuration / system.support.url`,
* - or system option `configuration / system.support.url`,
* - otherwise defaults to `false`.
*
* @returns Returns support url or false.
*/
async getSupportUrl() {
let url = this.supportUrl;
if (isUndefined(url)) {
url = await this.getCurrentTenantOption('configuration', 'system.support.url');
}
if (isUndefined(url)) {
url = await this.getInheritedTenantOption('configuration', 'system.support.url');
}
if (isUndefined(url)) {
url = (await this.getSystemOption('support', 'url')) || false;
}
this.supportUrl = url;
return this.supportUrl;
}
/**
* Returns if the tenant allows to show the activate-support user menu entry.
* Note: Only if system-level support-user/enabled is false we can activate it at tenant level.
*/
async getActivateSupportUser() {
const option = await this.getSystemOption('support-user', 'enabled', true);
return !option;
}
/**
* Gets a value from the system service and parses it.
*
* @param category The category for this option.
* @param key The key for that option.
* @param defaultValue The default if the option was not found.
*/
async getSystemOption(category, key, defaultValue) {
return this.getOptionFromService(category, key, null, this.systemOptionsService, defaultValue);
}
/**
* Gets a value from the tenant service and parses it.
*
* @param category The category for this option.
* @param key The key for that option.
* @param defaultValue The default if the option was not found.
*/
async getTenantOption(category, key, defaultValue) {
return this.getOptionFromService(category, key, null, this.tenantOptionService, defaultValue);
}
/**
* Gets an inherited from parent value from the tenant service if inheritance supported based on given parameters.
*
* @param category The category for this option.
* @param key The key for that option.
* @param defaultValue The default if the option was not found.
*/
async getInheritedTenantOption(category, key, defaultValue) {
return this.getOptionFromService(category, key, { evaluate: 'inherited' }, this.tenantOptionService, defaultValue);
}
/**
* Gets current tenant option value from the tenant service omitting the inheritance supported based on given parameters.
*
* @param category The category for this option.
* @param key The key for that option.
* @param defaultValue The default if the option was not found.
*/
async getCurrentTenantOption(category, key, defaultValue) {
return this.getOptionFromService(category, key, { evaluate: 'current' }, this.tenantOptionService, defaultValue);
}
setupOptions(options) {
if (options) {
if (!Array.isArray(options)) {
options = [options];
}
let combinedOptions = {};
if (options.length === 1) {
combinedOptions = options[0];
}
else if (options.length > 1) {
options.forEach(optionMap => {
if (optionMap) {
this.applyOptions(optionMap, combinedOptions);
}
});
}
else {
return;
}
if (this.applyOptions(combinedOptions, this)) {
this._optionsUpdated$.next();
}
}
}
applyOptions(options, applyTo) {
let optionWasChanged = false;
Object.entries(options).forEach(([key, value]) => {
const camelCasedKey = camelCase(key);
const previousValue = applyTo[camelCasedKey];
applyTo[camelCasedKey] = value;
if (!isEqual(previousValue, value)) {
optionWasChanged = true;
}
});
return optionWasChanged;
}
async getOptionFromService(category, key, filter, service, defaultValue) {
try {
const { data } = await service.detail({ category, key }, filter);
return this.parseOptionRawValue(data.value, defaultValue);
}
catch (ex) {
return defaultValue;
}
}
parseOptionRawValue(rawValue, defaultValue) {
let value;
try {
value = JSON.parse(rawValue);
}
catch (e) {
value = isUndefined(rawValue) ? defaultValue : rawValue;
}
return value;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: OptionsService, deps: [{ token: HOOK_OPTIONS, optional: true }, { token: i1.SystemOptionsService }, { token: i1.TenantOptionsService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: OptionsService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: OptionsService, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [HOOK_OPTIONS]
}] }, { type: i1.SystemOptionsService }, { type: i1.TenantOptionsService }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3B0aW9ucy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vY29yZS9jb21tb24vb3B0aW9ucy5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxjQUFjLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDN0UsT0FBTyxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzVELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzFELE9BQU8sRUFHTCxXQUFXLEVBRVosTUFBTSxtQkFBbUIsQ0FBQztBQUMzQixPQUFPLEVBQUUsb0JBQW9CLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFekUsT0FBTyxFQUFjLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMzQyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7QUFFdEU7O0dBRUc7QUFDSCxNQUFNLENBQUMsTUFBTSxZQUFZLEdBQUcsSUFBSSxjQUFjLENBQzVDLGNBQWMsQ0FDZixDQUFDO0FBRUY7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JHO0FBQ0gsTUFBTSxVQUFVLFdBQVcsQ0FDekIsT0FBNEMsRUFDNUMsV0FBeUM7SUFFekMsT0FBTyxXQUFXLENBQXFCLE9BQU8sRUFBRSxZQUFZLEVBQUUsV0FBVyxDQUFDLENBQUM7QUFDN0UsQ0FBQztBQUVEOzs7R0FHRztBQUVILE1BQU0sT0FBTyxjQUFlLFNBQVEsa0JBQWtCO0lBSXBELFlBQ29DLE9BQU8sRUFDakMsb0JBQTBDLEVBQzFDLG1CQUF5QztRQUVqRCxLQUFLLEVBQUUsQ0FBQztRQUhBLHlCQUFvQixHQUFwQixvQkFBb0IsQ0FBc0I7UUFDMUMsd0JBQW1CLEdBQW5CLG1CQUFtQixD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Q1gsS0FBSyxHQUFHLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUM7UUFDMUQsQ0FBQztRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQzsrR0FsUVUsY0FBYyxrQkFLSCxZQUFZO21IQUx2QixjQUFjLGNBREQsTUFBTTs7NEZBQ25CLGNBQWM7a0JBRDFCLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFOzswQkFNN0IsUUFBUTs7MEJBQUksTUFBTTsyQkFBQyxZQUFZIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0aW9uVG9rZW4sIE9wdGlvbmFsLCBJbmplY3QsIEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGNhbWVsQ2FzZSwgaXNVbmRlZmluZWQsIGlzRXF1YWwgfSBmcm9tICdsb2Rhc2gtZXMnO1xuaW1wb3J0IHsgQXBwbGljYXRpb25PcHRpb25zIH0gZnJvbSAnLi9BcHBsaWNhdGlvbk9wdGlvbnMnO1xuaW1wb3J0IHtcbiAgRXh0ZW5zaW9uRmFjdG9yeSxcbiAgR2VuZXJpY0hvb2tUeXBlLFxuICBob29rR2VuZXJpYyxcbiAgR2VuZXJpY0hvb2tPcHRpb25zXG59IGZyb20gJy4vZXh0ZW5zaW9uLWhvb2tzJztcbmltcG9ydCB7IFN5c3RlbU9wdGlvbnNTZXJ2aWNlLCBUZW5hbnRPcHRpb25zU2VydmljZSB9IGZyb20gJ0BjOHkvY2xpZW50JztcbmltcG9ydCB7IElUZW5hbnRPcHRpb25EZXRhaWxQYXJhbXMgfSBmcm9tICdAYzh5L2NsaWVudCc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBkaXN0aW5jdFVudGlsQ2hhbmdlZCwgbWFwLCBzdGFydFdpdGggfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbi8qKlxuICogQGRlcHJlY2F0ZWQgQ29uc2lkZXIgdXNpbmcgdGhlIGBob29rT3B0aW9uc2AgZnVuY3Rpb24gaW5zdGVhZC5cbiAqL1xuZXhwb3J0IGNvbnN0IEhPT0tfT1BUSU9OUyA9IG5ldyBJbmplY3Rpb25Ub2tlbjxFeHRlbnNpb25GYWN0b3J5PEFwcGxpY2F0aW9uT3B0aW9ucz4+KFxuICAnSE9PS19PUFRJT05TJ1xuKTtcblxuLyoqXG4gKiBZb3UgY2FuIGVpdGhlciBwcm92aWRlIGEgc2luZ2xlIGBBcHBsaWNhdGlvbk9wdGlvbnNgIGFzIHBhcmFtZXRlcjpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqICBob29rT3B0aW9ucyguLi4pXG4gKiBgYGBcbiAqXG4gKiBPciBhbiBhcnJheSB0byBkaXJlY3RseSByZWdpc3RlciBtdWx0aXBsZTpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqICBob29rT3B0aW9ucyhbLi4uXSlcbiAqIGBgYFxuICpcbiAqIE9yIHlvdSBwcm92aWRlIGFuIFNlcnZpY2UgdGhhdCBpbXBsZW1lbnRzIGBFeHRlbnNpb25GYWN0b3J5PEFwcGxpY2F0aW9uT3B0aW9ucz5gXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAgZXhwb3J0IGNsYXNzIE15QXBwbGljYXRpb25PcHRpb25zRmFjdG9yeSBpbXBsZW1lbnRzIEV4dGVuc2lvbkZhY3Rvcnk8QXBwbGljYXRpb25PcHRpb25zPiB7Li4ufVxuICogIC4uLlxuICogIGhvb2tPcHRpb25zKE15QXBwbGljYXRpb25PcHRpb25zRmFjdG9yeSlcbiAqIGBgYFxuICogQSB0eXBlZCBhbHRlcm5hdGl2ZSB0byBgSE9PS19PUFRJT05TYC5cbiAqIEBwYXJhbSBvcHRpb25zIFRoZSBgQXBwbGljYXRpb25PcHRpb25zYCdzIG9yIGBFeHRlbnNpb25GYWN0b3J5YCB0byBiZSBwcm92aWRlZC5cbiAqIEByZXR1cm5zIEFuIGBQcm92aWRlcmAgdG8gYmUgcHJvdmlkZWQgaW4geW91ciBtb2R1bGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBob29rT3B0aW9ucyhcbiAgb3B0aW9uczogR2VuZXJpY0hvb2tUeXBlPEFwcGxpY2F0aW9uT3B0aW9ucz4sXG4gIGhvb2tPcHRpb25zPzogUGFydGlhbDxHZW5lcmljSG9va09wdGlvbnM+XG4pIHtcbiAgcmV0dXJuIGhvb2tHZW5lcmljPEFwcGxpY2F0aW9uT3B0aW9ucz4ob3B0aW9ucywgSE9PS19PUFRJT05TLCBob29rT3B0aW9ucyk7XG59XG5cbi8qKlxuICogQSBzZXJ2aWNlIHRoYXQgYWxsb3dzIHRvIHNldCBvciBnZXQgYXBwbGljYXRpb24gb3B0aW9uc1xuICogd2hpY2ggY29uZmlndXJlIHRoZSBkZWZhdWx0IGJlaGF2aW9yIG9mIHRoZSBVSS5cbiAqL1xuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiAncm9vdCcgfSlcbmV4cG9ydCBjbGFzcyBPcHRpb25zU2VydmljZSBleHRlbmRzIEFwcGxpY2F0aW9uT3B0aW9ucyB7XG4gIG9wdGlvbnNVcGRhdGVkJDogT2JzZXJ2YWJsZTx2b2lkPjtcbiAgW2tleTogc3RyaW5nXTogYW55O1xuICBwcml2YXRlIF9vcHRpb25zVXBkYXRlZCQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICBjb25zdHJ1Y3RvcihcbiAgICBAT3B0aW9uYWwoKSBASW5qZWN0KEhPT0tfT1BUSU9OUykgb3B0aW9ucyxcbiAgICBwcml2YXRlIHN5c3RlbU9wdGlvbnNTZXJ2aWNlOiBTeXN0ZW1PcHRpb25zU2VydmljZSxcbiAgICBwcml2YXRlIHRlbmFudE9wdGlvblNlcnZpY2U6IFRlbmFudE9wdGlvbnNTZXJ2aWNlXG4gICkge1xuICAgIHN1cGVyKCk7XG4gICAgdGhpcy5vcHRpb25zVXBkYXRlZCQgPSB0aGlzLl9vcHRpb25zVXBkYXRlZCQuYXNPYnNlcnZhYmxlKCk7XG4gICAgdGhpcy5zZXR1cE9wdGlvbnMob3B0aW9ucyk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhbiBhcHBsaWNhdGlvbiBvcHRpb24gdXNlZCB0byBjb25maWd1cmUgdGhlIFVJLlxuICAgKiBAcGFyYW0gb3B0aW9uS2V5IFRoZSBhcHBsaWNhdGlvbiBvcHRpb25zIGtleS5cbiAgICogQHBhcmFtIGRlZmF1bHRWYWx1ZSBBIHZhbHVlIHRvIHJldHVybiBpZiBub24gaXMgc2V0LlxuICAgKiBAcGFyYW0gYXR0ZW1wdFBhcnNlIEluZGljYXRlcyB3aGV0aGVyIHRoZSB2YWx1ZSBzaG91bGQgYmUgcGFyc2VkIHdpdGggSlNPTi5wYXJzZS5cbiAgICovXG4gIGdldDxUIGV4dGVuZHMga2V5b2YgT3B0aW9uc1NlcnZpY2U+KFxuICAgIG9wdGlvbktleTogVCxcbiAgICBkZWZhdWx0VmFsdWU/OiBPcHRpb25zU2VydmljZVtUXSxcbiAgICBhdHRlbXB0UGFyc2U/OiBib29sZWFuXG4gICk6IE9wdGlvbnNTZXJ2aWNlW1RdIHtcbiAgICBsZXQgdmFsdWUgPSB0aGlzW29wdGlvbktleV07XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHZhbHVlID0gdGhpc1tjYW1lbENhc2Uob3B0aW9uS2V5KV07XG4gICAgfVxuICAgIGlmIChhdHRlbXB0UGFyc2UpIHtcbiAgICAgIHJldHVybiB0aGlzLnBhcnNlT3B0aW9uUmF3VmFsdWUodmFsdWUsIGRlZmF1bHRWYWx1ZSk7XG4gICAgfVxuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgIT09ICd1bmRlZmluZWQnID8gdmFsdWUgOiBkZWZhdWx0VmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhbiBvYnNlcnZhYmxlIG9mIGFuIGFwcGxpY2F0aW9uIG9wdGlvbiB1c2VkIHRvIGNvbmZpZ3VyZSB0aGUgVUkuXG4gICAqIEBwYXJhbSBvcHRpb25LZXkgVGhlIGFwcGxpY2F0aW9uIG9wdGlvbnMga2V5LlxuICAgKiBAcGFyYW0gZGVmYXVsdFZhbHVlIEEgdmFsdWUgdG8gcmV0dXJuIGlmIG5vbiBpcyBzZXQuXG4gICAqIEBwYXJhbSBhdHRlbXB0UGFyc2UgSW5kaWNhdGVzIHdoZXRoZXIgdGhlIHZhbHVlIHNob3VsZCBiZSBwYXJzZWQgd2l0aCBKU09OLnBhcnNlLlxuICAgKi9cbiAgZ2V0JDxUIGV4dGVuZHMga2V5b2YgT3B0aW9uc1NlcnZpY2U+KFxuICAgIG9wdGlvbktleTogVCxcbiAgICBkZWZhdWx0VmFsdWU/OiBPcHRpb25zU2VydmljZVtUXSxcbiAgICBhdHRlbXB0UGFyc2U/OiBib29sZWFuXG4gICk6IE9ic2VydmFibGU8T3B0aW9uc1NlcnZpY2VbVF0+IHtcbiAgICBjb25zdCBmbiA9ICgpID0+IHRoaXMuZ2V0KG9wdGlvbktleSwgZGVmYXVsdFZhbHVlLCBhdHRlbXB0UGFyc2UpO1xuICAgIHJldHVybiB0aGlzLm9wdGlvbnNVcGRhdGVkJC5waXBlKG1hcChmbiksIHN0YXJ0V2l0aChmbigpKSwgZGlzdGluY3RVbnRpbENoYW5nZWQoKSk7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBhbiBhcHBsaWNhdGlvbiBvcHRpb24uXG4gICAqIEBwYXJhbSBrZXkgVGhlIGtleSB0byBzZXQuXG4gICAqIEBwYXJhbSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0LlxuICAgKi9cbiAgc2V0PFQgZXh0ZW5kcyBrZXlvZiBPcHRpb25zU2VydmljZT4oa2V5OiBULCB2YWx1ZTogT3B0aW9uc1NlcnZpY2VbVF0pIHtcbiAgICBjb25zdCBjYW1lbENhc2VkS2V5ID0gY2FtZWxDYXNlKGtleSk7XG4gICAgY29uc3QgcHJldmlvdXNWYWx1ZSA9IHRoaXNbY2FtZWxDYXNlZEtleV07XG4gICAgdGhpc1tjYW1lbENhc2VkS2V5XSA9IHZhbHVlO1xuICAgIGlmICghaXNFcXVhbChwcmV2aW91c1ZhbHVlLCB2YWx1ZSkpIHtcbiAgICAgIHRoaXMuX29wdGlvbnNVcGRhdGVkJC5uZXh0KCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZXMgYW4gYXBwbGljYXRpb24gb3B0aW9uLlxuICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgdG8gcmVtb3ZlLlxuICAgKi9cbiAgZGVsZXRlPFQgZXh0ZW5kcyBrZXlvZiBPcHRpb25zU2VydmljZT4oa2V5OiBUKSB7XG4gICAgY29uc3QgY2FtZWxDYXNlZEtleSA9IGNhbWVsQ2FzZShrZXkpO1xuICAgIGNvbnN0IHByZXZpb3VzVmFsdWUgPSB0aGlzW2NhbWVsQ2FzZWRLZXldO1xuICAgIGRlbGV0ZSB0aGlzW2NhbWVsQ2FzZWRLZXldO1xuICAgIGNvbnN0IG5ld1ZhbHVlID0gdGhpc1tjYW1lbENhc2VkS2V5XTtcblxuICAgIGlmICghaXNFcXVhbChwcmV2aW91c1ZhbHVlLCBuZXdWYWx1ZSkpIHtcbiAgICAgIHRoaXMuX29wdGlvbnNVcGRhdGVkJC5uZXh0KCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgc3VwcG9ydCBVUkwgZnJvbTpcbiAgICogLSBhcHBsaWNhdGlvbiBvcHRpb24gYHN1cHBvcnRVcmxgLFxuICAgKiAtIG9yIGN1cnJlbnQgdGVuYW50J3Mgb3B0aW9uIGBjb25maWd1cmF0aW9uIC8gc3lzdGVtLnN1cHBvcnQudXJsYCxcbiAgICogLSBvciBjdXJyZW50IHRlbmFudCdzIGluaGVyaXRlZCBvcHRpb24gYGNvbmZpZ3VyYXRpb24gLyBzeXN0ZW0uc3VwcG9ydC51cmxgLFxuICAgKiAtIG9yIHN5c3RlbSBvcHRpb24gYGNvbmZpZ3VyYXRpb24gLyBzeXN0ZW0uc3VwcG9ydC51cmxgLFxuICAgKiAtIG90aGVyd2lzZSBkZWZhdWx0cyB0byBgZmFsc2VgLlxuICAgKlxuICAgKiBAcmV0dXJucyBSZXR1cm5zIHN1cHBvcnQgdXJsIG9yIGZhbHNlLlxuICAgKi9cbiAgYXN5bmMgZ2V0U3VwcG9ydFVybCgpIHtcbiAgICBsZXQgdXJsOiBzdHJpbmcgfCBib29sZWFuID0gdGhpcy5zdXBwb3J0VXJsO1xuXG4gICAgaWYgKGlzVW5kZWZpbmVkKHVybCkpIHtcbiAgICAgIHVybCA9IGF3YWl0IHRoaXMuZ2V0Q3VycmVudFRlbmFudE9wdGlvbignY29uZmlndXJhdGlvbicsICdzeXN0ZW0uc3VwcG9ydC51cmwnKTtcbiAgICB9XG4gICAgaWYgKGlzVW5kZWZpbmVkKHVybCkpIHtcbiAgICAgIHVybCA9IGF3YWl0IHRoaXMuZ2V0SW5oZXJpdGVkVGVuYW50T3B0aW9uKCdjb25maWd1cmF0aW9uJywgJ3N5c3RlbS5zdXBwb3J0LnVybCcpO1xuICAgIH1cbiAgICBpZiAoaXNVbmRlZmluZWQodXJsKSkge1xuICAgICAgdXJsID0gKGF3YWl0IHRoaXMuZ2V0U3lzdGVtT3B0aW9uKCdzdXBwb3J0JywgJ3VybCcpKSB8fCBmYWxzZTtcbiAgICB9XG5cbiAgICB0aGlzLnN1cHBvcnRVcmwgPSB1cmw7XG4gICAgcmV0dXJuIHRoaXMuc3VwcG9ydFVybDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGlmIHRoZSB0ZW5hbnQgYWxsb3dzIHRvIHNob3cgdGhlIGFjdGl2YXRlLXN1cHBvcnQgdXNlciBtZW51IGVudHJ5LlxuICAgKiBOb3RlOiBPbmx5IGlmIHN5c3RlbS1sZXZlbCBzdXBwb3J0LXVzZXIvZW5hYmxlZCBpcyBmYWxzZSB3ZSBjYW4gYWN0aXZhdGUgaXQgYXQgdGVuYW50IGxldmVsLlxuICAgKi9cbiAgYXN5bmMgZ2V0QWN0aXZhdGVTdXBwb3J0VXNlcigpIHtcbiAgICBjb25zdCBvcHRpb24gPSBhd2FpdCB0aGlzLmdldFN5c3RlbU9wdGlvbignc3VwcG9ydC11c2VyJywgJ2VuYWJsZWQnLCB0cnVlKTtcbiAgICByZXR1cm4gIW9wdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIGEgdmFsdWUgZnJvbSB0aGUgc3lzdGVtIHNlcnZpY2UgYW5kIHBhcnNlcyBpdC5cbiAgICpcbiAgICogQHBhcmFtIGNhdGVnb3J5IFRoZSBjYXRlZ29yeSBmb3IgdGhpcyBvcHRpb24uXG4gICAqIEBwYXJhbSBrZXkgVGhlIGtleSBmb3IgdGhhdCBvcHRpb24uXG4gICAqIEBwYXJhbSBkZWZhdWx0VmFsdWUgVGhlIGRlZmF1bHQgaWYgdGhlIG9wdGlvbiB3YXMgbm90IGZvdW5kLlxuICAgKi9cbiAgYXN5bmMgZ2V0U3lzdGVtT3B0aW9uPFQgPSBzdHJpbmc+KFxuICAgIGNhdGVnb3J5OiBzdHJpbmcsXG4gICAga2V5OiBzdHJpbmcsXG4gICAgZGVmYXVsdFZhbHVlPzogVFxuICApOiBQcm9taXNlPFQgfCBzdHJpbmc+IHtcbiAgICByZXR1cm4gdGhpcy5nZXRPcHRpb25Gcm9tU2VydmljZTxUPihcbiAgICAgIGNhdGVnb3J5LFxuICAgICAga2V5LFxuICAgICAgbnVsbCxcbiAgICAgIHRoaXMuc3lzdGVtT3B0aW9uc1NlcnZpY2UsXG4gICAgICBkZWZhdWx0VmFsdWVcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgYSB2YWx1ZSBmcm9tIHRoZSB0ZW5hbnQgc2VydmljZSBhbmQgcGFyc2VzIGl0LlxuICAgKlxuICAgKiBAcGFyYW0gY2F0ZWdvcnkgVGhlIGNhdGVnb3J5IGZvciB0aGlzIG9wdGlvbi5cbiAgICogQHBhcmFtIGtleSBUaGUga2V5IGZvciB0aGF0IG9wdGlvbi5cbiAgICogQHBhcmFtIGRlZmF1bHRWYWx1ZSBUaGUgZGVmYXVsdCBpZiB0aGUgb3B0aW9uIHdhcyBub3QgZm91bmQuXG4gICAqL1xuICBhc3luYyBnZXRUZW5hbnRPcHRpb248VCA9IHN0cmluZz4oXG4gICAgY2F0ZWdvcnk6IHN0cmluZyxcbiAgICBrZXk6IHN0cmluZyxcbiAgICBkZWZhdWx0VmFsdWU/OiBUXG4gICk6IFByb21pc2U8VCB8IHN0cmluZz4ge1xuICAgIHJldHVybiB0aGlzLmdldE9wdGlvbkZyb21TZXJ2aWNlPFQ+KFxuICAgICAgY2F0ZWdvcnksXG4gICAgICBrZXksXG4gICAgICBudWxsLFxuICAgICAgdGhpcy50ZW5hbnRPcHRpb25TZXJ2aWNlLFxuICAgICAgZGVmYXVsdFZhbHVlXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIGFuIGluaGVyaXRlZCBmcm9tIHBhcmVudCB2YWx1ZSBmcm9tIHRoZSB0ZW5hbnQgc2VydmljZSBpZiBpbmhlcml0YW5jZSBzdXBwb3J0ZWQgYmFzZWQgb24gZ2l2ZW4gcGFyYW1ldGVycy5cbiAgICpcbiAgICogQHBhcmFtIGNhdGVnb3J5IFRoZSBjYXRlZ29yeSBmb3IgdGhpcyBvcHRpb24uXG4gICAqIEBwYXJhbSBrZXkgVGhlIGtleSBmb3IgdGhhdCBvcHRpb24uXG4gICAqIEBwYXJhbSBkZWZhdWx0VmFsdWUgVGhlIGRlZmF1bHQgaWYgdGhlIG9wdGlvbiB3YXMgbm90IGZvdW5kLlxuICAgKi9cbiAgYXN5bmMgZ2V0SW5oZXJpdGVkVGVuYW50T3B0aW9uPFQgPSBzdHJpbmc+KFxuICAgIGNhdGVnb3J5OiBzdHJpbmcsXG4gICAga2V5OiBzdHJpbmcsXG4gICAgZGVmYXVsdFZhbHVlPzogVFxuICApOiBQcm9taXNlPFQgfCBzdHJpbmc+IHtcbiAgICByZXR1cm4gdGhpcy5nZXRPcHRpb25Gcm9tU2VydmljZTxUPihcbiAgICAgIGNhdGVnb3J5LFxuICAgICAga2V5LFxuICAgICAgeyBldmFsdWF0ZTogJ2luaGVyaXRlZCcgfSxcbiAgICAgIHRoaXMudGVuYW50T3B0aW9uU2VydmljZSxcbiAgICAgIGRlZmF1bHRWYWx1ZVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyBjdXJyZW50IHRlbmFudCBvcHRpb24gdmFsdWUgZnJvbSB0aGUgdGVuYW50IHNlcnZpY2Ugb21pdHRpbmcgdGhlIGluaGVyaXRhbmNlIHN1cHBvcnRlZCBiYXNlZCBvbiBnaXZlbiBwYXJhbWV0ZXJzLlxuICAgKlxuICAgKiBAcGFyYW0gY2F0ZWdvcnkgVGhlIGNhdGVnb3J5IGZvciB0aGlzIG9wdGlvbi5cbiAgICogQHBhcmFtIGtleSBUaGUga2V5IGZvciB0aGF0IG9wdGlvbi5cbiAgICogQHBhcmFtIGRlZmF1bHRWYWx1ZSBUaGUgZGVmYXVsdCBpZiB0aGUgb3B0aW9uIHdhcyBub3QgZm91bmQuXG4gICAqL1xuICBhc3luYyBnZXRDdXJyZW50VGVuYW50T3B0aW9uPFQgPSBzdHJpbmc+KFxuICAgIGNhdGVnb3J5OiBzdHJpbmcsXG4gICAga2V5OiBzdHJpbmcsXG4gICAgZGVmYXVsdFZhbHVlPzogVFxuICApOiBQcm9taXNlPFQgfCBzdHJpbmc+IHtcbiAgICByZXR1cm4gdGhpcy5nZXRPcHRpb25Gcm9tU2VydmljZTxUPihcbiAgICAgIGNhdGVnb3J5LFxuICAgICAga2V5LFxuICAgICAgeyBldmFsdWF0ZTogJ2N1cnJlbnQnIH0sXG4gICAgICB0aGlzLnRlbmFudE9wdGlvblNlcnZpY2UsXG4gICAgICBkZWZhdWx0VmFsdWVcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXR1cE9wdGlvbnMob3B0aW9uczogYW55W10gfCBudWxsKSB7XG4gICAgaWYgKG9wdGlvbnMpIHtcbiAgICAgIGlmICghQXJyYXkuaXNBcnJheShvcHRpb25zKSkge1xuICAgICAgICBvcHRpb25zID0gW29wdGlvbnNdO1xuICAgICAgfVxuICAgICAgbGV0IGNvbWJpbmVkT3B0aW9ucyA9IHt9O1xuICAgICAgaWYgKG9wdGlvbnMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIGNvbWJpbmVkT3B0aW9ucyA9IG9wdGlvbnNbMF07XG4gICAgICB9IGVsc2UgaWYgKG9wdGlvbnMubGVuZ3RoID4gMSkge1xuICAgICAgICBvcHRpb25zLmZvckVhY2gob3B0aW9uTWFwID0+IHtcbiAgICAgICAgICBpZiAob3B0aW9uTWFwKSB7XG4gICAgICAgICAgICB0aGlzLmFwcGx5T3B0aW9ucyhvcHRpb25NYXAsIGNvbWJpbmVkT3B0aW9ucyk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLmFwcGx5T3B0aW9ucyhjb21iaW5lZE9wdGlvbnMsIHRoaXMpKSB7XG4gICAgICAgIHRoaXMuX29wdGlvbnNVcGRhdGVkJC5uZXh0KCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhcHBseU9wdGlvbnMob3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55PiwgYXBwbHlUbzogYW55KSB7XG4gICAgbGV0IG9wdGlvbldhc0NoYW5nZWQgPSBmYWxzZTtcbiAgICBPYmplY3QuZW50cmllcyhvcHRpb25zKS5mb3JFYWNoKChba2V5LCB2YWx1ZV0pID0+IHtcbiAgICAgIGNvbnN0IGNhbWVsQ2FzZWRLZXkgPSBjYW1lbENhc2Uoa2V5KTtcbiAgICAgIGNvbnN0IHByZXZpb3VzVmFsdWUgPSBhcHBseVRvW2NhbWVsQ2FzZWRLZXldO1xuICAgICAgYXBwbHlUb1tjYW1lbENhc2VkS2V5XSA9IHZhbHVlO1xuICAgICAgaWYgKCFpc0VxdWFsKHByZXZpb3VzVmFsdWUsIHZhbHVlKSkge1xuICAgICAgICBvcHRpb25XYXNDaGFuZ2VkID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gb3B0aW9uV2FzQ2hhbmdlZDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZ2V0T3B0aW9uRnJvbVNlcnZpY2U8VCA9IHN0cmluZz4oXG4gICAgY2F0ZWdvcnk6IHN0cmluZyxcbiAgICBrZXk6IHN0cmluZyxcbiAgICBmaWx0ZXI6IElUZW5hbnRPcHRpb25EZXRhaWxQYXJhbXMsXG4gICAgc2VydmljZTogU3lzdGVtT3B0aW9uc1NlcnZpY2UgfCBUZW5hbnRPcHRpb25zU2VydmljZSxcbiAgICBkZWZhdWx0VmFsdWU6IFRcbiAgKTogUHJvbWlzZTxUIHwgc3RyaW5nPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHsgZGF0YSB9ID0gYXdhaXQgc2VydmljZS5kZXRhaWwoeyBjYXRlZ29yeSwga2V5IH0sIGZpbHRlcik7XG4gICAgICByZXR1cm4gdGhpcy5wYXJzZU9wdGlvblJhd1ZhbHVlKGRhdGEudmFsdWUsIGRlZmF1bHRWYWx1ZSk7XG4gICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgIHJldHVybiBkZWZhdWx0VmFsdWU7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZU9wdGlvblJhd1ZhbHVlPFQgPSBzdHJpbmc+KHJhd1ZhbHVlOiBzdHJpbmcsIGRlZmF1bHRWYWx1ZTogVCk6IFQgfCBzdHJpbmcge1xuICAgIGxldCB2YWx1ZTogVCB8IHN0cmluZztcbiAgICB0cnkge1xuICAgICAgdmFsdWUgPSBKU09OLnBhcnNlKHJhd1ZhbHVlKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB2YWx1ZSA9IGlzVW5kZWZpbmVkKHJhd1ZhbHVlKSA/IGRlZmF1bHRWYWx1ZSA6IHJhd1ZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cbn1cbiJdfQ==