@alauda-fe/common
Version:
Alauda frontend team common codes.
282 lines • 40 kB
JavaScript
import { MessageService, MessageType as Type, NotificationService, } from '@alauda/ui';
import { Injectable } from '@angular/core';
import { get } from 'lodash-es';
import { Subject, of, map, switchMap, takeUntil, tap } from 'rxjs';
import { K8sApiService } from '../../../api/k8s-api.service';
import { WatchEvent } from '../../../api/types';
import { AuthorizationStateService } from '../../../authorization/state.service';
import { K8sUtilService } from '../../../core/public-api';
import { K8SResourceList } from '../../../k8s-resource-list/k8s-resource-list';
import { MESSAGE_CONFIG, MessageType, NOTIFY_INFO_TYPE, NOTIFY_NOT_FIXED, NOTIFY_PUSH_TYPE, dateValueOf, } from './utils';
import * as i0 from "@angular/core";
import * as i1 from "../../../api/k8s-api.service";
import * as i2 from "../../../authorization/state.service";
import * as i3 from "../../../core/public-api";
import * as i4 from "@alauda/ui";
const NOTIFY_TYPE_MAP = {
[MessageType.WarningMessage]: Type.Error,
[MessageType.SystemMessage]: Type.Info,
[MessageType.ProductMessage]: Type.Success,
[MessageType.PlatformAnnouncement]: '',
};
export class NotifyService {
constructor(k8sApi, auth, k8sUtil, notification, messages) {
this.k8sApi = k8sApi;
this.auth = auth;
this.k8sUtil = k8sUtil;
this.notification = notification;
this.messages = messages;
this.triggerNotify$ = new Subject();
this.pushEnabled = true;
this.auiNotificationList = [];
this.windowUnload = false;
this.onDestroy$ = new Subject();
this.userName$ = this.auth.getTokenPayload().pipe(takeUntil(this.onDestroy$), map(account => account.email || account.name), tap(name => {
this.userName = name;
this.settingDefaultPushStatus();
}));
// 这个版本没有自动发送的消息,用户手册没有办法描述这部分功能, 先注释
// 因占用并发数,后续如产品需要重新加入此功能,可以和产品讨论下是否可以阉割此功能
// watchConfigMap$ = this.k8sApi
// .watchGlobalResource({
// definition: {
// type: 'configmaps',
// },
// namespaced: true,
// name: 'message-config',
// })
// .pipe(
// takeUntil(this.onDestroy$),
// catchError(() => of(null)),
// map(() => {
// return this.pushEnabled;
// }),
// );
// watchMessageConfigMap$ = this.watchConfigMap$.pipe(
// switchMap(res =>
// this.userName$.pipe(
// map(() => {
// return res;
// }),
// ),
// ),
// );
this.list = new K8SResourceList({
fetchParams$: of({}), // 使用空参数否则路由参数变化会导致重新触发 get list
fetcher: this.fetcher.bind(this),
watcher: seed => this.k8sApi
.watchGlobalResourceChange(seed, {
definition: MESSAGE_CONFIG,
})
.pipe(tap(item => {
const cacheInfo = this.getCacheLocalValue(NOTIFY_INFO_TYPE);
const infoValue = cacheInfo?.split(',') || [];
this.removePush(item);
if ([WatchEvent.Added, WatchEvent.Modified].includes(item.type) &&
!infoValue.includes(this.k8sUtil.getName(item.object))) {
this.dispatchNotify(item.object);
const value = [...infoValue, this.k8sUtil.getName(item.object)];
this.cacheNotifyInfo(value.join(','));
}
})),
polling: 10_000,
});
}
watchNotify() {
this.triggerNotify$.pipe(takeUntil(this.onDestroy$)).subscribe(res => {
this.notifyMessage(res);
});
}
getNotifyList() {
return this.list.items$.pipe(takeUntil(this.onDestroy$), switchMap(res => this.userName$.pipe(map(() => res))), map(res => this.messageSort(res, 'desc')));
}
messageSort(data, type = 'asc') {
return data.sort((a, b) => {
const start = type === 'asc'
? a.metadata.creationTimestamp
: b.metadata.creationTimestamp;
const end = type === 'asc'
? b.metadata.creationTimestamp
: a.metadata.creationTimestamp;
return dateValueOf(start) - dateValueOf(end);
});
}
fetcher() {
return this.k8sApi
.getGlobalResourceList({
definition: MESSAGE_CONFIG,
})
.pipe(tap(res => {
this.handleNotify(res.items);
}));
}
handleNotify(data) {
const cacheInfo = this.getCacheLocalValue(NOTIFY_INFO_TYPE);
const infoValue = cacheInfo?.split(',') || [];
const messages = this.messageSort(data, 'desc').reduce((acc, item) => {
const { isResident } = item.spec;
if (isResident &&
!this.expired(item) &&
!infoValue.includes(this.k8sUtil.getName(item))) {
const pre = acc ? `${acc},` : '';
this.dispatchNotify(item); // 触发提示消息
return `${pre}${this.k8sUtil.getName(item)}`;
}
return acc;
}, '');
if (messages) {
this.cacheNotifyInfo(messages);
}
}
cacheNotifyInfo(values) {
this.addCacheLocalValue(NOTIFY_INFO_TYPE, values);
}
dispatchNotify(data) {
const notFixed = this.getCacheLocalValue(NOTIFY_NOT_FIXED);
const pass = !notFixed?.split(',')?.includes(this.k8sUtil.getName(data));
const push = this.getCacheLocalValue(NOTIFY_PUSH_TYPE);
if (((!data.spec.isResident && this.pushEnabled && push) ||
!this.expired(data)) &&
pass) {
this.triggerNotify$.next(data);
}
}
expired(item) {
const expiredTimestamp = item.spec.expiredTimestamp;
if (!expiredTimestamp) {
return true;
}
return new Date(expiredTimestamp).valueOf() < Date.now();
}
getCacheLocalValue(type) {
const value = window.localStorage.getItem(type);
return value && JSON.parse(value)[this.userName];
}
addCacheLocalValue(type, value) {
const preValue = window.localStorage.getItem(type);
window.localStorage.setItem(type, JSON.stringify({
...(preValue ? JSON.parse(preValue) : {}),
[this.userName]: value,
}));
}
notifyMessage(data) {
const { isResident, subject, content } = data.spec;
const name = this.k8sUtil.getName(data);
const type = this.getMessageType(data);
if (isResident) {
const notificationRef = this.notification.create({
type: type || Type.Info,
title: subject,
...(type ? {} : { customClass: 'platform-class' }),
content,
...(isResident ? { duration: 0 } : {}),
});
this.auiNotificationList.push(notificationRef);
Object.assign(notificationRef.instance, { data });
notificationRef.instance.afterClosed.subscribe(() => {
this.closedNotifyCallback(data, name, get(notificationRef.instance, 'windowUnload', false));
});
return;
}
this.messages.create({
type: type || Type.Info,
content: subject,
});
}
/**
* 关闭通知: 手动关闭存储 添加不再展示状态记录
* 关闭页面、删除消息 不记录
*/
closedNotifyCallback(data, name, windowUnload) {
this.removeNotificationList(name);
if (!this.windowUnload && !windowUnload) {
this.addNotFixed(data);
}
this.windowUnload = false;
}
/**
* 记录 不再展示状态 存储在 local storage
*/
addNotFixed(data) {
if (data.spec.isResident) {
const notFixedVal = this.getCacheLocalValue(NOTIFY_NOT_FIXED);
const value = [
...(notFixedVal?.split(',') || []),
this.k8sUtil.getName(data),
];
this.addCacheLocalValue(NOTIFY_NOT_FIXED, value.join(','));
}
this.windowUnload = false;
}
/**
* 触发删除消息
* - 删除 local storage NOT_FIXED 存储的消息
* - 手动触发关闭常驻通知弹框
*/
removePush(item) {
const name = this.k8sUtil.getName(item.object);
const notFixedVal = this.getCacheLocalValue(NOTIFY_NOT_FIXED)?.split(',') || [];
if (WatchEvent.Deleted === item.type) {
this.removeMessage(name);
this.manualCloseNotify(name);
}
if (WatchEvent.Deleted === item.type &&
item.object.spec.isResident &&
!notFixedVal.includes(name)) {
this.manualCloseNotify(name);
}
}
removeMessage(name) {
const cacheNotFixed = this.getCacheLocalValue(NOTIFY_NOT_FIXED)?.split(',') || [];
if (cacheNotFixed.length > 0) {
const index = cacheNotFixed.indexOf(name);
if (index !== -1) {
cacheNotFixed.splice(index, 1);
this.addCacheLocalValue(NOTIFY_NOT_FIXED, cacheNotFixed.join(','));
}
}
}
manualCloseNotify(name) {
const notifyInstance = this.auiNotificationList.find(item => this.k8sUtil.getName(get(item.instance, 'data')) === name);
if (notifyInstance) {
this.windowUnload = true;
notifyInstance.instance.close();
}
}
removeNotificationList(name) {
this.auiNotificationList = this.auiNotificationList.filter(item => this.k8sUtil.getName(get(item.instance, 'data')) !== name);
}
getMessageType(data) {
const type = this.k8sUtil.getLabel(data, 'type');
return NOTIFY_TYPE_MAP[type];
}
settingDefaultPushStatus() {
if (!window.localStorage.getItem(NOTIFY_PUSH_TYPE)) {
this.addCacheLocalValue(NOTIFY_PUSH_TYPE, true);
}
}
closeAllNotification() {
for (const notify of this.auiNotificationList) {
// 将 windowUnload 存储 instance 在 afterClosed 进行判断
// remove 异步 循环中 windowUnload 值已发生改变但还未触发 afterClosed 回调
Object.assign(notify.instance, { windowUnload: true });
notify.instance.close();
}
this.auiNotificationList = [];
}
destroy() {
// 重新加载 header 关闭所有通知,重新加载 header 重新弹出
this.closeAllNotification();
window.localStorage.removeItem(NOTIFY_INFO_TYPE);
this.onDestroy$.next();
}
static { this.ɵfac = function NotifyService_Factory(t) { return new (t || NotifyService)(i0.ɵɵinject(i1.K8sApiService), i0.ɵɵinject(i2.AuthorizationStateService), i0.ɵɵinject(i3.K8sUtilService), i0.ɵɵinject(i4.NotificationService), i0.ɵɵinject(i4.MessageService)); }; }
static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: NotifyService, factory: NotifyService.ɵfac, providedIn: 'root' }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(NotifyService, [{
type: Injectable,
args: [{
providedIn: 'root',
}]
}], () => [{ type: i1.K8sApiService }, { type: i2.AuthorizationStateService }, { type: i3.K8sUtilService }, { type: i4.NotificationService }, { type: i4.MessageService }], null); })();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm90aWZ5LnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9saWJzL2NvbW1vbi9zcmMvcGFnZS1zY2FmZm9sZC9wYWdlLWhlYWRlci9oZWFkZXItbm90aWZ5L25vdGlmeS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxjQUFjLEVBQ2QsV0FBVyxJQUFJLElBQUksRUFFbkIsbUJBQW1CLEdBQ3BCLE1BQU0sWUFBWSxDQUFDO0FBQ3BCLE9BQU8sRUFBZ0IsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3pELE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDaEMsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRW5FLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUM3RCxPQUFPLEVBQW9CLFVBQVUsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBQ2pGLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sOENBQThDLENBQUM7QUFHL0UsT0FBTyxFQUNMLGNBQWMsRUFFZCxXQUFXLEVBQ1gsZ0JBQWdCLEVBQ2hCLGdCQUFnQixFQUNoQixnQkFBZ0IsRUFDaEIsV0FBVyxHQUNaLE1BQU0sU0FBUyxDQUFDOzs7Ozs7QUFFakIsTUFBTSxlQUFlLEdBQUc7SUFDdEIsQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUs7SUFDeEMsQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLEVBQUUsSUFBSSxDQUFDLElBQUk7SUFDdEMsQ0FBQyxXQUFXLENB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RUFBRSxDQUFDO0lBQ2hDLENBQUM7SUFFRCxPQUFPO1FBQ0wsc0NBQXNDO1FBQ3RDLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1FBQzVCLE1BQU0sQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUN6QixDQUFDOzhFQTNUVSxhQUFhO3VFQUFiLGFBQWEsV0FBYixhQUFhLG1CQUZaLE1BQU07O2lGQUVQLGFBQWE7Y0FIekIsVUFBVTtlQUFDO2dCQUNWLFVBQVUsRUFBRSxNQUFNO2FBQ25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgTWVzc2FnZVNlcnZpY2UsXG4gIE1lc3NhZ2VUeXBlIGFzIFR5cGUsXG4gIE5vdGlmaWNhdGlvbkNvbXBvbmVudCxcbiAgTm90aWZpY2F0aW9uU2VydmljZSxcbn0gZnJvbSAnQGFsYXVkYS91aSc7XG5pbXBvcnQgeyBDb21wb25lbnRSZWYsIEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGdldCB9IGZyb20gJ2xvZGFzaC1lcyc7XG5pbXBvcnQgeyBTdWJqZWN0LCBvZiwgbWFwLCBzd2l0Y2hNYXAsIHRha2VVbnRpbCwgdGFwIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IEs4c0FwaVNlcnZpY2UgfSBmcm9tICcuLi8uLi8uLi9hcGkvazhzLWFwaS5zZXJ2aWNlJztcbmltcG9ydCB7IFdhdGNoQVBJUmVzcG9uc2UsIFdhdGNoRXZlbnQgfSBmcm9tICcuLi8uLi8uLi9hcGkvdHlwZXMnO1xuaW1wb3J0IHsgQXV0aG9yaXphdGlvblN0YXRlU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL2F1dGhvcml6YXRpb24vc3RhdGUuc2VydmljZSc7XG5pbXBvcnQgeyBLOHNVdGlsU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL2NvcmUvcHVibGljLWFwaSc7XG5pbXBvcnQgeyBLOFNSZXNvdXJjZUxpc3QgfSBmcm9tICcuLi8uLi8uLi9rOHMtcmVzb3VyY2UtbGlzdC9rOHMtcmVzb3VyY2UtbGlzdCc7XG5pbXBvcnQgeyBBY2NvdW50SW5mbyB9IGZyb20gJy4uL2FjY291bnQtbWVudS9jb21wb25lbnQvY29tcG9uZW50JztcblxuaW1wb3J0IHtcbiAgTUVTU0FHRV9DT05GSUcsXG4gIE1lc3NhZ2UsXG4gIE1lc3NhZ2VUeXBlLFxuICBOT1RJRllfSU5GT19UWVBFLFxuICBOT1RJRllfTk9UX0ZJWEVELFxuICBOT1RJRllfUFVTSF9UWVBFLFxuICBkYXRlVmFsdWVPZixcbn0gZnJvbSAnLi91dGlscyc7XG5cbmNvbnN0IE5PVElGWV9UWVBFX01BUCA9IHtcbiAgW01lc3NhZ2VUeXBlLldhcm5pbmdNZXNzYWdlXTogVHlwZS5FcnJvcixcbiAgW01lc3NhZ2VUeXBlLlN5c3RlbU1lc3NhZ2VdOiBUeXBlLkluZm8sXG4gIFtNZXNzYWdlVHlwZS5Qcm9kdWN0TWVzc2FnZV06IFR5cGUuU3VjY2VzcyxcbiAgW01lc3NhZ2VUeXBlLlBsYXRmb3JtQW5ub3VuY2VtZW50XTogJycsXG59O1xuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIE5vdGlmeVNlcnZpY2Uge1xuICBwcml2YXRlIHVzZXJOYW1lOiBzdHJpbmc7XG4gIHRyaWdnZXJOb3RpZnkkID0gbmV3IFN1YmplY3Q8TWVzc2FnZT4oKTtcbiAgcHVzaEVuYWJsZWQgPSB0cnVlO1xuICBhdWlOb3RpZmljYXRpb25MaXN0OiBBcnJheTxDb21wb25lbnRSZWY8Tm90aWZpY2F0aW9uQ29tcG9uZW50Pj4gPSBbXTtcbiAgd2luZG93VW5sb2FkID0gZmFsc2U7XG4gIG9uRGVzdHJveSQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICB1c2VyTmFtZSQgPSB0aGlzLmF1dGguZ2V0VG9rZW5QYXlsb2FkPEFjY291bnRJbmZvPigpLnBpcGUoXG4gICAgdGFrZVVudGlsKHRoaXMub25EZXN0cm95JCksXG4gICAgbWFwKGFjY291bnQgPT4gYWNjb3VudC5lbWFpbCB8fCBhY2NvdW50Lm5hbWUpLFxuICAgIHRhcChuYW1lID0+IHtcbiAgICAgIHRoaXMudXNlck5hbWUgPSBuYW1lO1xuICAgICAgdGhpcy5zZXR0aW5nRGVmYXVsdFB1c2hTdGF0dXMoKTtcbiAgICB9KSxcbiAgKTtcbiAgLy8g6L+Z5Liq54mI5pys5rKh5pyJ6Ieq5Yqo5Y+R6YCB55qE5raI5oGv77yM55So5oi35omL5YaM5rKh5pyJ5Yqe5rOV5o+P6L+w6L+Z6YOo5YiG5Yqf6IO9LCDlhYjms6jph4pcbiAgLy8g5Zug5Y2g55So5bm25Y+R5pWw77yM5ZCO57ut5aaC5Lqn5ZOB6ZyA6KaB6YeN5paw5Yqg5YWl5q2k5Yqf6IO977yM5Y+v5Lul5ZKM5Lqn5ZOB6K6o6K665LiL5piv5ZCm5Y+v5Lul6ZiJ5Ymy5q2k5Yqf6IO9XG4gIC8vIHdhdGNoQ29uZmlnTWFwJCA9IHRoaXMuazhzQXBpXG4gIC8vICAgLndhdGNoR2xvYmFsUmVzb3VyY2Uoe1xuICAvLyAgICAgZGVmaW5pdGlvbjoge1xuICAvLyAgICAgICB0eXBlOiAnY29uZmlnbWFwcycsXG4gIC8vICAgICB9LFxuICAvLyAgICAgbmFtZXNwYWNlZDogdHJ1ZSxcbiAgLy8gICAgIG5hbWU6ICdtZXNzYWdlLWNvbmZpZycsXG4gIC8vICAgfSlcbiAgLy8gICAucGlwZShcbiAgLy8gICAgIHRha2VVbnRpbCh0aGlzLm9uRGVzdHJveSQpLFxuICAvLyAgICAgY2F0Y2hFcnJvcigoKSA9PiBvZihudWxsKSksXG4gIC8vICAgICBtYXAoKCkgPT4ge1xuICAvLyAgICAgICByZXR1cm4gdGhpcy5wdXNoRW5hYmxlZDtcbiAgLy8gICAgIH0pLFxuICAvLyAgICk7XG4gIC8vIHdhdGNoTWVzc2FnZUNvbmZpZ01hcCQgPSB0aGlzLndhdGNoQ29uZmlnTWFwJC5waXBlKFxuICAvLyAgIHN3aXRjaE1hcChyZXMgPT5cbiAgLy8gICAgIHRoaXMudXNlck5hbWUkLnBpcGUoXG4gIC8vICAgICAgIG1hcCgoKSA9PiB7XG4gIC8vICAgICAgICAgcmV0dXJuIHJlcztcbiAgLy8gICAgICAgfSksXG4gIC8vICAgICApLFxuICAvLyAgICksXG4gIC8vICk7XG5cbiAgbGlzdCA9IG5ldyBLOFNSZXNvdXJjZUxpc3Qoe1xuICAgIGZldGNoUGFyYW1zJDogb2Yoe30pLCAvLyDkvb/nlKjnqbrlj4LmlbDlkKbliJnot6/nlLHlj4LmlbDlj5jljJbkvJrlr7zoh7Tph43mlrDop6blj5EgZ2V0IGxpc3RcbiAgICBmZXRjaGVyOiB0aGlzLmZldGNoZXIuYmluZCh0aGlzKSxcbiAgICB3YXRjaGVyOiBzZWVkID0+XG4gICAgICB0aGlzLms4c0FwaVxuICAgICAgICAud2F0Y2hHbG9iYWxSZXNvdXJjZUNoYW5nZTxNZXNzYWdlPihzZWVkLCB7XG4gICAgICAgICAgZGVmaW5pdGlvbjogTUVTU0FHRV9DT05GSUcsXG4gICAgICAgIH0pXG4gICAgICAgIC5waXBlKFxuICAgICAgICAgIHRhcChpdGVtID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNhY2hlSW5mbyA9IHRoaXMuZ2V0Q2FjaGVMb2NhbFZhbHVlKE5PVElGWV9JTkZPX1RZUEUpO1xuICAgICAgICAgICAgY29uc3QgaW5mb1ZhbHVlOiBzdHJpbmdbXSA9IGNhY2hlSW5mbz8uc3BsaXQoJywnKSB8fCBbXTtcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlUHVzaChpdGVtKTtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgW1dhdGNoRXZlbnQuQWRkZWQsIFdhdGNoRXZlbnQuTW9kaWZpZWRdLmluY2x1ZGVzKGl0ZW0udHlwZSkgJiZcbiAgICAgICAgICAgICAgIWluZm9WYWx1ZS5pbmNsdWRlcyh0aGlzLms4c1V0aWwuZ2V0TmFtZShpdGVtLm9iamVjdCkpXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgdGhpcy5kaXNwYXRjaE5vdGlmeShpdGVtLm9iamVjdCk7XG4gICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gWy4uLmluZm9WYWx1ZSwgdGhpcy5rOHNVdGlsLmdldE5hbWUoaXRlbS5vYmplY3QpXTtcbiAgICAgICAgICAgICAgdGhpcy5jYWNoZU5vdGlmeUluZm8odmFsdWUuam9pbignLCcpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KSxcbiAgICAgICAgKSxcbiAgICBwb2xsaW5nOiAxMF8wMDAsXG4gIH0pO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgazhzQXBpOiBLOHNBcGlTZXJ2aWNlLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgYXV0aDogQXV0aG9yaXphdGlvblN0YXRlU2VydmljZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGs4c1V0aWw6IEs4c1V0aWxTZXJ2aWNlLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgbm90aWZpY2F0aW9uOiBOb3RpZmljYXRpb25TZXJ2aWNlLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgbWVzc2FnZXM6IE1lc3NhZ2VTZXJ2aWNlLFxuICApIHt9XG5cbiAgd2F0Y2hOb3RpZnkoKSB7XG4gICAgdGhpcy50cmlnZ2VyTm90aWZ5JC5waXBlKHRha2VVbnRpbCh0aGlzLm9uRGVzdHJveSQpKS5zdWJzY3JpYmUocmVzID0+IHtcbiAgICAgIHRoaXMubm90aWZ5TWVzc2FnZShyZXMpO1xuICAgIH0pO1xuICB9XG5cbiAgZ2V0Tm90aWZ5TGlzdCgpIHtcbiAgICByZXR1cm4gdGhpcy5saXN0Lml0ZW1zJC5waXBlKFxuICAgICAgdGFrZVVudGlsKHRoaXMub25EZXN0cm95JCksXG4gICAgICBzd2l0Y2hNYXAocmVzID0+IHRoaXMudXNlck5hbWUkLnBpcGUobWFwKCgpID0+IHJlcykpKSxcbiAgICAgIG1hcChyZXMgPT4gdGhpcy5tZXNzYWdlU29ydChyZXMsICdkZXNjJykpLFxuICAgICk7XG4gIH1cblxuICBtZXNzYWdlU29ydChkYXRhOiBNZXNzYWdlW10sIHR5cGU6ICdhc2MnIHwgJ2Rlc2MnID0gJ2FzYycpIHtcbiAgICByZXR1cm4gZGF0YS5zb3J0KChhLCBiKSA9PiB7XG4gICAgICBjb25zdCBzdGFydCA9XG4gICAgICAgIHR5cGUgPT09ICdhc2MnXG4gICAgICAgICAgPyBhLm1ldGFkYXRhLmNyZWF0aW9uVGltZXN0YW1wXG4gICAgICAgICAgOiBiLm1ldGFkYXRhLmNyZWF0aW9uVGltZXN0YW1wO1xuICAgICAgY29uc3QgZW5kID1cbiAgICAgICAgdHlwZSA9PT0gJ2FzYydcbiAgICAgICAgICA/IGIubWV0YWRhdGEuY3JlYXRpb25UaW1lc3RhbXBcbiAgICAgICAgICA6IGEubWV0YWRhdGEuY3JlYXRpb25UaW1lc3RhbXA7XG4gICAgICByZXR1cm4gZGF0ZVZhbHVlT2Yoc3RhcnQpIC0gZGF0ZVZhbHVlT2YoZW5kKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZmV0Y2hlcigpIHtcbiAgICByZXR1cm4gdGhpcy5rOHNBcGlcbiAgICAgIC5nZXRHbG9iYWxSZXNvdXJjZUxpc3Q8TWVzc2FnZT4oe1xuICAgICAgICBkZWZpbml0aW9uOiBNRVNTQUdFX0NPTkZJRyxcbiAgICAgIH0pXG4gICAgICAucGlwZShcbiAgICAgICAgdGFwKHJlcyA9PiB7XG4gICAgICAgICAgdGhpcy5oYW5kbGVOb3RpZnkocmVzLml0ZW1zKTtcbiAgICAgICAgfSksXG4gICAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVOb3RpZnkoZGF0YTogTWVzc2FnZVtdKSB7XG4gICAgY29uc3QgY2FjaGVJbmZvID0gdGhpcy5nZXRDYWNoZUxvY2FsVmFsdWUoTk9USUZZX0lORk9fVFlQRSk7XG4gICAgY29uc3QgaW5mb1ZhbHVlOiBzdHJpbmdbXSA9IGNhY2hlSW5mbz8uc3BsaXQoJywnKSB8fCBbXTtcbiAgICBjb25zdCBtZXNzYWdlcyA9IHRoaXMubWVzc2FnZVNvcnQoZGF0YSwgJ2Rlc2MnKS5yZWR1Y2UoKGFjYywgaXRlbSkgPT4ge1xuICAgICAgY29uc3QgeyBpc1Jlc2lkZW50IH0gPSBpdGVtLnNwZWM7XG4gICAgICBpZiAoXG4gICAgICAgIGlzUmVzaWRlbnQgJiZcbiAgICAgICAgIXRoaXMuZXhwaXJlZChpdGVtKSAmJlxuICAgICAgICAhaW5mb1ZhbHVlLmluY2x1ZGVzKHRoaXMuazhzVXRpbC5nZXROYW1lKGl0ZW0pKVxuICAgICAgKSB7XG4gICAgICAgIGNvbnN0IHByZSA9IGFjYyA/IGAke2FjY30sYCA6ICcnO1xuICAgICAgICB0aGlzLmRpc3BhdGNoTm90aWZ5KGl0ZW0pOyAvLyDop6blj5Hmj5DnpLrmtojmga9cbiAgICAgICAgcmV0dXJuIGAke3ByZX0ke3RoaXMuazhzVXRpbC5nZXROYW1lKGl0ZW0pfWA7XG4gICAgICB9XG4gICAgICByZXR1cm4gYWNjO1xuICAgIH0sICcnKTtcbiAgICBpZiAobWVzc2FnZXMpIHtcbiAgICAgIHRoaXMuY2FjaGVOb3RpZnlJbmZvKG1lc3NhZ2VzKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGNhY2hlTm90aWZ5SW5mbyh2YWx1ZXM6IHN0cmluZykge1xuICAgIHRoaXMuYWRkQ2FjaGVMb2NhbFZhbHVlKE5PVElGWV9JTkZPX1RZUEUsIHZhbHVlcyk7XG4gIH1cblxuICBwcml2YXRlIGRpc3BhdGNoTm90aWZ5KGRhdGE6IE1lc3NhZ2UpIHtcbiAgICBjb25zdCBub3RGaXhlZCA9IHRoaXMuZ2V0Q2FjaGVMb2NhbFZhbHVlKE5PVElGWV9OT1RfRklYRUQpO1xuICAgIGNvbnN0IHBhc3MgPSAhbm90Rml4ZWQ/LnNwbGl0KCcsJyk/LmluY2x1ZGVzKHRoaXMuazhzVXRpbC5nZXROYW1lKGRhdGEpKTtcbiAgICBjb25zdCBwdXNoID0gdGhpcy5nZXRDYWNoZUxvY2FsVmFsdWUoTk9USUZZX1BVU0hfVFlQRSk7XG4gICAgaWYgKFxuICAgICAgKCghZGF0YS5zcGVjLmlzUmVzaWRlbnQgJiYgdGhpcy5wdXNoRW5hYmxlZCAmJiBwdXNoKSB8fFxuICAgICAgICAhdGhpcy5leHBpcmVkKGRhdGEpKSAmJlxuICAgICAgcGFzc1xuICAgICkge1xuICAgICAgdGhpcy50cmlnZ2VyTm90aWZ5JC5uZXh0KGRhdGEpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZXhwaXJlZChpdGVtOiBNZXNzYWdlKSB7XG4gICAgY29uc3QgZXhwaXJlZFRpbWVzdGFtcCA9IGl0ZW0uc3BlYy5leHBpcmVkVGltZXN0YW1wO1xuICAgIGlmICghZXhwaXJlZFRpbWVzdGFtcCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBuZXcgRGF0ZShleHBpcmVkVGltZXN0YW1wKS52YWx1ZU9mKCkgPCBEYXRlLm5vdygpO1xuICB9XG5cbiAgZ2V0Q2FjaGVMb2NhbFZhbHVlKHR5cGU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgdmFsdWUgPSB3aW5kb3cubG9jYWxTdG9yYWdlLmdldEl0ZW0odHlwZSk7XG4gICAgcmV0dXJuIHZhbHVlICYmIEpTT04ucGFyc2UodmFsdWUpW3RoaXMudXNlck5hbWVdO1xuICB9XG5cbiAgYWRkQ2FjaGVMb2NhbFZhbHVlKHR5cGU6IHN0cmluZywgdmFsdWU6IHN0cmluZyB8IGJvb2xlYW4pIHtcbiAgICBjb25zdCBwcmVWYWx1ZSA9IHdpbmRvdy5sb2NhbFN0b3JhZ2UuZ2V0SXRlbSh0eXBlKTtcbiAgICB3aW5kb3cubG9jYWxTdG9yYWdlLnNldEl0ZW0oXG4gICAgICB0eXBlLFxuICAgICAgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAuLi4ocHJlVmFsdWUgPyBKU09OLnBhcnNlKHByZVZhbHVlKSA6IHt9KSxcbiAgICAgICAgW3RoaXMudXNlck5hbWVdOiB2YWx1ZSxcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIG5vdGlmeU1lc3NhZ2UoZGF0YTogTWVzc2FnZSkge1xuICAgIGNvbnN0IHsgaXNSZXNpZGVudCwgc3ViamVjdCwgY29udGVudCB9ID0gZGF0YS5zcGVjO1xuICAgIGNvbnN0IG5hbWUgPSB0aGlzLms4c1V0aWwuZ2V0TmFtZShkYXRhKTtcbiAgICBjb25zdCB0eXBlID0gdGhpcy5nZXRNZXNzYWdlVHlwZShkYXRhKTtcblxuICAgIGlmIChpc1Jlc2lkZW50KSB7XG4gICAgICBjb25zdCBub3RpZmljYXRpb25SZWYgPSB0aGlzLm5vdGlmaWNhdGlvbi5jcmVhdGUoe1xuICAgICAgICB0eXBlOiB0eXBlIHx8IFR5cGUuSW5mbyxcbiAgICAgICAgdGl0bGU6IHN1YmplY3QsXG4gICAgICAgIC4uLih0eXBlID8ge30gOiB7IGN1c3RvbUNsYXNzOiAncGxhdGZvcm0tY2xhc3MnIH0pLFxuICAgICAgICBjb250ZW50LFxuICAgICAgICAuLi4oaXNSZXNpZGVudCA/IHsgZHVyYXRpb246IDAgfSA6IHt9KSxcbiAgICAgIH0pO1xuICAgICAgdGhpcy5hdWlOb3RpZmljYXRpb25MaXN0LnB1c2gobm90aWZpY2F0aW9uUmVmKTtcbiAgICAgIE9iamVjdC5hc3NpZ24obm90aWZpY2F0aW9uUmVmLmluc3RhbmNlLCB7IGRhdGEgfSk7XG4gICAgICBub3RpZmljYXRpb25SZWYuaW5zdGFuY2UuYWZ0ZXJDbG9zZWQuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgdGhpcy5jbG9zZWROb3RpZnlDYWxsYmFjayhcbiAgICAgICAgICBkYXRhLFxuICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgZ2V0KG5vdGlmaWNhdGlvblJlZi5pbnN0YW5jZSwgJ3dpbmRvd1VubG9hZCcsIGZhbHNlKSxcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLm1lc3NhZ2VzLmNyZWF0ZSh7XG4gICAgICB0eXBlOiB0eXBlIHx8IFR5cGUuSW5mbyxcbiAgICAgIGNvbnRlbnQ6IHN1YmplY3QsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICog5YWz6Zet6YCa55+lOiDmiYvliqjlhbPpl63lrZjlgqgg5re75Yqg5LiN5YaN5bGV56S654q25oCB6K6w5b2VXG4gICAqIOWFs+mXremhtemdouOAgeWIoOmZpOa2iOaBryDkuI3orrDlvZVcbiAgICovXG4gIHByaXZhdGUgY2xvc2VkTm90aWZ5Q2FsbGJhY2soXG4gICAgZGF0YTogTWVzc2FnZSxcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgd2luZG93VW5sb2FkOiBib29sZWFuLFxuICApIHtcbiAgICB0aGlzLnJlbW92ZU5vdGlmaWNhdGlvbkxpc3QobmFtZSk7XG4gICAgaWYgKCF0aGlzLndpbmRvd1VubG9hZCAmJiAhd2luZG93VW5sb2FkKSB7XG4gICAgICB0aGlzLmFkZE5vdEZpeGVkKGRhdGEpO1xuICAgIH1cbiAgICB0aGlzLndpbmRvd1VubG9hZCA9IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIOiusOW9lSDkuI3lho3lsZXnpLrnirbmgIEg5a2Y5YKo5ZyoIGxvY2FsIHN0b3JhZ2VcbiAgICovXG4gIHByaXZhdGUgYWRkTm90Rml4ZWQoZGF0YTogTWVzc2FnZSkge1xuICAgIGlmIChkYXRhLnNwZWMuaXNSZXNpZGVudCkge1xuICAgICAgY29uc3Qgbm90Rml4ZWRWYWwgPSB0aGlzLmdldENhY2hlTG9jYWxWYWx1ZShOT1RJRllfTk9UX0ZJWEVEKTtcbiAgICAgIGNvbnN0IHZhbHVlID0gW1xuICAgICAgICAuLi4obm90Rml4ZWRWYWw/LnNwbGl0KCcsJykgfHwgW10pLFxuICAgICAgICB0aGlzLms4c1V0aWwuZ2V0TmFtZShkYXRhKSxcbiAgICAgIF07XG4gICAgICB0aGlzLmFkZENhY2hlTG9jYWxWYWx1ZShOT1RJRllfTk9UX0ZJWEVELCB2YWx1ZS5qb2luKCcsJykpO1xuICAgIH1cbiAgICB0aGlzLndpbmRvd1VubG9hZCA9IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIOinpuWPkeWIoOmZpOa2iOaBr1xuICAgKiAtIOWIoOmZpCBsb2NhbCBzdG9yYWdlIE5PVF9GSVhFRCDlrZjlgqjnmoTmtojmga9cbiAgICogLSDmiYvliqjop6blj5HlhbPpl63luLjpqbvpgJrnn6XlvLnmoYZcbiAgICovXG4gIHByaXZhdGUgcmVtb3ZlUHVzaChpdGVtOiBXYXRjaEFQSVJlc3BvbnNlPE1lc3NhZ2U+KSB7XG4gICAgY29uc3QgbmFtZSA9IHRoaXMuazhzVXRpbC5nZXROYW1lKGl0ZW0ub2JqZWN0KTtcbiAgICBjb25zdCBub3RGaXhlZFZhbCA9XG4gICAgICB0aGlzLmdldENhY2hlTG9jYWxWYWx1ZShOT1RJRllfTk9UX0ZJWEVEKT8uc3BsaXQoJywnKSB8fCBbXTtcbiAgICBpZiAoV2F0Y2hFdmVudC5EZWxldGVkID09PSBpdGVtLnR5cGUpIHtcbiAgICAgIHRoaXMucmVtb3ZlTWVzc2FnZShuYW1lKTtcbiAgICAgIHRoaXMubWFudWFsQ2xvc2VOb3RpZnkobmFtZSk7XG4gICAgfVxuICAgIGlmIChcbiAgICAgIFdhdGNoRXZlbnQuRGVsZXRlZCA9PT0gaXRlbS50eXBlICYmXG4gICAgICBpdGVtLm9iamVjdC5zcGVjLmlzUmVzaWRlbnQgJiZcbiAgICAgICFub3RGaXhlZFZhbC5pbmNsdWRlcyhuYW1lKVxuICAgICkge1xuICAgICAgdGhpcy5tYW51YWxDbG9zZU5vdGlmeShuYW1lKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlbW92ZU1lc3NhZ2UobmFtZTogc3RyaW5nKSB7XG4gICAgY29uc3QgY2FjaGVOb3RGaXhlZCA9XG4gICAgICB0aGlzLmdldENhY2hlTG9jYWxWYWx1ZShOT1RJRllfTk9UX0ZJWEVEKT8uc3BsaXQoJywnKSB8fCBbXTtcbiAgICBpZiAoY2FjaGVOb3RGaXhlZC5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBpbmRleCA9IGNhY2hlTm90Rml4ZWQuaW5kZXhPZihuYW1lKTtcbiAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgY2FjaGVOb3RGaXhlZC5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICB0aGlzLmFkZENhY2hlTG9jYWxWYWx1ZShOT1RJRllfTk9UX0ZJWEVELCBjYWNoZU5vdEZpeGVkLmpvaW4oJywnKSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBtYW51YWxDbG9zZU5vdGlmeShuYW1lOiBzdHJpbmcpIHtcbiAgICBjb25zdCBub3RpZnlJbnN0YW5jZSA9IHRoaXMuYXVpTm90aWZpY2F0aW9uTGlzdC5maW5kKFxuICAgICAgaXRlbSA9PiB0aGlzLms4c1V0aWwuZ2V0TmFtZShnZXQoaXRlbS5pbnN0YW5jZSwgJ2RhdGEnKSkgPT09IG5hbWUsXG4gICAgKTtcbiAgICBpZiAobm90aWZ5SW5zdGFuY2UpIHtcbiAgICAgIHRoaXMud2luZG93VW5sb2FkID0gdHJ1ZTtcbiAgICAgIG5vdGlmeUluc3RhbmNlLmluc3RhbmNlLmNsb3NlKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZW1vdmVOb3RpZmljYXRpb25MaXN0KG5hbWU6IHN0cmluZykge1xuICAgIHRoaXMuYXVpTm90aWZpY2F0aW9uTGlzdCA9IHRoaXMuYXVpTm90aWZpY2F0aW9uTGlzdC5maWx0ZXIoXG4gICAgICBpdGVtID0+IHRoaXMuazhzVXRpbC5nZXROYW1lKGdldChpdGVtLmluc3RhbmNlLCAnZGF0YScpKSAhPT0gbmFtZSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRNZXNzYWdlVHlwZShkYXRhOiBNZXNzYWdlKSB7XG4gICAgY29uc3QgdHlwZSA9IHRoaXMuazhzVXRpbC5nZXRMYWJlbChkYXRhLCAndHlwZScpIGFzIE1lc3NhZ2VUeXBlO1xuICAgIHJldHVybiBOT1RJRllfVFlQRV9NQVBbdHlwZV0gYXMgVHlwZTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0dGluZ0RlZmF1bHRQdXNoU3RhdHVzKCkge1xuICAgIGlmICghd2luZG93LmxvY2FsU3RvcmFnZS5nZXRJdGVtKE5PVElGWV9QVVNIX1RZUEUpKSB7XG4gICAgICB0aGlzLmFkZENhY2hlTG9jYWxWYWx1ZShOT1RJRllfUFVTSF9UWVBFLCB0cnVlKTtcbiAgICB9XG4gIH1cblxuICBjbG9zZUFsbE5vdGlmaWNhdGlvbigpIHtcbiAgICBmb3IgKGNvbnN0IG5vdGlmeSBvZiB0aGlzLmF1aU5vdGlmaWNhdGlvbkxpc3QpIHtcbiAgICAgIC8vIOWwhiB3aW5kb3dVbmxvYWQg5a2Y5YKoIGluc3RhbmNlIOWcqCBhZnRlckNsb3NlZCDov5vooYzliKTmlq1cbiAgICAgIC8vIHJlbW92ZSDlvILmraUg5b6q546v5LitIHdpbmRvd1VubG9hZCDlgLzlt7Llj5HnlJ/mlLnlj5jkvYbov5jmnKrop6blj5EgYWZ0ZXJDbG9zZWQg5Zue6LCDXG4gICAgICBPYmplY3QuYXNzaWduKG5vdGlmeS5pbnN0YW5jZSwgeyB3aW5kb3dVbmxvYWQ6IHRydWUgfSk7XG4gICAgICBub3RpZnkuaW5zdGFuY2UuY2xvc2UoKTtcbiAgICB9XG4gICAgdGhpcy5hdWlOb3RpZmljYXRpb25MaXN0ID0gW107XG4gIH1cblxuICBkZXN0cm95KCkge1xuICAgIC8vIOmHjeaWsOWKoOi9vSBoZWFkZXIg5YWz6Zet5omA5pyJ6YCa55+l77yM6YeN5paw5Yqg6L29IGhlYWRlciDph43mlrDlvLnlh7pcbiAgICB0aGlzLmNsb3NlQWxsTm90aWZpY2F0aW9uKCk7XG4gICAgd2luZG93LmxvY2FsU3RvcmFnZS5yZW1vdmVJdGVtKE5PVElGWV9JTkZPX1RZUEUpO1xuICAgIHRoaXMub25EZXN0cm95JC5uZXh0KCk7XG4gIH1cbn1cbiJdfQ==