@alauda-fe/common
Version:
Alauda frontend team common codes.
394 lines • 53.6 kB
JavaScript
/**
* @packageDocumentation
* @module api
*/
import { HttpClient, HttpEventType, } from '@angular/common/http';
import { Inject, Injectable } from '@angular/core';
import { get, set } from 'lodash-es';
import { NEVER, Observable, combineLatest, from, of, throwError, filter, map, retryWhen, startWith, switchMap, concatMap, delay, distinctUntilChanged, } from 'rxjs';
import { API_GATEWAY, DOWNGRADE_WATCH_ENABLED, NOTIFY_ON_ERROR_HEADERS, NOT_NOTIFY_ON_ERROR_HEADERS, TRUE, } from '../core/constants/constants';
import { TOKEN_GLOBAL_NAMESPACE } from '../core/constants/tokens';
import { CRYPTO_HEADER_KEY, } from '../core/public-api';
import { METADATA, NAME, NAMESPACE } from '../core/services/public-api';
import { createPollObservable } from '../core/utils/observable';
import { isEqual, parseJSONStream } from '../core/utils/public-api';
import { normalizeParams } from '../k8s-resource-list/utils';
import { getApiPrefixParts, getMetadataHeaders, isResourceEvent, reduceWatchEvents, } from './helpers';
import { K8sApiResourceService } from './k8s-api-resource.service';
import { PageVisibilityService } from './page-visibility.service';
import { PatchOperation, WatchEvent, } from './types';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common/http";
import * as i2 from "./k8s-api-resource.service";
import * as i3 from "./page-visibility.service";
// 名称前缀 Erebus 参考 http://confluence.alauda.cn/pages/viewpage.action?pageId=44663484 指 /kubernetes/ 开头的 api 组件
export const TIMEOUT_SECONDS = 59;
export const SEARCH_URL_PREFIX = '/acp/v1/resources/search';
const RETRY_DELAY = 5000;
const RETRY_COUNT = 3;
export class K8sApiService {
constructor(http, k8sApiResource, pageVisibility, globalNamespace) {
this.http = http;
this.k8sApiResource = k8sApiResource;
this.pageVisibility = pageVisibility;
this.globalNamespace = globalNamespace;
// @internal
this._getHeaders = ({ notifyOnError, onlyMetadata, customAccept, crypto }, isList) => {
const headers = {};
if (typeof notifyOnError === 'boolean') {
Object.assign(headers, notifyOnError ? NOTIFY_ON_ERROR_HEADERS : NOT_NOTIFY_ON_ERROR_HEADERS);
}
if (crypto) {
Object.assign(headers, {
[CRYPTO_HEADER_KEY]: crypto,
});
}
/**
* @see https://github.com/kubernetes/design-proposals-archive/blob/main/api-machinery/alternate-api-representations.md
*/
if (onlyMetadata) {
Object.assign(headers, getMetadataHeaders(isList, customAccept));
}
return headers;
};
}
/**
* 获取 Global 集群单个资源对象
*/
getGlobalResource(params) {
return this._getResource(params);
}
/**
* 监听 Global 集群单个资源对象
*/
watchGlobalResource(params) {
return DOWNGRADE_WATCH_ENABLED && params.downgradePolling
? createPollObservable(this.getGlobalResource(params), this._getDowngradePolling(params)).pipe(distinctUntilChanged((a, b) => isEqual(a, b)))
: this._watchResource(params);
}
/**
* 监听 Global 集群资源列表变化
*/
watchGlobalResourceChange(seedVersion, params) {
return this._keepWatchResourceChange(seedVersion, params);
}
/**
* 获取 Global 集群资源对象列表,包含分页信息
*/
getGlobalResourceList(params) {
return this._getResourceList(params);
}
/**
* 创建 Global 集群资源
*/
postGlobalResource(params) {
return this._postResource(params);
}
/**
* 完整覆盖更新 Global 集群单个资源对象
*/
putGlobalResource(params) {
return this._putResource(params);
}
/**
* 增量更新 Global 集群单个资源对象的部分属性
*/
patchGlobalResource(params) {
return this._patchResource(params);
}
/**
* 删除 Global 集群单个资源
*/
deleteGlobalResource(params) {
return this._deleteResource(params);
}
/**
* 获取业务集群单个资源对象
*/
getResource(params) {
return this._getResource(params);
}
/**
* 监听业务集群单个资源对象
*/
watchResource(params) {
return DOWNGRADE_WATCH_ENABLED && params.downgradePolling
? createPollObservable(this._getResource(params), this._getDowngradePolling(params)).pipe(distinctUntilChanged((a, b) => isEqual(a, b)))
: this._watchResource(params);
}
/**
* 监听资源列表变化
*/
watchResourceChange(seedVersion, params) {
return this._keepWatchResourceChange(seedVersion, params);
}
/**
* 获取业务集群资源对象列表,包含分页信息
*/
getResourceList(params) {
return this._getResourceList(params);
}
/**
* 创建业务集群资源
*/
postResource(params) {
return this._postResource(params);
}
/**
* 完整覆盖更新业务集群单个资源对象
*/
putResource(params) {
return this._putResource(params);
}
/**
* 增量更新业务集群单个资源对象的部分属性
*/
patchResource(params) {
return this._patchResource(params);
}
/**
* 删除业务集群单个资源
*/
deleteResource(params) {
if ('name' in params && !params.name) {
return throwError(() => new Error('delete resource need resource name'));
}
return this._deleteResource(params);
}
/**
* 批量删除业务集群的资源
*/
batchDeleteResource(params) {
return this._batchDeleteResource(params);
}
// @internal
_getResourceDefinition(params) {
const definition = this.k8sApiResource.getDefinition('definition' in params && params.definition
? params.definition
: 'type' in params && params.type);
if ('resource' in params && params.resource) {
return {
type: definition.type,
...getApiPrefixParts(params.resource.apiVersion),
};
}
return definition;
}
// @internal
_getApiPath(params, ignoreName = false) {
return this.k8sApiResource.getApiPath({
...this._getResourceDefinition(params),
cluster: 'cluster' in params && params.cluster,
namespace: this._getNamespace(params),
name: ignoreName ? null : this._getName(params),
});
}
// @internal
_getNamespace(params) {
return 'namespace' in params && params.namespace
? params.namespace
: 'namespaced' in params && params.namespaced
? this.globalNamespace
: 'resource' in params && get(params.resource, [METADATA, NAMESPACE]);
}
// @internal
_getName(params) {
return 'name' in params
? params.name
: 'resource' in params && get(params.resource, [METADATA, NAME]);
}
/**
* k8s list api 返回的结果里,items 缺失 kind 和 apiVersion 字段
* 规则如 Service 类型对应 kind: ServiceList,去掉最后四个字符可得到资源的 kind
* @internal
*/
_getNormalizedList(list) {
const { apiVersion, items } = list;
if (!items || items.length === 0) {
return {
...list,
items: [],
};
}
const kind = list.kind.slice(0, -4);
return {
...list,
items: items.map(item => ({
// key 顺序会影响转 yaml 后的顺序
kind,
apiVersion,
...item,
})),
};
}
// @internal
_getResource(params) {
return this.http.get(this._getApiPath(params), {
headers: this._getHeaders(params),
});
}
// @internal
_watchResource(params) {
const detailParams = {
...params,
queryParams: { fieldSelector: 'metadata.name=' + this._getName(params) },
};
const defaultRetry = {
count: RETRY_COUNT,
delay: RETRY_DELAY,
};
const { count, delay: delayTime } = params.retry === true
? {
...defaultRetry,
count: Infinity,
}
: {
...defaultRetry,
...params.retry,
};
let soFar = 0;
return this._getResourceList(detailParams).pipe(switchMap(list => this._keepWatchResourceChange(list.metadata.resourceVersion, detailParams).pipe(filter(isResourceEvent), map(res => (res.type === WatchEvent.Deleted ? null : res.object)), startWith(list.items[0] ?? null))), retryWhen(err$ => err$.pipe(switchMap(err => {
if (err === WatchEvent.Error || (count && soFar++ < count)) {
return of(err).pipe(delay(count ? delayTime : 0));
}
return throwError(() => err);
}))));
}
// @internal
_keepWatchResourceChange(seedVersion, params) {
let resourceVersion = seedVersion;
let sub;
const watch$ = new Observable(observer => {
const unsubscribe = () => {
if (sub && !sub.closed) {
sub.unsubscribe();
}
};
const watch = () => {
unsubscribe();
sub = this._watchResourceChange({
...params,
queryParams: normalizeParams({
...params.queryParams,
watch: TRUE,
allowWatchBookmarks: TRUE,
timeoutSeconds: String(TIMEOUT_SECONDS),
resourceVersion,
}),
}).subscribe({
next(res) {
if (res.type === WatchEvent.Error) {
observer.error(res.type);
return;
}
resourceVersion = res.object.metadata.resourceVersion;
observer.next(res);
},
error(err) {
observer.error(err);
},
complete: watch,
});
};
watch();
return unsubscribe;
});
return params.keepalive
? watch$
: combineLatest([
this.pageVisibility.getPageVisibility(),
params.active$ || of(true),
]).pipe(switchMap(([visible, active]) => visible && active ? watch$ : NEVER));
}
// @internal
_watchResourceChange(params) {
return this.http
.get(this._getApiPath(params, true), {
responseType: 'text',
observe: 'events',
reportProgress: true,
headers: this._getHeaders(params),
params: params.queryParams,
})
.pipe(filter(ev => ev.type === HttpEventType.DownloadProgress), filter(({ partialText }) => !!partialText?.trim()), concatMap(({ partialText }) => from(reduceWatchEvents(parseJSONStream(partialText)))));
}
// @internal
_getResourceList(params) {
// 包含 keyword 前缀需要加上前缀 'acp/v1/resources/search'
// 参考 http://confluence.alauda.cn/pages/viewpage.action?pageId=48731058
let url = this._getApiPath(params, true);
const queryParams = { ...params.queryParams };
if (queryParams.keyword) {
url = url.replace(API_GATEWAY, `${API_GATEWAY}${SEARCH_URL_PREFIX}`);
if (!queryParams.field) {
queryParams.field = 'metadata.name';
}
}
return this.http
.get(url, {
params: queryParams,
headers: this._getHeaders(params, true),
})
.pipe(map(this._getNormalizedList));
}
// @internal
_postResource(params) {
if (('namespace' in params && params.namespace) ||
('namespaced' in params && params.namespaced)) {
const resourceNamespace = get(params.resource, [METADATA, NAMESPACE]);
if (!resourceNamespace) {
set(params.resource, [METADATA, NAMESPACE], params.namespace || this.globalNamespace);
}
}
return this.http.post(this._getApiPath(params, true), params.resource, {
headers: this._getHeaders(params),
});
}
// @internal
_putResource(params) {
return this.http.put(this._getApiPath(params), params.resource, {
headers: this._getHeaders(params),
});
}
// @internal
_patchResource(params) {
return this.http.patch(this._getApiPath(params), params.part, {
headers: {
...this._getHeaders(params),
'Content-Type': params.operation || PatchOperation.Merge,
},
});
}
// @internal
_deleteResource(params) {
return this.http.request('delete', this._getApiPath(params), {
headers: this._getHeaders(params),
body: params.body,
});
}
// @internal
_batchDeleteResource(params) {
return this.http.request('delete', this._getApiPath(params), {
headers: this._getHeaders(params),
body: params.body,
params: params.queryParams,
});
}
_getDowngradePolling({ keepalive, downgradePolling, }) {
return keepalive
? downgradePolling
: this.pageVisibility
.getPageVisibility()
.pipe(map(visible => (visible ? downgradePolling : 0)));
}
static { this.ɵfac = function K8sApiService_Factory(t) { return new (t || K8sApiService)(i0.ɵɵinject(i1.HttpClient), i0.ɵɵinject(i2.K8sApiResourceService), i0.ɵɵinject(i3.PageVisibilityService), i0.ɵɵinject(TOKEN_GLOBAL_NAMESPACE)); }; }
static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: K8sApiService, factory: K8sApiService.ɵfac, providedIn: 'root' }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(K8sApiService, [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], () => [{ type: i1.HttpClient }, { type: i2.K8sApiResourceService }, { type: i3.PageVisibilityService }, { type: undefined, decorators: [{
type: Inject,
args: [TOKEN_GLOBAL_NAMESPACE]
}] }], null); })();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiazhzLWFwaS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vbGlicy9jb21tb24vc3JjL2FwaS9rOHMtYXBpLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBRUgsT0FBTyxFQUNMLFVBQVUsRUFFVixhQUFhLEdBQ2QsTUFBTSxzQkFBc0IsQ0FBQztBQUM5QixPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNuRCxPQUFPLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNyQyxPQUFPLEVBQ0wsS0FBSyxFQUNMLFVBQVUsRUFFVixhQUFhLEVBQ2IsSUFBSSxFQUNKLEVBQUUsRUFDRixVQUFVLEVBQ1YsTUFBTSxFQUNOLEdBQUcsRUFDSCxTQUFTLEVBQ1QsU0FBUyxFQUNULFNBQVMsRUFDVCxTQUFTLEVBQ1QsS0FBSyxFQUNMLG9CQUFvQixHQUNyQixNQUFNLE1BQU0sQ0FBQztBQUVkLE9BQU8sRUFDTCxXQUFXLEVBQ1gsdUJBQXVCLEVBQ3ZCLHVCQUF1QixFQUN2QiwyQkFBMkIsRUFDM0IsSUFBSSxHQUNMLE1BQU0sNkJBQTZCLENBQUM7QUFDckMsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDbEUsT0FBTyxFQUNMLGlCQUFpQixHQUlsQixNQUFNLG9CQUFvQixDQUFDO0FBQzVCLE9BQU8sRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ3hFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDcEUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRTdELE9BQU8sRUFDTCxpQkFBaUIsRUFD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QUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDaEUsQ0FBQzs4RUE5ZlUsYUFBYSx3SEFLZCxzQkFBc0I7dUVBTHJCLGFBQWEsV0FBYixhQUFhLG1CQURBLE1BQU07O2lGQUNuQixhQUFhO2NBRHpCLFVBQVU7ZUFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUU7O3NCQU03QixNQUFNO3VCQUFDLHNCQUFzQiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG4gKiBAbW9kdWxlIGFwaVxuICovXG5cbmltcG9ydCB7XG4gIEh0dHBDbGllbnQsXG4gIEh0dHBEb3dubG9hZFByb2dyZXNzRXZlbnQsXG4gIEh0dHBFdmVudFR5cGUsXG59IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IEluamVjdCwgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgZ2V0LCBzZXQgfSBmcm9tICdsb2Rhc2gtZXMnO1xuaW1wb3J0IHtcbiAgTkVWRVIsXG4gIE9ic2VydmFibGUsXG4gIFN1YnNjcmlwdGlvbixcbiAgY29tYmluZUxhdGVzdCxcbiAgZnJvbSxcbiAgb2YsXG4gIHRocm93RXJyb3IsXG4gIGZpbHRlcixcbiAgbWFwLFxuICByZXRyeVdoZW4sXG4gIHN0YXJ0V2l0aCxcbiAgc3dpdGNoTWFwLFxuICBjb25jYXRNYXAsXG4gIGRlbGF5LFxuICBkaXN0aW5jdFVudGlsQ2hhbmdlZCxcbn0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7XG4gIEFQSV9HQVRFV0FZLFxuICBET1dOR1JBREVfV0FUQ0hfRU5BQkxFRCxcbiAgTk9USUZZX09OX0VSUk9SX0hFQURFUlMsXG4gIE5PVF9OT1RJRllfT05fRVJST1JfSEVBREVSUyxcbiAgVFJVRSxcbn0gZnJvbSAnLi4vY29yZS9jb25zdGFudHMvY29uc3RhbnRzJztcbmltcG9ydCB7IFRPS0VOX0dMT0JBTF9OQU1FU1BBQ0UgfSBmcm9tICcuLi9jb3JlL2NvbnN0YW50cy90b2tlbnMnO1xuaW1wb3J0IHtcbiAgQ1JZUFRPX0hFQURFUl9LRVksXG4gIEt1YmVybmV0ZXNSZXNvdXJjZSxcbiAgS3ViZXJuZXRlc1Jlc291cmNlTGlzdCxcbiAgU3RhdHVzLFxufSBmcm9tICcuLi9jb3JlL3B1YmxpYy1hcGknO1xuaW1wb3J0IHsgTUVUQURBVEEsIE5BTUUsIE5BTUVTUEFDRSB9IGZyb20gJy4uL2NvcmUvc2VydmljZXMvcHVibGljLWFwaSc7XG5pbXBvcnQgeyBjcmVhdGVQb2xsT2JzZXJ2YWJsZSB9IGZyb20gJy4uL2NvcmUvdXRpbHMvb2JzZXJ2YWJsZSc7XG5pbXBvcnQgeyBpc0VxdWFsLCBwYXJzZUpTT05TdHJlYW0gfSBmcm9tICcuLi9jb3JlL3V0aWxzL3B1YmxpYy1hcGknO1xuaW1wb3J0IHsgbm9ybWFsaXplUGFyYW1zIH0gZnJvbSAnLi4vazhzLXJlc291cmNlLWxpc3QvdXRpbHMnO1xuXG5pbXBvcnQge1xuICBnZXRBcGlQcmVmaXhQYXJ0cyxcbiAgZ2V0TWV0YWRhdGFIZWFkZXJzLFxuICBpc1Jlc291cmNlRXZlbnQsXG4gIHJlZHVjZVdhdGNoRXZlbnRzLFxufSBmcm9tICcuL2hlbHBlcnMnO1xuaW1wb3J0IHsgSzhzQXBpUmVzb3VyY2VTZXJ2aWNlIH0gZnJvbSAnLi9rOHMtYXBpLXJlc291cmNlLnNlcnZpY2UnO1xuaW1wb3J0IHsgUGFnZVZpc2liaWxpdHlTZXJ2aWNlIH0gZnJvbSAnLi9wYWdlLXZpc2liaWxpdHkuc2VydmljZSc7XG5pbXBvcnQge1xuICBBcGlCYXNlUGFyYW1zLFxuICBFcmVidXNSZXNvdXJjZURlbGV0ZVBhcmFtcyxcbiAgRXJlYnVzUmVzb3VyY2VMaXN0UGFyYW1zLFxuICBFcmVidXNSZXNvdXJjZVBhcmFtcyxcbiAgRXJlYnVzUmVzb3VyY2VQYXRjaFBhcmFtcyxcbiAgRXJlYnVzUmVzb3VyY2VXcml0ZVBhcmFtcyxcbiAgR2xvYmFsUmVzb3VyY2VEZWxldGVQYXJhbXMsXG4gIEdsb2JhbFJlc291cmNlTGlzdFBhcmFtcyxcbiAgR2xvYmFsUmVzb3VyY2VQYXJhbXMsXG4gIEdsb2JhbFJlc291cmNlUGF0Y2hQYXJhbXMsXG4gIEdsb2JhbFJlc291cmNlV3JpdGVQYXJhbXMsXG4gIFBhdGNoT3BlcmF0aW9uLFxuICBSZXNvdXJjZUFwaVBhcmFtcyxcbiAgUmVzb3VyY2VEZWxldGVQYXJhbXMsXG4gIFJlc291cmNlTGlzdFJlYWRQYXJhbXMsXG4gIFJlc291cmNlUGF0Y2hQYXJhbXMsXG4gIFJlc291cmNlUmVhZFBhcmFtcyxcbiAgUmVzb3VyY2VXcml0ZVBhcmFtcyxcbiAgV2F0Y2hBUElSZXNwb25zZSxcbiAgV2F0Y2hBcGlQYXJhbXMsXG4gIFdhdGNoRXJlYnVzUmVzb3VyY2VMaXN0UGFyYW1zLFxuICBXYXRjaEVyZWJ1c1Jlc291cmNlUGFyYW1zLFxuICBXYXRjaEV2ZW50LFxuICBXYXRjaEdsb2JhbFJlc291cmNlTGlzdFBhcmFtcyxcbiAgV2F0Y2hHbG9iYWxSZXNvdXJjZVBhcmFtcyxcbiAgV2F0Y2hSZXNvdXJjZUxpc3RSZWFkUGFyYW1zLFxuICBXYXRjaFJlc291cmNlUmVhZFBhcmFtcyxcbiAgRXJlYnVzUmVzb3VyY2VCYXRjaERlbGV0ZVBhcmFtcyxcbn0gZnJvbSAnLi90eXBlcyc7XG5cbi8vIOWQjeensOWJjee8gCBFcmVidXMg5Y+C6ICDIGh0dHA6Ly9jb25mbHVlbmNlLmFsYXVkYS5jbi9wYWdlcy92aWV3cGFnZS5hY3Rpb24/cGFnZUlkPTQ0NjYzNDg0IOaMhyAva3ViZXJuZXRlcy8g5byA5aS055qEIGFwaSDnu4Tku7ZcblxuZXhwb3J0IGNvbnN0IFRJTUVPVVRfU0VDT05EUyA9IDU5O1xuZXhwb3J0IGNvbnN0IFNFQVJDSF9VUkxfUFJFRklYID0gJy9hY3AvdjEvcmVzb3VyY2VzL3NlYXJjaCc7XG5cbmNvbnN0IFJFVFJZX0RFTEFZID0gNTAwMDtcblxuY29uc3QgUkVUUllfQ09VTlQgPSAzO1xuXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIEs4c0FwaVNlcnZpY2U8UiBleHRlbmRzIHN0cmluZyA9IHN0cmluZz4ge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IGh0dHA6IEh0dHBDbGllbnQsXG4gICAgcHJpdmF0ZSByZWFkb25seSBrOHNBcGlSZXNvdXJjZTogSzhzQXBpUmVzb3VyY2VTZXJ2aWNlLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgcGFnZVZpc2liaWxpdHk6IFBhZ2VWaXNpYmlsaXR5U2VydmljZSxcbiAgICBASW5qZWN0KFRPS0VOX0dMT0JBTF9OQU1FU1BBQ0UpIHByaXZhdGUgcmVhZG9ubHkgZ2xvYmFsTmFtZXNwYWNlOiBzdHJpbmcsXG4gICkge31cblxuICAvKipcbiAgICog6I635Y+WIEdsb2JhbCDpm4bnvqTljZXkuKrotYTmupDlr7nosaFcbiAgICovXG4gIGdldEdsb2JhbFJlc291cmNlPFQgZXh0ZW5kcyBLdWJlcm5ldGVzUmVzb3VyY2U+KFxuICAgIHBhcmFtczogR2xvYmFsUmVzb3VyY2VQYXJhbXM8Uj4sXG4gICkge1xuICAgIHJldHVybiB0aGlzLl9nZXRSZXNvdXJjZTxUPihwYXJhbXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIOebkeWQrCBHbG9iYWwg6ZuG576k5Y2V5Liq6LWE5rqQ5a+56LGhXG4gICAqL1xuICB3YXRjaEdsb2JhbFJlc291cmNlPFQgZXh0ZW5kcyBLdWJlcm5ldGVzUmVzb3VyY2U+KFxuICAgIHBhcmFtczogV2F0Y2hHbG9iYWxSZXNvdXJjZVBhcmFtczxSPixcbiAgKSB7XG4gICAgcmV0dXJuIERPV05HUkFERV9XQVRDSF9FTkFCTEVEICYmIHBhcmFtcy5kb3duZ3JhZGVQb2xsaW5nXG4gICAgICA/IGNyZWF0ZVBvbGxPYnNlcnZhYmxlPFQ+KFxuICAgICAgICAgIHRoaXMuZ2V0R2xvYmFsUmVzb3VyY2UocGFyYW1zKSxcbiAgICAgICAgICB0aGlzLl9nZXREb3duZ3JhZGVQb2xsaW5nKHBhcmFtcyksXG4gICAgICAgICkucGlwZShkaXN0aW5jdFVudGlsQ2hhbmdlZCgoYSwgYikgPT4gaXNFcXVhbChhLCBiKSkpXG4gICAgICA6IHRoaXMuX3dhdGNoUmVzb3VyY2U8VD4ocGFyYW1zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDnm5HlkKwgR2xvYmFsIOmbhue+pOi1hOa6kOWIl+ihqOWPmOWMllxuICAgKi9cbiAgd2F0Y2hHbG9iYWxSZXNvdXJjZUNoYW5nZTxUIGV4dGVuZHMgS3ViZXJuZXRlc1Jlc291cmNlPihcbiAgICBzZWVkVmVyc2lvbjogc3RyaW5nLFxuICAgIHBhcmFtczogV2F0Y2hHbG9iYWxSZXNvdXJjZUxpc3RQYXJhbXM8Uj4sXG4gICkge1xuICAgIHJldHVybiB0aGlzLl9rZWVwV2F0Y2hSZXNvdXJjZUNoYW5nZTxUPihzZWVkVmVyc2lvbiwgcGFyYW1zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDojrflj5YgR2xvYmFsIOmbhue+pOi1hOa6kOWvueixoeWIl+ihqO+8jOWMheWQq+WIhumhteS/oeaBr1xuICAgKi9cbiAgZ2V0R2xvYmFsUmVzb3VyY2VMaXN0PFQgZXh0ZW5kcyBLdWJlcm5ldGVzUmVzb3VyY2U+KFxuICAgIHBhcmFtczogR2xvYmFsUmVzb3VyY2VMaXN0UGFyYW1zPFI+LFxuICApIHtcbiAgICByZXR1cm4gdGhpcy5fZ2V0UmVzb3VyY2VMaXN0PFQ+KHBhcmFtcyk7XG4gIH1cblxuICAvKipcbiAgICog5Yib5bu6IEdsb2JhbCDpm4bnvqTotYTmupBcbiAgICovXG4gIHBvc3RHbG9iYWxSZXNvdXJjZTxUIGV4dGVuZHMgS3ViZXJuZXRlc1Jlc291cmNlPihcbiAgICBwYXJhbXM6IEdsb2JhbFJlc291cmNlV3JpdGVQYXJhbXM8VCwgUj4sXG4gICkge1xuICAgIHJldHVybiB0aGlzLl9wb3N0UmVzb3VyY2U8VD4ocGFyYW1zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDlrozmlbTopobnm5bmm7TmlrAgR2xvYmFsIOmbhue+pOWNleS4qui1hOa6kOWvueixoVxuICAgKi9cbiAgcHV0R2xvYmFsUmVzb3VyY2U8VCBleHRlbmRzIEt1YmVybmV0ZXNSZXNvdXJjZT4oXG4gICAgcGFyYW1zOiBHbG9iYWxSZXNvdXJjZVdyaXRlUGFyYW1zPFQsIFI+LFxuICApIHtcbiAgICByZXR1cm4gdGhpcy5fcHV0UmVzb3VyY2U8VD4ocGFyYW1zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDlop7ph4/mm7TmlrAgR2xvYmFsIOmbhue+pOWNleS4qui1hOa6kOWvueixoeeahOmDqOWIhuWxnuaAp1xuICAgKi9cbiAgcGF0Y2hHbG9iYWxSZXNvdXJjZTxUIGV4dGVuZHMgS3ViZXJuZXRlc1Jlc291cmNlPihcbiAgICBwYXJhbXM6IEdsb2JhbFJlc291cmNlUGF0Y2hQYXJhbXM8VCwgUj4sXG4gICkge1xuICAgIHJldHVybiB0aGlzLl9wYXRjaFJlc291cmNlPFQ+KHBhcmFtcyk7XG4gIH1cblxuICAvKipcbiAgICog5Yig6ZmkIEdsb2JhbCDpm4bnvqTljZXkuKrotYTmupBcbiAgICovXG4gIGRlbGV0ZUdsb2JhbFJlc291cmNlPFxuICAgIFMgZXh0ZW5kcyBLdWJlcm5ldGVzUmVzb3VyY2UgPSBTdGF0dXMsXG4gICAgVCBleHRlbmRzIEt1YmVybmV0ZXNSZXNvdXJjZSA9IFMgZXh0ZW5kcyBTdGF0dXMgPyBLdWJlcm5ldGVzUmVzb3VyY2UgOiBTLFxuICA+KHBhcmFtczogR2xvYmFsUmVzb3VyY2VEZWxldGVQYXJhbXM8VCwgUj4pIHtcbiAgICByZXR1cm4gdGhpcy5fZGVsZXRlUmVzb3VyY2U8UywgVD4ocGFyYW1zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDojrflj5bkuJrliqHpm4bnvqTljZXkuKrotYTmupDlr7nosaFcbiAgICovXG4gIGdldFJlc291cmNlPFQgZXh0ZW5kcyBLdWJlcm5ldGVzUmVzb3VyY2U+KHBhcmFtczogRXJlYnVzUmVzb3VyY2VQYXJhbXM8Uj4pIHtcbiAgICByZXR1cm4gdGhpcy5fZ2V0UmVzb3VyY2U8VD4ocGFyYW1zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDnm5HlkKzkuJrliqHpm4bnvqTljZXkuKrotYTmupDlr7nosaFcbiAgICovXG4gIHdhdGNoUmVzb3VyY2U8VCBleHRlbmRzIEt1YmVybmV0ZXNSZXNvdXJjZT4oXG4gICAgcGFyYW1zOiBXYXRjaEVyZWJ1c1Jlc291cmNlUGFyYW1zPFI+LFxuICApIHtcbiAgICByZXR1cm4gRE9XTkdSQURFX1dBVENIX0VOQUJMRUQgJiYgcGFyYW1zLmRvd25ncmFkZVBvbGxpbmdcbiAgICAgID8gY3JlYXRlUG9sbE9ic2VydmFibGU8VD4oXG4gICAgICAgICAgdGhpcy5fZ2V0UmVzb3VyY2U8VD4ocGFyYW1zKSxcbiAgICAgICAgICB0aGlzLl9nZXREb3duZ3JhZGVQb2xsaW5nKHBhcmFtcyksXG4gICAgICAgICkucGlwZShkaXN0aW5jdFVudGlsQ2hhbmdlZCgoYSwgYikgPT4gaXNFcXVhbChhLCBiKSkpXG4gICAgICA6IHRoaXMuX3dhdGNoUmVzb3VyY2U8VD4ocGFyYW1zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDnm5HlkKzotYTmupDliJfooajlj5jljJZcbiAgICovXG4gIHdhdGNoUmVzb3VyY2VDaGFuZ2U8VCBleHRlbmRzIEt1YmVybmV0ZXNSZXNvdXJjZT4oXG4gICAgc2VlZFZlcnNpb246IHN0cmluZyxcbiAgICBwYXJhbXM6IFdhdGNoRXJlYnVzUmVzb3VyY2VMaXN0UGFyYW1zPFI+LFxuICApIHtcbiAgICByZXR1cm4gdGhpcy5fa2VlcFdhdGNoUmVzb3VyY2VDaGFuZ2U8VD4oc2VlZFZlcnNpb24sIHBhcmFtcyk7XG4gIH1cblxuICAvKipcbiAgICog6I635Y+W5Lia5Yqh6ZuG576k6LWE5rqQ5a+56LGh5YiX6KGo77yM5YyF5ZCr5YiG6aG15L+h5oGvXG4gICAqL1xuICBnZXRSZXNvdXJjZUxpc3Q8VCBleHRlbmRzIEt1YmVybmV0ZXNSZXNvdXJjZT4oXG4gICAgcGFyYW1zOiBFcmVidXNSZXNvdXJjZUxpc3RQYXJhbXM8Uj4sXG4gICkge1xuICAgIHJldHVybiB0aGlzLl9nZXRSZXNvdXJjZUxpc3Q8VD4ocGFyYW1zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDliJvlu7rkuJrliqHpm4bnvqTotYTmupBcbiAgICovXG4gIHBvc3RSZXNvdXJjZTxUIGV4dGVuZHMgS3ViZXJuZXRlc1Jlc291cmNlPihcbiAgICBwYXJhbXM6IEVyZWJ1c1Jlc291cmNlV3JpdGVQYXJhbXM8VCwgUj4sXG4gICkge1xuICAgIHJldHVybiB0aGlzLl9wb3N0UmVzb3VyY2U8VD4ocGFyYW1zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDlrozmlbTopobnm5bmm7TmlrDkuJrliqHpm4bnvqTljZXkuKrotYTmupDlr7nosaFcbiAgICovXG4gIHB1dFJlc291cmNlPFQgZXh0ZW5kcyBLdWJlcm5ldGVzUmVzb3VyY2U+KFxuICAgIHBhcmFtczogRXJlYnVzUmVzb3VyY2VXcml0ZVBhcmFtczxULCBSPixcbiAgKSB7XG4gICAgcmV0dXJuIHRoaXMuX3B1dFJlc291cmNlPFQ+KHBhcmFtcyk7XG4gIH1cblxuICAvKipcbiAgICog5aKe6YeP5pu05paw5Lia5Yqh6ZuG576k5Y2V5Liq6LWE5rqQ5a+56LGh55qE6YOo5YiG5bGe5oCnXG4gICAqL1xuICBwYXRjaFJlc291cmNlPFQgZXh0ZW5kcyBLdWJlcm5ldGVzUmVzb3VyY2U+KFxuICAgIHBhcmFtczogRXJlYnVzUmVzb3VyY2VQYXRjaFBhcmFtczxULCBSPixcbiAgKSB7XG4gICAgcmV0dXJuIHRoaXMuX3BhdGNoUmVzb3VyY2U8VD4ocGFyYW1zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDliKDpmaTkuJrliqHpm4bnvqTljZXkuKrotYTmupBcbiAgICovXG4gIGRlbGV0ZVJlc291cmNlPFxuICAgIFMgZXh0ZW5kcyBLdWJlcm5ldGVzUmVzb3VyY2UgPSBTdGF0dXMsXG4gICAgVCBleHRlbmRzIEt1YmVybmV0ZXNSZXNvdXJjZSA9IFMgZXh0ZW5kcyBTdGF0dXMgPyBLdWJlcm5ldGVzUmVzb3VyY2UgOiBTLFxuICA+KHBhcmFtczogRXJlYnVzUmVzb3VyY2VEZWxldGVQYXJhbXM8VCwgUj4pIHtcbiAgICBpZiAoJ25hbWUnIGluIHBhcmFtcyAmJiAhcGFyYW1zLm5hbWUpIHtcbiAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IG5ldyBFcnJvcignZGVsZXRlIHJlc291cmNlIG5lZWQgcmVzb3VyY2UgbmFtZScpKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2RlbGV0ZVJlc291cmNlPFMsIFQ+KHBhcmFtcyk7XG4gIH1cblxuICAvKipcbiAgICog5om56YeP5Yig6Zmk5Lia5Yqh6ZuG576k55qE6LWE5rqQXG4gICAqL1xuICBiYXRjaERlbGV0ZVJlc291cmNlPFxuICAgIFMgZXh0ZW5kcyBLdWJlcm5ldGVzUmVzb3VyY2UgPSBTdGF0dXMsXG4gICAgVCBleHRlbmRzIEt1YmVybmV0ZXNSZXNvdXJjZSA9IFMgZXh0ZW5kcyBTdGF0dXMgPyBLdWJlcm5ldGVzUmVzb3VyY2UgOiBTLFxuICA+KHBhcmFtczogRXJlYnVzUmVzb3VyY2VCYXRjaERlbGV0ZVBhcmFtczxSPikge1xuICAgIHJldHVybiB0aGlzLl9iYXRjaERlbGV0ZVJlc291cmNlPFQ+KHBhcmFtcyk7XG4gIH1cblxuICAvLyBAaW50ZXJuYWxcbiAgcHJpdmF0ZSBfZ2V0UmVzb3VyY2VEZWZpbml0aW9uKHBhcmFtczogUmVzb3VyY2VBcGlQYXJhbXM8Uj4pIHtcbiAgICBjb25zdCBkZWZpbml0aW9uID0gdGhpcy5rOHNBcGlSZXNvdXJjZS5nZXREZWZpbml0aW9uKFxuICAgICAgJ2RlZmluaXRpb24nIGluIHBhcmFtcyAmJiBwYXJhbXMuZGVmaW5pdGlvblxuICAgICAgICA/IHBhcmFtcy5kZWZpbml0aW9uXG4gICAgICAgIDogJ3R5cGUnIGluIHBhcmFtcyAmJiBwYXJhbXMudHlwZSxcbiAgICApO1xuICAgIGlmICgncmVzb3VyY2UnIGluIHBhcmFtcyAmJiBwYXJhbXMucmVzb3VyY2UpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IGRlZmluaXRpb24udHlwZSxcbiAgICAgICAgLi4uZ2V0QXBpUHJlZml4UGFydHMocGFyYW1zLnJlc291cmNlLmFwaVZlcnNpb24pLFxuICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIGRlZmluaXRpb247XG4gIH1cblxuICAvLyBAaW50ZXJuYWxcbiAgcHJpdmF0ZSBfZ2V0QXBpUGF0aChwYXJhbXM6IFJlc291cmNlQXBpUGFyYW1zPFI+LCBpZ25vcmVOYW1lID0gZmFsc2UpIHtcbiAgICByZXR1cm4gdGhpcy5rOHNBcGlSZXNvdXJjZS5nZXRBcGlQYXRoKHtcbiAgICAgIC4uLnRoaXMuX2dldFJlc291cmNlRGVmaW5pdGlvbihwYXJhbXMpLFxuICAgICAgY2x1c3RlcjogJ2NsdXN0ZXInIGluIHBhcmFtcyAmJiBwYXJhbXMuY2x1c3RlcixcbiAgICAgIG5hbWVzcGFjZTogdGhpcy5fZ2V0TmFtZXNwYWNlKHBhcmFtcyksXG4gICAgICBuYW1lOiBpZ25vcmVOYW1lID8gbnVsbCA6IHRoaXMuX2dldE5hbWUocGFyYW1zKSxcbiAgICB9KTtcbiAgfVxuXG4gIC8vIEBpbnRlcm5hbFxuICBwcml2YXRlIF9nZXROYW1lc3BhY2UocGFyYW1zOiBSZXNvdXJjZUFwaVBhcmFtczxSPikge1xuICAgIHJldHVybiAnbmFtZXNwYWNlJyBpbiBwYXJhbXMgJiYgcGFyYW1zLm5hbWVzcGFjZVxuICAgICAgPyBwYXJhbXMubmFtZXNwYWNlXG4gICAgICA6ICduYW1lc3BhY2VkJyBpbiBwYXJhbXMgJiYgcGFyYW1zLm5hbWVzcGFjZWRcbiAgICAgID8gdGhpcy5nbG9iYWxOYW1lc3BhY2VcbiAgICAgIDogJ3Jlc291cmNlJyBpbiBwYXJhbXMgJiYgZ2V0KHBhcmFtcy5yZXNvdXJjZSwgW01FVEFEQVRBLCBOQU1FU1BBQ0VdKTtcbiAgfVxuXG4gIC8vIEBpbnRlcm5hbFxuICBwcml2YXRlIF9nZXROYW1lKHBhcmFtczogUmVzb3VyY2VBcGlQYXJhbXM8Uj4pIHtcbiAgICByZXR1cm4gJ25hbWUnIGluIHBhcmFtc1xuICAgICAgPyBwYXJhbXMubmFtZVxuICAgICAgOiAncmVzb3VyY2UnIGluIHBhcmFtcyAmJiBnZXQocGFyYW1zLnJlc291cmNlLCBbTUVUQURBVEEsIE5BTUVdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBrOHMgbGlzdCBhcGkg6L+U5Zue55qE57uT5p6c6YeM77yMaXRlbXMg57y65aSxIGtpbmQg5ZKMIGFwaVZlcnNpb24g5a2X5q61XG4gICAqIOinhOWImeWmgiBTZXJ2aWNlIOexu+Wei+WvueW6lCBraW5kOiBTZXJ2aWNlTGlzdO+8jOWOu+aOieacgOWQjuWbm+S4quWtl+espuWPr+W+l+WIsOi1hOa6kOeahCBraW5kXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHJpdmF0ZSBfZ2V0Tm9ybWFsaXplZExpc3Q8VCBleHRlbmRzIEt1YmVybmV0ZXNSZXNvdXJjZUxpc3Q+KGxpc3Q6IFQpOiBUIHtcbiAgICBjb25zdCB7IGFwaVZlcnNpb24sIGl0ZW1zIH0gPSBsaXN0O1xuXG4gICAgaWYgKCFpdGVtcyB8fCBpdGVtcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLmxpc3QsXG4gICAgICAgIGl0ZW1zOiBbXSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3Qga2luZCA9IGxpc3Qua2luZC5zbGljZSgwLCAtNCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmxpc3QsXG4gICAgICBpdGVtczogaXRlbXMubWFwKGl0ZW0gPT4gKHtcbiAgICAgICAgLy8ga2V5IOmhuuW6j+S8muW9seWTjei9rCB5YW1sIOWQjueahOmhuuW6j1xuICAgICAgICBraW5kLFxuICAgICAgICBhcGlWZXJzaW9uLFxuICAgICAgICAuLi5pdGVtLFxuICAgICAgfSkpLFxuICAgIH07XG4gIH1cblxuICAvLyBAaW50ZXJuYWxcbiAgcHJpdmF0ZSBfZ2V0UmVzb3VyY2U8VCBleHRlbmRzIEt1YmVybmV0ZXNSZXNvdXJjZT4oXG4gICAgcGFyYW1zOiBSZXNvdXJjZVJlYWRQYXJhbXM8Uj4sXG4gICkge1xuICAgIHJldHVybiB0aGlzLmh0dHAuZ2V0PFQ+KHRoaXMuX2dldEFwaVBhdGgocGFyYW1zKSwge1xuICAgICAgaGVhZGVyczogdGhpcy5fZ2V0SGVhZGVycyhwYXJhbXMpLFxuICAgIH0pO1xuICB9XG5cbiAgLy8gQGludGVybmFsXG4gIHByaXZhdGUgX3dhdGNoUmVzb3VyY2U8VCBleHRlbmRzIEt1YmVybmV0ZXNSZXNvdXJjZT4oXG4gICAgcGFyYW1zOiBXYXRjaFJlc291cmNlUmVhZFBhcmFtczxSPixcbiAgKSB7XG4gICAgY29uc3QgZGV0YWlsUGFyYW1zID0ge1xuICAgICAgLi4ucGFyYW1zLFxuICAgICAgcXVlcnlQYXJhbXM6IHsgZmllbGRTZWxlY3RvcjogJ21ldGFkYXRhLm5hbWU9JyArIHRoaXMuX2dldE5hbWUocGFyYW1zKSB9LFxuICAgIH07XG4gICAgY29uc3QgZGVmYXVsdFJldHJ5ID0ge1xuICAgICAgY291bnQ6IFJFVFJZX0NPVU5ULFxuICAgICAgZGVsYXk6IFJFVFJZX0RFTEFZLFxuICAgIH07XG4gICAgY29uc3QgeyBjb3VudCwgZGVsYXk6IGRlbGF5VGltZSB9ID1cbiAgICAgIHBhcmFtcy5yZXRyeSA9PT0gdHJ1ZVxuICAgICAgICA/IHtcbiAgICAgICAgICAgIC4uLmRlZmF1bHRSZXRyeSxcbiAgICAgICAgICAgIGNvdW50OiBJbmZpbml0eSxcbiAgICAgICAgICB9XG4gICAgICAgIDoge1xuICAgICAgICAgICAgLi4uZGVmYXVsdFJldHJ5LFxuICAgICAgICAgICAgLi4ucGFyYW1zLnJldHJ5LFxuICAgICAgICAgIH07XG4gICAgbGV0IHNvRmFyID0gMDtcbiAgICByZXR1cm4gdGhpcy5fZ2V0UmVzb3VyY2VMaXN0PFQ+KGRldGFpbFBhcmFtcykucGlwZShcbiAgICAgIHN3aXRjaE1hcChsaXN0ID0+XG4gICAgICAgIHRoaXMuX2tlZXBXYXRjaFJlc291cmNlQ2hhbmdlPFQ+KFxuICAgICAgICAgIGxpc3QubWV0YWRhdGEucmVzb3VyY2VWZXJzaW9uLFxuICAgICAgICAgIGRldGFpbFBhcmFtcyxcbiAgICAgICAgKS5waXBlKFxuICAgICAgICAgIGZpbHRlcihpc1Jlc291cmNlRXZlbnQpLFxuICAgICAgICAgIG1hcChyZXMgPT4gKHJlcy50eXBlID09PSBXYXRjaEV2ZW50LkRlbGV0ZWQgPyBudWxsIDogcmVzLm9iamVjdCkpLFxuICAgICAgICAgIHN0YXJ0V2l0aChsaXN0Lml0ZW1zWzBdID8/IG51bGwpLFxuICAgICAgICApLFxuICAgICAgKSxcbiAgICAgIHJldHJ5V2hlbihlcnIkID0+XG4gICAgICAgIGVyciQucGlwZShcbiAgICAgICAgICBzd2l0Y2hNYXAoZXJyID0+IHtcbiAgICAgICAgICAgIGlmIChlcnIgPT09IFdhdGNoRXZlbnQuRXJyb3IgfHwgKGNvdW50ICYmIHNvRmFyKysgPCBjb3VudCkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIG9mKGVycikucGlwZShkZWxheShjb3VudCA/IGRlbGF5VGltZSA6IDApKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IGVycik7XG4gICAgICAgICAgfSksXG4gICAgICAgICksXG4gICAgICApLFxuICAgICk7XG4gIH1cblxuICAvLyBAaW50ZXJuYWxcbiAgcHJpdmF0ZSBfa2VlcFdhdGNoUmVzb3VyY2VDaGFuZ2U8VCBleHRlbmRzIEt1YmVybmV0ZXNSZXNvdXJjZT4oXG4gICAgc2VlZFZlcnNpb246IHN0cmluZyxcbiAgICBwYXJhbXM6IFdhdGNoUmVzb3VyY2VMaXN0UmVhZFBhcmFtczxSPixcbiAgKSB7XG4gICAgbGV0IHJlc291cmNlVmVyc2lvbiA9IHNlZWRWZXJzaW9uO1xuICAgIGxldCBzdWI6IFN1YnNjcmlwdGlvbjtcblxuICAgIGNvbnN0IHdhdGNoJCA9IG5ldyBPYnNlcnZhYmxlPFdhdGNoQVBJUmVzcG9uc2U8VD4+KG9ic2VydmVyID0+IHtcbiAgICAgIGNvbnN0IHVuc3Vic2NyaWJlID0gKCkgPT4ge1xuICAgICAgICBpZiAoc3ViICYmICFzdWIuY2xvc2VkKSB7XG4gICAgICAgICAgc3ViLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHdhdGNoID0gKCkgPT4ge1xuICAgICAgICB1bnN1YnNjcmliZSgpO1xuICAgICAgICBzdWIgPSB0aGlzLl93YXRjaFJlc291cmNlQ2hhbmdlPFQ+KHtcbiAgICAgICAgICAuLi5wYXJhbXMsXG4gICAgICAgICAgcXVlcnlQYXJhbXM6IG5vcm1hbGl6ZVBhcmFtcyh7XG4gICAgICAgICAgICAuLi5wYXJhbXMucXVlcnlQYXJhbXMsXG4gICAgICAgICAgICB3YXRjaDogVFJVRSxcbiAgICAgICAgICAgIGFsbG93V2F0Y2hCb29rbWFya3M6IFRSVUUsXG4gICAgICAgICAgICB0aW1lb3V0U2Vjb25kczogU3RyaW5nKFRJTUVPVVRfU0VDT05EUyksXG4gICAgICAgICAgICByZXNvdXJjZVZlcnNpb24sXG4gICAgICAgICAgfSksXG4gICAgICAgIH0pLnN1YnNjcmliZSh7XG4gICAgICAgICAgbmV4dChyZXMpIHtcbiAgICAgICAgICAgIGlmIChyZXMudHlwZSA9PT0gV2F0Y2hFdmVudC5FcnJvcikge1xuICAgICAgICAgICAgICBvYnNlcnZlci5lcnJvcihyZXMudHlwZSk7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmVzb3VyY2VWZXJzaW9uID0gcmVzLm9iamVjdC5tZXRhZGF0YS5yZXNvdXJjZVZlcnNpb247XG4gICAgICAgICAgICBvYnNlcnZlci5uZXh0KHJlcyk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBlcnJvcihlcnIpIHtcbiAgICAgICAgICAgIG9ic2VydmVyLmVycm9yKGVycik7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBjb21wbGV0ZTogd2F0Y2gsXG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgd2F0Y2goKTtcbiAgICAgIHJldHVybiB1bnN1YnNjcmliZTtcbiAgICB9KTtcblxuICAgIHJldHVybiBwYXJhbXMua2VlcGFsaXZlXG4gICAgICA/IHdhdGNoJFxuICAgICAgOiBjb21iaW5lTGF0ZXN0KFtcbiAgICAgICAgICB0aGlzLnBhZ2VWaXNpYmlsaXR5LmdldFBhZ2VWaXNpYmlsaXR5KCksXG4gICAgICAgICAgcGFyYW1zLmFjdGl2ZSQgfHwgb2YodHJ1ZSksXG4gICAgICAgIF0pLnBpcGUoXG4gICAgICAgICAgc3dpdGNoTWFwKChbdmlzaWJsZSwgYWN0aXZlXSkgPT5cbiAgICAgICAgICAgIHZpc2libGUgJiYgYWN0aXZlID8gd2F0Y2gkIDogTkVWRVIsXG4gICAgICAgICAgKSxcbiAgICAgICAgKTtcbiAgfVxuXG4gIC8vIEBpbnRlcm5hbFxuICBwcml2YXRlIF93YXRjaFJlc291cmNlQ2hhbmdlPFQgZXh0ZW5kcyBLdWJlcm5ldGVzUmVzb3VyY2U+KFxuICAgIHBhcmFtczogUmVzb3VyY2VMaXN0UmVhZFBhcmFtczxSPixcbiAgKTogT2JzZXJ2YWJsZTxXYXRjaEFQSVJlc3BvbnNlPFQ+PiB7XG4gICAgcmV0dXJuIHRoaXMuaHR0cFxuICAgICAgLmdldCh0aGlzLl9nZXRBcGlQYXRoKHBhcmFtcywgdHJ1ZSksIHtcbiAgICAgICAgcmVzcG9uc2VUeXBlOiAndGV4dCcsXG4gICAgICAgIG9ic2VydmU6ICdldmVudHMnLFxuICAgICAgICByZXBvcnRQcm9ncmVzczogdHJ1ZSxcbiAgICAgICAgaGVhZGVyczogdGhpcy5fZ2V0SGVhZGVycyhwYXJhbXMpLFxuICAgICAgICBwYXJhbXM6IHBhcmFtcy5xdWVyeVBhcmFtcyxcbiAgICAgIH0pXG4gICAgICAucGlwZShcbiAgICAgICAgZmlsdGVyKGV2ID0+IGV2LnR5cGUgPT09IEh0dHBFdmVudFR5cGUuRG93bmxvYWRQcm9ncmVzcyksXG4gICAgICAgIGZpbHRlcihcbiAgICAgICAgICAoeyBwYXJ0aWFsVGV4dCB9OiBIdHRwRG93bmxvYWRQcm9ncmVzc0V2ZW50KSA9PiAhIXBhcnRpYWxUZXh0Py50cmltKCksXG4gICAgICAgICksXG4gICAgICAgIGNvbmNhdE1hcCgoeyBwYXJ0aWFsVGV4dCB9KSA9PlxuICAgICAgICAgIGZyb20oXG4gICAgICAgICAgICByZWR1Y2VXYXRjaEV2ZW50cyhcbiAgICAgICAgICAgICAgcGFyc2VKU09OU3RyZWFtPFdhdGNoQVBJUmVzcG9uc2U8VD4+KHBhcnRpYWxUZXh0KSxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgKSxcbiAgICAgICAgKSxcbiAgICAgICk7XG4gIH1cblxuICAvLyBAaW50ZXJuYWxcbiAgcHJpdmF0ZSBfZ2V0UmVzb3VyY2VMaXN0PFQgZXh0ZW5kcyBLdWJlcm5ldGVzUmVzb3VyY2U+KFxuICAgIHBhcmFtczogUmVzb3VyY2VMaXN0UmVhZFBhcmFtczxSPixcbiAgKSB7XG4gICAgLy8g5YyF5ZCrIGtleXdvcmQg5YmN57yA6ZyA6KaB5Yqg5LiK5YmN57yAICdhY3AvdjEvcmVzb3VyY2VzL3NlYXJjaCdcbiAgICAvLyDlj4LogIMgaHR0cDovL2NvbmZsdWVuY2UuYWxhdWRhLmNuL3BhZ2VzL3ZpZXdwYWdlLmFjdGlvbj9wYWdlSWQ9NDg3MzEwNThcbiAgICBsZXQgdXJsID0gdGhpcy5fZ2V0QXBpUGF0aChwYXJhbXMsIHRydWUpO1xuICAgIGNvbnN0IHF1ZXJ5UGFyYW1zID0geyAuLi5wYXJhbXMucXVlcnlQYXJhbXMgfTtcbiAgICBpZiAocXVlcnlQYXJhbXMua2V5d29yZCkge1xuICAgICAgdXJsID0gdXJsLnJlcGxhY2UoQVBJX0dBVEVXQVksIGAke0FQSV9HQVRFV0FZfSR7U0VBUkNIX1VSTF9QUkVGSVh9YCk7XG4gICAgICBpZiAoIXF1ZXJ5UGFyYW1zLmZpZWxkKSB7XG4gICAgICAgIHF1ZXJ5UGFyYW1zLmZpZWxkID0gJ21ldGFkYXRhLm5hbWUnO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5odHRwXG4gICAgICAuZ2V0PEt1YmVybmV0ZXNSZXNvdXJjZUxpc3Q8VD4+KHVybCwge1xuICAgICAgICBwYXJhbXM6IHF1ZXJ5UGFyYW1zLFxuICAgICAgICBoZWFkZXJzOiB0aGlzLl9nZXRIZWFkZXJzKHBhcmFtcywgdHJ1ZSksXG4gICAgICB9KVxuICAgICAgLnBpcGUobWFwKHRoaXMuX2dldE5vcm1hbGl6ZWRMaXN0KSk7XG4gIH1cblxuICAvLyBAaW50ZXJuYWxcbiAgcHJpdmF0ZSBfcG9zdFJlc291cmNlPFQgZXh0ZW5kcyBLdWJlcm5ldGVzUmVzb3VyY2U+KFxuICAgIHBhcmFtczogUmVzb3VyY2VXcml0ZVBhcmFtczxSLCBUPixcbiAgKSB7XG4gICAgaWYgKFxuICAgICAgKCduYW1lc3BhY2UnIGluIHBhcmFtcyAmJiBwYXJhbXMubmFtZXNwYWNlKSB8fFxuICAgICAgKCduYW1lc3BhY2VkJyBpbiBwYXJhbXMgJiYgcGFyYW1zLm5hbWVzcGFjZWQpXG4gICAgKSB7XG4gICAgICBjb25zdCByZXNvdXJjZU5hbWVzcGFjZSA9IGdldChwYXJhbXMucmVzb3VyY2UsIFtNRVRBREFUQSwgTkFNRVNQQUNFXSk7XG4gICAgICBpZiAoIXJlc291cmNlTmFtZXNwYWNlKSB7XG4gICAgICAgIHNldChcbiAgICAgICAgICBwYXJhbXMucmVzb3VyY2UsXG4gICAgICAgICAgW01FVEFEQVRBLCBOQU1FU1BBQ0VdLFxuICAgICAgICAgIHBhcmFtcy5uYW1lc3BhY2UgfHwgdGhpcy5nbG9iYWxOYW1lc3BhY2UsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmh0dHAucG9zdDxUPih0aGlzLl9nZXRBcGlQYXRoKHBhcmFtcywgdHJ1ZSksIHBhcmFtcy5yZXNvdXJjZSwge1xuICAgICAgaGVhZGVyczogdGhpcy5fZ2V0SGVhZGVycyhwYXJhbXMpLFxuICAgIH0pO1