UNPKG

@alauda-fe/common

Version:

Alauda frontend team common codes.

394 lines 53.6 kB
/** * @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