@yelon/bis 15.2.0 → 15.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +23 -23
  3. package/esm2020/bis.mjs +4 -4
  4. package/esm2020/index.mjs +1 -1
  5. package/esm2020/layout/bis.config.mjs +10 -10
  6. package/esm2020/layout/html-names.mjs +32 -32
  7. package/esm2020/layout/icon/style-icons.mjs +795 -795
  8. package/esm2020/layout/layout-basic/index.mjs +2 -2
  9. package/esm2020/layout/layout-basic/interface.mjs +6 -6
  10. package/esm2020/layout/layout-basic/layout-basic.component.mjs +355 -355
  11. package/esm2020/layout/layout-nav/index.mjs +4 -4
  12. package/esm2020/layout/layout-nav/layout-nav-application.component.mjs +326 -326
  13. package/esm2020/layout/layout-nav/layout-nav-group.component.mjs +123 -123
  14. package/esm2020/layout/layout-nav/layout-nav-tile.component.mjs +14 -14
  15. package/esm2020/layout/layout-nav/types.mjs +1 -1
  16. package/esm2020/layout/layout.mjs +4 -4
  17. package/esm2020/layout/public_api.mjs +12 -12
  18. package/esm2020/layout/widgets/index.mjs +6 -6
  19. package/esm2020/layout/widgets/yunzai-clear-storage.component.mjs +44 -44
  20. package/esm2020/layout/widgets/yunzai-fullscreen.component.mjs +44 -44
  21. package/esm2020/layout/widgets/yunzai-i18n.component.mjs +145 -145
  22. package/esm2020/layout/widgets/yunzai-notify.component.mjs +182 -182
  23. package/esm2020/layout/widgets/yunzai-theme-btn.component.mjs +200 -200
  24. package/esm2020/layout/widgets/yunzai-user.component.mjs +129 -129
  25. package/esm2020/layout/yunzai-act.guard.mjs +106 -106
  26. package/esm2020/layout/yunzai-auth.service.mjs +169 -167
  27. package/esm2020/layout/yunzai-default.interceptor.mjs +208 -208
  28. package/esm2020/layout/yunzai-i18n.service.mjs +130 -130
  29. package/esm2020/layout/yunzai-lang.mjs +113 -113
  30. package/esm2020/layout/yunzai-layout.module.mjs +75 -75
  31. package/esm2020/layout/yunzai-startup.service.mjs +156 -156
  32. package/esm2020/public_api.mjs +1 -1
  33. package/fesm2015/bis.mjs +6 -6
  34. package/fesm2015/layout.mjs +3232 -3230
  35. package/fesm2015/layout.mjs.map +1 -1
  36. package/fesm2020/bis.mjs +6 -6
  37. package/fesm2020/layout.mjs +3240 -3238
  38. package/fesm2020/layout.mjs.map +1 -1
  39. package/index.d.ts +1 -1
  40. package/index.less +1 -1
  41. package/layout/bis.config.d.ts +3 -3
  42. package/layout/html-names.d.ts +31 -31
  43. package/layout/icon/style-icons.d.ts +1 -1
  44. package/layout/index.d.ts +5 -5
  45. package/layout/layout-basic/index.d.ts +2 -2
  46. package/layout/layout-basic/interface.d.ts +24 -24
  47. package/layout/layout-basic/layout-basic.component.d.ts +32 -32
  48. package/layout/layout-nav/index.d.ts +4 -4
  49. package/layout/layout-nav/layout-nav-application.component.d.ts +27 -27
  50. package/layout/layout-nav/layout-nav-group.component.d.ts +17 -17
  51. package/layout/layout-nav/layout-nav-tile.component.d.ts +6 -6
  52. package/layout/layout-nav/types.d.ts +15 -15
  53. package/layout/public_api.d.ts +12 -12
  54. package/layout/style/index.less +154 -154
  55. package/layout/widgets/index.d.ts +6 -6
  56. package/layout/widgets/yunzai-clear-storage.component.d.ts +11 -11
  57. package/layout/widgets/yunzai-fullscreen.component.d.ts +8 -8
  58. package/layout/widgets/yunzai-i18n.component.d.ts +21 -21
  59. package/layout/widgets/yunzai-notify.component.d.ts +30 -30
  60. package/layout/widgets/yunzai-theme-btn.component.d.ts +32 -32
  61. package/layout/widgets/yunzai-user.component.d.ts +28 -28
  62. package/layout/yunzai-act.guard.d.ts +22 -22
  63. package/layout/yunzai-auth.service.d.ts +21 -21
  64. package/layout/yunzai-default.interceptor.d.ts +27 -27
  65. package/layout/yunzai-i18n.service.d.ts +33 -33
  66. package/layout/yunzai-lang.d.ts +11 -11
  67. package/layout/yunzai-layout.module.d.ts +21 -21
  68. package/layout/yunzai-startup.service.d.ts +37 -37
  69. package/package.json +47 -47
  70. package/public_api.d.ts +2 -2
  71. package/theme-compact.less +3 -3
  72. package/theme-dark.less +46 -46
  73. package/theme-default.less +46 -46
@@ -1,209 +1,209 @@
1
- import { HttpErrorResponse, HttpResponse, HttpResponseBase } from '@angular/common/http';
2
- import { Injectable } from '@angular/core';
3
- import { Router } from '@angular/router';
4
- import { BehaviorSubject, of, throwError, catchError, filter, mergeMap, switchMap, take } from 'rxjs';
5
- import { YA_SERVICE_TOKEN, ALLOW_ANONYMOUS } from '@yelon/auth';
6
- import { YUNZAI_I18N_TOKEN, _HttpClient } from '@yelon/theme';
7
- import { WINDOW } from '@yelon/util';
8
- import { YunzaiConfigService } from '@yelon/util/config';
9
- import { log } from '@yelon/util/other';
10
- import { NzNotificationService } from 'ng-zorro-antd/notification';
11
- import { mergeBisConfig } from './bis.config';
12
- import * as i0 from "@angular/core";
13
- const CODEMESSAGE = {
14
- 200: '服务器成功返回请求的数据。',
15
- 201: '新建或修改数据成功。',
16
- 202: '一个请求已经进入后台排队(异步任务)。',
17
- 204: '删除数据成功。',
18
- 400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
19
- 401: '用户没有权限(令牌、用户名、密码错误)。',
20
- 403: '用户得到授权,但是访问是被禁止的。',
21
- 404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
22
- 406: '请求的格式不可得。',
23
- 410: '请求的资源被永久删除,且不会再得到的。',
24
- 422: '当创建一个对象时,发生一个验证错误。',
25
- 500: '服务器发生错误,请检查服务器。',
26
- 502: '网关错误。',
27
- 503: '服务不可用,服务器暂时过载或维护。',
28
- 504: '网关超时。'
29
- };
30
- class YunzaiDefaultInterceptor {
31
- get notification() {
32
- return this.injector.get(NzNotificationService);
33
- }
34
- get tokenSrv() {
35
- return this.injector.get(YA_SERVICE_TOKEN);
36
- }
37
- get http() {
38
- return this.injector.get(_HttpClient);
39
- }
40
- get config() {
41
- return mergeBisConfig(this.injector.get(YunzaiConfigService));
42
- }
43
- goTo(url) {
44
- setTimeout(() => this.injector.get(Router).navigateByUrl(url));
45
- }
46
- constructor(injector) {
47
- this.injector = injector;
48
- this.jump = false;
49
- this.refreshToking = false;
50
- this.refreshToken$ = new BehaviorSubject(null);
51
- if (this.config.refreshTokenType === 'auth-refresh') {
52
- console.error("can't use auth-refresh, please change yz.default.interceptor to default.interceptor!");
53
- }
54
- }
55
- checkStatus(ev) {
56
- if ((ev.status >= 200 && ev.status < 300) || ev.status === 401) {
57
- return;
58
- }
59
- if (ev instanceof HttpErrorResponse && (ev.error.message || ev.error.errorMessage)) {
60
- if (ev.error.errorMessage) {
61
- this.notification.error(`发生了一些错误 `, ev.error.errorMessage);
62
- }
63
- else {
64
- this.notification.error(`发生了一些错误 `, ev.error.message);
65
- }
66
- return;
67
- }
68
- if (ev instanceof HttpResponse && ev.body.errorMessage) {
69
- this.notification.error(`发生了一些错误 `, ev.body.errorMessage);
70
- return;
71
- }
72
- const errortext = CODEMESSAGE[ev.status] || ev.statusText;
73
- this.notification.error(`请求错误 ${ev.status}: ${ev.url}`, errortext);
74
- }
75
- ToLogin() {
76
- this.notification.error(`未登录或登录状态已过期,5秒后将跳转到登录页面。`, ``);
77
- setTimeout(() => {
78
- localStorage.clear();
79
- this.injector.get(WINDOW).location.href = `${this.config.baseUrl}/cas-proxy/app/logout`;
80
- }, 5000);
81
- }
82
- reAttachToken(req) {
83
- const token = this.tokenSrv.get()?.token;
84
- return req.clone({
85
- setHeaders: {
86
- Authorization: `Bearer ${token}`
87
- }
88
- });
89
- }
90
- refreshTokenRequest() {
91
- const model = this.tokenSrv.get();
92
- const form = new FormData();
93
- form.set('refresh_token', model?.refreshToken);
94
- form.set('grant_type', 'refresh_token');
95
- form.set('scope', 'webapp');
96
- log('yz.default.interceptor: use the refresh token to request a new token', model?.refreshToken);
97
- // return this.http.post(`/auth/user/token/refresh?_allow_anonymous=true`, form);
98
- return this.http.post(`/auth/oauth/getOrCreateToken/webapp`, form);
99
- }
100
- tryRefreshToken(ev, req, next) {
101
- // 连刷新Token的请求都错了,那就是真错了
102
- if (['/auth/oauth/getOrCreateToken/webapp'].some(url => req.url.includes(url))) {
103
- this.ToLogin();
104
- return throwError(() => ev);
105
- }
106
- // 正在刷新token,所有其他请求排队
107
- if (this.refreshToking) {
108
- return this.refreshToken$.pipe(filter(v => !!v), take(1), switchMap(() => next.handle(this.reAttachToken(req))));
109
- }
110
- //尝试调用刷新 Token
111
- this.refreshToking = true;
112
- this.refreshToken$.next(null);
113
- // 处理Token
114
- return this.refreshTokenRequest().pipe(switchMap(res => {
115
- log('yz.default.interceptor: refresh token accessed -> ', res);
116
- // 重新保存新 token
117
- const { access_token, expires_in, refresh_token, scope, token_type } = res;
118
- this.tokenSrv.set({
119
- token: access_token,
120
- expired: expires_in,
121
- refreshToken: refresh_token,
122
- tokenType: token_type,
123
- scope
124
- });
125
- // 通知后续请求继续执行
126
- this.refreshToking = false;
127
- this.refreshToken$.next(res);
128
- // 重新发起请求
129
- return next.handle(this.reAttachToken(req));
130
- }), catchError(err => {
131
- this.refreshToking = false;
132
- this.ToLogin();
133
- return throwError(() => err);
134
- }));
135
- }
136
- getAdditionalHeaders(headers) {
137
- const res = {};
138
- const lang = this.injector.get(YUNZAI_I18N_TOKEN).currentLang;
139
- if (!headers?.has('Accept-Language') && lang) {
140
- res['Accept-Language'] = lang;
141
- }
142
- return res;
143
- }
144
- handleData(ev, req, next) {
145
- this.checkStatus(ev);
146
- switch (ev.status) {
147
- case 200:
148
- return of(ev);
149
- case 401:
150
- if (this.config.refreshTokenEnabled && this.config.refreshTokenType === 're-request') {
151
- const unAuthorizationReq = req.clone();
152
- unAuthorizationReq.headers.delete('Authorization');
153
- return this.tryRefreshToken(ev, unAuthorizationReq, next);
154
- }
155
- this.ToLogin();
156
- break;
157
- case 403:
158
- case 404:
159
- case 500:
160
- if (this.jump) {
161
- this.goTo(`/exception/${ev.status}`);
162
- }
163
- break;
164
- default:
165
- if (ev instanceof HttpErrorResponse) {
166
- console.warn('未可知错误,大部分是由于后端不支持跨域CORS或无效配置引起,请参考 https://ng.yunzainfo.com/docs/server 解决跨域问题', ev);
167
- }
168
- break;
169
- }
170
- if (ev instanceof HttpErrorResponse) {
171
- return throwError(() => ev);
172
- }
173
- else {
174
- return of(ev);
175
- }
176
- }
177
- intercept(req, next) {
178
- if (req.context.get(ALLOW_ANONYMOUS))
179
- return next.handle(req);
180
- log('yz.default.interceptor.ts: ', 'request ', req);
181
- // 统一加前缀
182
- let url = req.url;
183
- if (!url.startsWith('https://') && !url.startsWith('http://')) {
184
- url = this.config.baseUrl + url;
185
- }
186
- if (url.includes('.json') && url.includes('assets')) {
187
- url = req.url;
188
- }
189
- if (url.includes('i18n'))
190
- return next.handle(req);
191
- // 加入语言头
192
- const newReq = req.clone({ url, setHeaders: this.getAdditionalHeaders(req.headers) });
193
- return next.handle(newReq).pipe(mergeMap(ev => {
194
- // 允许统一对请求错误处理
195
- if (ev instanceof HttpResponseBase) {
196
- return this.handleData(ev, newReq, next);
197
- }
198
- // 若一切都正常,则后续操作
199
- return of(ev);
200
- }), catchError((err) => this.handleData(err, newReq, next)));
201
- }
202
- }
203
- YunzaiDefaultInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: YunzaiDefaultInterceptor, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
204
- YunzaiDefaultInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: YunzaiDefaultInterceptor });
205
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: YunzaiDefaultInterceptor, decorators: [{
206
- type: Injectable
207
- }], ctorParameters: function () { return [{ type: i0.Injector }]; } });
208
- export { YunzaiDefaultInterceptor as YzDefaultInterceptor, YunzaiDefaultInterceptor };
1
+ import { HttpErrorResponse, HttpResponse, HttpResponseBase } from '@angular/common/http';
2
+ import { Injectable } from '@angular/core';
3
+ import { Router } from '@angular/router';
4
+ import { BehaviorSubject, of, throwError, catchError, filter, mergeMap, switchMap, take } from 'rxjs';
5
+ import { YA_SERVICE_TOKEN, ALLOW_ANONYMOUS } from '@yelon/auth';
6
+ import { YUNZAI_I18N_TOKEN, _HttpClient } from '@yelon/theme';
7
+ import { WINDOW } from '@yelon/util';
8
+ import { YunzaiConfigService } from '@yelon/util/config';
9
+ import { log } from '@yelon/util/other';
10
+ import { NzNotificationService } from 'ng-zorro-antd/notification';
11
+ import { mergeBisConfig } from './bis.config';
12
+ import * as i0 from "@angular/core";
13
+ const CODEMESSAGE = {
14
+ 200: '服务器成功返回请求的数据。',
15
+ 201: '新建或修改数据成功。',
16
+ 202: '一个请求已经进入后台排队(异步任务)。',
17
+ 204: '删除数据成功。',
18
+ 400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
19
+ 401: '用户没有权限(令牌、用户名、密码错误)。',
20
+ 403: '用户得到授权,但是访问是被禁止的。',
21
+ 404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
22
+ 406: '请求的格式不可得。',
23
+ 410: '请求的资源被永久删除,且不会再得到的。',
24
+ 422: '当创建一个对象时,发生一个验证错误。',
25
+ 500: '服务器发生错误,请检查服务器。',
26
+ 502: '网关错误。',
27
+ 503: '服务不可用,服务器暂时过载或维护。',
28
+ 504: '网关超时。'
29
+ };
30
+ class YunzaiDefaultInterceptor {
31
+ get notification() {
32
+ return this.injector.get(NzNotificationService);
33
+ }
34
+ get tokenSrv() {
35
+ return this.injector.get(YA_SERVICE_TOKEN);
36
+ }
37
+ get http() {
38
+ return this.injector.get(_HttpClient);
39
+ }
40
+ get config() {
41
+ return mergeBisConfig(this.injector.get(YunzaiConfigService));
42
+ }
43
+ goTo(url) {
44
+ setTimeout(() => this.injector.get(Router).navigateByUrl(url));
45
+ }
46
+ constructor(injector) {
47
+ this.injector = injector;
48
+ this.jump = false;
49
+ this.refreshToking = false;
50
+ this.refreshToken$ = new BehaviorSubject(null);
51
+ if (this.config.refreshTokenType === 'auth-refresh') {
52
+ console.error("can't use auth-refresh, please change yz.default.interceptor to default.interceptor!");
53
+ }
54
+ }
55
+ checkStatus(ev) {
56
+ if ((ev.status >= 200 && ev.status < 300) || ev.status === 401) {
57
+ return;
58
+ }
59
+ if (ev instanceof HttpErrorResponse && (ev.error.message || ev.error.errorMessage)) {
60
+ if (ev.error.errorMessage) {
61
+ this.notification.error(`发生了一些错误 `, ev.error.errorMessage);
62
+ }
63
+ else {
64
+ this.notification.error(`发生了一些错误 `, ev.error.message);
65
+ }
66
+ return;
67
+ }
68
+ if (ev instanceof HttpResponse && ev.body.errorMessage) {
69
+ this.notification.error(`发生了一些错误 `, ev.body.errorMessage);
70
+ return;
71
+ }
72
+ const errortext = CODEMESSAGE[ev.status] || ev.statusText;
73
+ this.notification.error(`请求错误 ${ev.status}: ${ev.url}`, errortext);
74
+ }
75
+ ToLogin() {
76
+ this.notification.error(`未登录或登录状态已过期,5秒后将跳转到登录页面。`, ``);
77
+ setTimeout(() => {
78
+ localStorage.clear();
79
+ this.injector.get(WINDOW).location.href = `${this.config.baseUrl}/cas-proxy/app/logout`;
80
+ }, 5000);
81
+ }
82
+ reAttachToken(req) {
83
+ const token = this.tokenSrv.get()?.token;
84
+ return req.clone({
85
+ setHeaders: {
86
+ Authorization: `Bearer ${token}`
87
+ }
88
+ });
89
+ }
90
+ refreshTokenRequest() {
91
+ const model = this.tokenSrv.get();
92
+ const form = new FormData();
93
+ form.set('refresh_token', model?.refreshToken);
94
+ form.set('grant_type', 'refresh_token');
95
+ form.set('scope', 'webapp');
96
+ log('yz.default.interceptor: use the refresh token to request a new token', model?.refreshToken);
97
+ // return this.http.post(`/auth/user/token/refresh?_allow_anonymous=true`, form);
98
+ return this.http.post(`/auth/oauth/getOrCreateToken/webapp`, form);
99
+ }
100
+ tryRefreshToken(ev, req, next) {
101
+ // 连刷新Token的请求都错了,那就是真错了
102
+ if (['/auth/oauth/getOrCreateToken/webapp'].some(url => req.url.includes(url))) {
103
+ this.ToLogin();
104
+ return throwError(() => ev);
105
+ }
106
+ // 正在刷新token,所有其他请求排队
107
+ if (this.refreshToking) {
108
+ return this.refreshToken$.pipe(filter(v => !!v), take(1), switchMap(() => next.handle(this.reAttachToken(req))));
109
+ }
110
+ //尝试调用刷新 Token
111
+ this.refreshToking = true;
112
+ this.refreshToken$.next(null);
113
+ // 处理Token
114
+ return this.refreshTokenRequest().pipe(switchMap(res => {
115
+ log('yz.default.interceptor: refresh token accessed -> ', res);
116
+ // 重新保存新 token
117
+ const { access_token, expires_in, refresh_token, scope, token_type } = res;
118
+ this.tokenSrv.set({
119
+ token: access_token,
120
+ expired: expires_in,
121
+ refreshToken: refresh_token,
122
+ tokenType: token_type,
123
+ scope
124
+ });
125
+ // 通知后续请求继续执行
126
+ this.refreshToking = false;
127
+ this.refreshToken$.next(res);
128
+ // 重新发起请求
129
+ return next.handle(this.reAttachToken(req));
130
+ }), catchError(err => {
131
+ this.refreshToking = false;
132
+ this.ToLogin();
133
+ return throwError(() => err);
134
+ }));
135
+ }
136
+ getAdditionalHeaders(headers) {
137
+ const res = {};
138
+ const lang = this.injector.get(YUNZAI_I18N_TOKEN).currentLang;
139
+ if (!headers?.has('Accept-Language') && lang) {
140
+ res['Accept-Language'] = lang;
141
+ }
142
+ return res;
143
+ }
144
+ handleData(ev, req, next) {
145
+ this.checkStatus(ev);
146
+ switch (ev.status) {
147
+ case 200:
148
+ return of(ev);
149
+ case 401:
150
+ if (this.config.refreshTokenEnabled && this.config.refreshTokenType === 're-request') {
151
+ const unAuthorizationReq = req.clone();
152
+ unAuthorizationReq.headers.delete('Authorization');
153
+ return this.tryRefreshToken(ev, unAuthorizationReq, next);
154
+ }
155
+ this.ToLogin();
156
+ break;
157
+ case 403:
158
+ case 404:
159
+ case 500:
160
+ if (this.jump) {
161
+ this.goTo(`/exception/${ev.status}`);
162
+ }
163
+ break;
164
+ default:
165
+ if (ev instanceof HttpErrorResponse) {
166
+ console.warn('未可知错误,大部分是由于后端不支持跨域CORS或无效配置引起,请参考 https://ng.yunzainfo.com/docs/server 解决跨域问题', ev);
167
+ }
168
+ break;
169
+ }
170
+ if (ev instanceof HttpErrorResponse) {
171
+ return throwError(() => ev);
172
+ }
173
+ else {
174
+ return of(ev);
175
+ }
176
+ }
177
+ intercept(req, next) {
178
+ if (req.context.get(ALLOW_ANONYMOUS))
179
+ return next.handle(req);
180
+ log('yz.default.interceptor.ts: ', 'request ', req);
181
+ // 统一加前缀
182
+ let url = req.url;
183
+ if (!url.startsWith('https://') && !url.startsWith('http://')) {
184
+ url = this.config.baseUrl + url;
185
+ }
186
+ if (url.includes('.json') && url.includes('assets')) {
187
+ url = req.url;
188
+ }
189
+ if (url.includes('i18n'))
190
+ return next.handle(req);
191
+ // 加入语言头
192
+ const newReq = req.clone({ url, setHeaders: this.getAdditionalHeaders(req.headers) });
193
+ return next.handle(newReq).pipe(mergeMap(ev => {
194
+ // 允许统一对请求错误处理
195
+ if (ev instanceof HttpResponseBase) {
196
+ return this.handleData(ev, newReq, next);
197
+ }
198
+ // 若一切都正常,则后续操作
199
+ return of(ev);
200
+ }), catchError((err) => this.handleData(err, newReq, next)));
201
+ }
202
+ }
203
+ YunzaiDefaultInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: YunzaiDefaultInterceptor, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
204
+ YunzaiDefaultInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: YunzaiDefaultInterceptor });
205
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: YunzaiDefaultInterceptor, decorators: [{
206
+ type: Injectable
207
+ }], ctorParameters: function () { return [{ type: i0.Injector }]; } });
208
+ export { YunzaiDefaultInterceptor as YzDefaultInterceptor, YunzaiDefaultInterceptor };
209
209
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieXVuemFpLWRlZmF1bHQuaW50ZXJjZXB0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9iaXMvbGF5b3V0L3l1bnphaS1kZWZhdWx0LmludGVyY2VwdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFLTCxpQkFBaUIsRUFFakIsWUFBWSxFQUNaLGdCQUFnQixFQUNqQixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFBRSxVQUFVLEVBQVksTUFBTSxlQUFlLENBQUM7QUFDckQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3pDLE9BQU8sRUFBRSxlQUFlLEVBQUUsRUFBRSxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFjLE1BQU0sTUFBTSxDQUFDO0FBRWxILE9BQU8sRUFBRSxnQkFBZ0IsRUFBaUIsZUFBZSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQy9FLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxXQUFXLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDOUQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNyQyxPQUFPLEVBQXdCLG1CQUFtQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDL0UsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3hDLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRW5FLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxjQUFjLENBQUM7O0FBRTlDLE1BQU0sV0FBVyxHQUE4QjtJQUM3QyxHQUFHLEVBQUUsZUFBZTtJQUNwQixHQUFHLEVBQUUsWUFBWTtJQUNqQixHQUFHLEVBQUUscUJBQXFCO0lBQzFCLEdBQUcsRUFBRSxTQUFTO0lBQ2QsR0FBRyxFQUFFLDZCQUE2QjtJQUNsQyxHQUFHLEVB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QUcsRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FDM0UsQ0FBQztJQUNKLENBQUM7O3FIQXRNRyx3QkFBd0I7eUhBQXhCLHdCQUF3QjsyRkFBeEIsd0JBQXdCO2tCQUQ3QixVQUFVOztBQTBNWCxPQUFPLEVBQUUsd0JBQXdCLElBQUksb0JBQW9CLEVBQUUsd0JBQXdCLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEh0dHBFdmVudCxcbiAgSHR0cEhhbmRsZXIsXG4gIEh0dHBJbnRlcmNlcHRvcixcbiAgSHR0cFJlcXVlc3QsXG4gIEh0dHBFcnJvclJlc3BvbnNlLFxuICBIdHRwSGVhZGVycyxcbiAgSHR0cFJlc3BvbnNlLFxuICBIdHRwUmVzcG9uc2VCYXNlXG59IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IEluamVjdGFibGUsIEluamVjdG9yIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBvZiwgdGhyb3dFcnJvciwgY2F0Y2hFcnJvciwgZmlsdGVyLCBtZXJnZU1hcCwgc3dpdGNoTWFwLCB0YWtlLCBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IFlBX1NFUlZJQ0VfVE9LRU4sIElUb2tlblNlcnZpY2UsIEFMTE9XX0FOT05ZTU9VUyB9IGZyb20gJ0B5ZWxvbi9hdXRoJztcbmltcG9ydCB7IFlVTlpBSV9JMThOX1RPS0VOLCBfSHR0cENsaWVudCB9IGZyb20gJ0B5ZWxvbi90aGVtZSc7XG5pbXBvcnQgeyBXSU5ET1cgfSBmcm9tICdAeWVsb24vdXRpbCc7XG5pbXBvcnQgeyBZdW56YWlCdXNpbmVzc0NvbmZpZywgWXVuemFpQ29uZmlnU2VydmljZSB9IGZyb20gJ0B5ZWxvbi91dGlsL2NvbmZpZyc7XG5pbXBvcnQgeyBsb2cgfSBmcm9tICdAeWVsb24vdXRpbC9vdGhlcic7XG5pbXBvcnQgeyBOek5vdGlmaWNhdGlvblNlcnZpY2UgfSBmcm9tICduZy16b3Jyby1hbnRkL25vdGlmaWNhdGlvbic7XG5cbmltcG9ydCB7IG1lcmdlQmlzQ29uZmlnIH0gZnJvbSAnLi9iaXMuY29uZmlnJztcblxuY29uc3QgQ09ERU1FU1NBR0U6IHsgW2tleTogbnVtYmVyXTogc3RyaW5nIH0gPSB7XG4gIDIwMDogJ+acjeWKoeWZqOaIkOWKn+i/lOWbnuivt+axgueahOaVsOaNruOAgicsXG4gIDIwMTogJ+aWsOW7uuaIluS/ruaUueaVsOaNruaIkOWKn+OAgicsXG4gIDIwMjogJ+S4gOS4quivt+axguW3sue7j+i/m+WFpeWQjuWPsOaOkumYn++8iOW8guatpeS7u+WKoe+8ieOAgicsXG4gIDIwNDogJ+WIoOmZpOaVsOaNruaIkOWKn+OAgicsXG4gIDQwMDogJ+WPkeWHuueahOivt+axguaciemUmeivr++8jOacjeWKoeWZqOayoeaciei/m+ihjOaWsOW7uuaIluS/ruaUueaVsOaNrueahOaTjeS9nOOAgicsXG4gIDQwMTogJ+eUqOaIt+ayoeacieadg+mZkO+8iOS7pOeJjOOAgeeUqOaIt+WQjeOAgeWvhueggemUmeivr++8ieOAgicsXG4gIDQwMzogJ+eUqOaIt+W+l+WIsOaOiOadg++8jOS9huaYr+iuv+mXruaYr+iiq+emgeatoueahOOAgicsXG4gIDQwNDogJ+WPkeWHuueahOivt+axgumSiOWvueeahOaYr+S4jeWtmOWcqOeahOiusOW9le+8jOacjeWKoeWZqOayoeaciei/m+ihjOaTjeS9nOOAgicsXG4gIDQwNjogJ+ivt+axgueahOagvOW8j+S4jeWPr+W+l+OAgicsXG4gIDQxMDogJ+ivt+axgueahOi1hOa6kOiiq+awuOS5heWIoOmZpO+8jOS4lOS4jeS8muWGjeW+l+WIsOeahOOAgicsXG4gIDQyMjogJ+W9k+WIm+W7uuS4gOS4quWvueixoeaXtu+8jOWPkeeUn+S4gOS4qumqjOivgemUmeivr+OAgicsXG4gIDUwMDogJ+acjeWKoeWZqOWPkeeUn+mUmeivr++8jOivt+ajgOafpeacjeWKoeWZqOOAgicsXG4gIDUwMjogJ+e9keWFs+mUmeivr+OAgicsXG4gIDUwMzogJ+acjeWKoeS4jeWPr+eUqO+8jOacjeWKoeWZqOaaguaXtui/h+i9veaIlue7tOaKpOOAgicsXG4gIDUwNDogJ+e9keWFs+i2heaXtuOAgidcbn07XG5cbkBJbmplY3RhYmxlKClcbmNsYXNzIFl1bnphaURlZmF1bHRJbnRlcmNlcHRvciBpbXBsZW1lbnRzIEh0dHBJbnRlcmNlcHRvciB7XG4gIHByaXZhdGUganVtcCA9IGZhbHNlO1xuICBwcml2YXRlIHJlZnJlc2hUb2tpbmcgPSBmYWxzZTtcbiAgcHJpdmF0ZSByZWZyZXNoVG9rZW4kOiBCZWhhdmlvclN1YmplY3Q8YW55PiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8YW55PihudWxsKTtcblxuICBwcml2YXRlIGdldCBub3RpZmljYXRpb24oKTogTnpOb3RpZmljYXRpb25TZXJ2aWNlIHtcbiAgICByZXR1cm4gdGhpcy5pbmplY3Rvci5nZXQoTnpOb3RpZmljYXRpb25TZXJ2aWNlKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0IHRva2VuU3J2KCk6IElUb2tlblNlcnZpY2Uge1xuICAgIHJldHVybiB0aGlzLmluamVjdG9yLmdldChZQV9TRVJWSUNFX1RPS0VOKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0IGh0dHAoKTogX0h0dHBDbGllbnQge1xuICAgIHJldHVybiB0aGlzLmluamVjdG9yLmdldChfSHR0cENsaWVudCk7XG4gIH1cblxuICBwcml2YXRlIGdldCBjb25maWcoKTogWXVuemFpQnVzaW5lc3NDb25maWcge1xuICAgIHJldHVybiBtZXJnZUJpc0NvbmZpZyh0aGlzLmluamVjdG9yLmdldChZdW56YWlDb25maWdTZXJ2aWNlKSk7XG4gIH1cblxuICBwcml2YXRlIGdvVG8odXJsOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBzZXRUaW1lb3V0KCgpID0+IHRoaXMuaW5qZWN0b3IuZ2V0KFJvdXRlcikubmF2aWdhdGVCeVVybCh1cmwpKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgaW5qZWN0b3I6IEluamVjdG9yKSB7XG4gICAgaWYgKHRoaXMuY29uZmlnLnJlZnJlc2hUb2tlblR5cGUgPT09ICdhdXRoLXJlZnJlc2gnKSB7XG4gICAgICBjb25zb2xlLmVycm9yKFwiY2FuJ3QgdXNlIGF1dGgtcmVmcmVzaCwgcGxlYXNlIGNoYW5nZSB5ei5kZWZhdWx0LmludGVyY2VwdG9yIHRvIGRlZmF1bHQuaW50ZXJjZXB0b3IhXCIpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY2hlY2tTdGF0dXMoZXY6IEh0dHBSZXNwb25zZUJhc2UpOiB2b2lkIHtcbiAgICBpZiAoKGV2LnN0YXR1cyA+PSAyMDAgJiYgZXYuc3RhdHVzIDwgMzAwKSB8fCBldi5zdGF0dXMgPT09IDQwMSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChldiBpbnN0YW5jZW9mIEh0dHBFcnJvclJlc3BvbnNlICYmIChldi5lcnJvci5tZXNzYWdlIHx8IGV2LmVycm9yLmVycm9yTWVzc2FnZSkpIHtcbiAgICAgIGlmIChldi5lcnJvci5lcnJvck1lc3NhZ2UpIHtcbiAgICAgICAgdGhpcy5ub3RpZmljYXRpb24uZXJyb3IoYOWPkeeUn+S6huS4gOS6m+mUmeivryBgLCBldi5lcnJvci5lcnJvck1lc3NhZ2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5ub3RpZmljYXRpb24uZXJyb3IoYOWPkeeUn+S6huS4gOS6m+mUmeivryBgLCBldi5lcnJvci5tZXNzYWdlKTtcbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoZXYgaW5zdGFuY2VvZiBIdHRwUmVzcG9uc2UgJiYgZXYuYm9keS5lcnJvck1lc3NhZ2UpIHtcbiAgICAgIHRoaXMubm90aWZpY2F0aW9uLmVycm9yKGDlj5HnlJ/kuobkuIDkupvplJnor68gYCwgZXYuYm9keS5lcnJvck1lc3NhZ2UpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBlcnJvcnRleHQgPSBDT0RFTUVTU0FHRVtldi5zdGF0dXNdIHx8IGV2LnN0YXR1c1RleHQ7XG4gICAgdGhpcy5ub3RpZmljYXRpb24uZXJyb3IoYOivt+axgumUmeivryAke2V2LnN0YXR1c306ICR7ZXYudXJsfWAsIGVycm9ydGV4dCk7XG4gIH1cblxuICBwcml2YXRlIFRvTG9naW4oKTogdm9pZCB7XG4gICAgdGhpcy5ub3RpZmljYXRpb24uZXJyb3IoYOacqueZu+W9leaIlueZu+W9leeKtuaAgeW3sui/h+acn++8jDXnp5LlkI7lsIbot7PovazliLDnmbvlvZXpobXpnaLjgIJgLCBgYCk7XG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBsb2NhbFN0b3JhZ2UuY2xlYXIoKTtcbiAgICAgIHRoaXMuaW5qZWN0b3IuZ2V0KFdJTkRPVykubG9jYXRpb24uaHJlZiA9IGAke3RoaXMuY29uZmlnLmJhc2VVcmx9L2Nhcy1wcm94eS9hcHAvbG9nb3V0YDtcbiAgICB9LCA1MDAwKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVBdHRhY2hUb2tlbihyZXE6IEh0dHBSZXF1ZXN0PGFueT4pOiBIdHRwUmVxdWVzdDxhbnk+IHtcbiAgICBjb25zdCB0b2tlbiA9IHRoaXMudG9rZW5TcnYuZ2V0KCk/LnRva2VuO1xuICAgIHJldHVybiByZXEuY2xvbmUoe1xuICAgICAgc2V0SGVhZGVyczoge1xuICAgICAgICBBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7dG9rZW59YFxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSByZWZyZXNoVG9rZW5SZXF1ZXN0KCk6IE9ic2VydmFibGU8YW55PiB7XG4gICAgY29uc3QgbW9kZWwgPSB0aGlzLnRva2VuU3J2LmdldCgpO1xuICAgIGNvbnN0IGZvcm0gPSBuZXcgRm9ybURhdGEoKTtcbiAgICBmb3JtLnNldCgncmVmcmVzaF90b2tlbicsIG1vZGVsPy5yZWZyZXNoVG9rZW4pO1xuICAgIGZvcm0uc2V0KCdncmFudF90eXBlJywgJ3JlZnJlc2hfdG9rZW4nKTtcbiAgICBmb3JtLnNldCgnc2NvcGUnLCAnd2ViYXBwJyk7XG4gICAgbG9nKCd5ei5kZWZhdWx0LmludGVyY2VwdG9yOiB1c2UgdGhlIHJlZnJlc2ggdG9rZW4gdG8gcmVxdWVzdCBhIG5ldyB0b2tlbicsIG1vZGVsPy5yZWZyZXNoVG9rZW4pO1xuICAgIC8vIHJldHVybiB0aGlzLmh0dHAucG9zdChgL2F1dGgvdXNlci90b2tlbi9yZWZyZXNoP19hbGxvd19hbm9ueW1vdXM9dHJ1ZWAsIGZvcm0pO1xuICAgIHJldHVybiB0aGlzLmh0dHAucG9zdChgL2F1dGgvb2F1dGgvZ2V0T3JDcmVhdGVUb2tlbi93ZWJhcHBgLCBmb3JtKTtcbiAgfVxuXG4gIHByaXZhdGUgdHJ5UmVmcmVzaFRva2VuKGV2OiBIdHRwUmVzcG9uc2VCYXNlLCByZXE6IEh0dHBSZXF1ZXN0PGFueT4sIG5leHQ6IEh0dHBIYW5kbGVyKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICAvLyDov57liLfmlrBUb2tlbueahOivt+axgumDvemUmeS6hu+8jOmCo+WwseaYr+ecn+mUmeS6hlxuICAgIGlmIChbJy9hdXRoL29hdXRoL2dldE9yQ3JlYXRlVG9rZW4vd2ViYXBwJ10uc29tZSh1cmwgPT4gcmVxLnVybC5pbmNsdWRlcyh1cmwpKSkge1xuICAgICAgdGhpcy5Ub0xvZ2luKCk7XG4gICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBldik7XG4gICAgfVxuXG4gICAgLy8g5q2j5Zyo5Yi35pawdG9rZW7vvIzmiYDmnInlhbbku5bor7fmsYLmjpLpmJ9cbiAgICBpZiAodGhpcy5yZWZyZXNoVG9raW5nKSB7XG4gICAgICByZXR1cm4gdGhpcy5yZWZyZXNoVG9rZW4kLnBpcGUoXG4gICAgICAgIGZpbHRlcih2ID0+ICEhdiksXG4gICAgICAgIHRha2UoMSksXG4gICAgICAgIHN3aXRjaE1hcCgoKSA9PiBuZXh0LmhhbmRsZSh0aGlzLnJlQXR0YWNoVG9rZW4ocmVxKSkpXG4gICAgICApO1xuICAgIH1cblxuICAgIC8v5bCd6K+V6LCD55So5Yi35pawIFRva2VuXG4gICAgdGhpcy5yZWZyZXNoVG9raW5nID0gdHJ1ZTtcbiAgICB0aGlzLnJlZnJlc2hUb2tlbiQubmV4dChudWxsKTtcblxuICAgIC8vIOWkhOeQhlRva2VuXG4gICAgcmV0dXJuIHRoaXMucmVmcmVzaFRva2VuUmVxdWVzdCgpLnBpcGUoXG4gICAgICBzd2l0Y2hNYXAocmVzID0+IHtcbiAgICAgICAgbG9nKCd5ei5kZWZhdWx0LmludGVyY2VwdG9yOiByZWZyZXNoIHRva2VuIGFjY2Vzc2VkIC0+ICcsIHJlcyk7XG4gICAgICAgIC8vIOmHjeaWsOS/neWtmOaWsCB0b2tlblxuICAgICAgICBjb25zdCB7IGFjY2Vzc190b2tlbiwgZXhwaXJlc19pbiwgcmVmcmVzaF90b2tlbiwgc2NvcGUsIHRva2VuX3R5cGUgfSA9IHJlcztcbiAgICAgICAgdGhpcy50b2tlblNydi5zZXQoe1xuICAgICAgICAgIHRva2VuOiBhY2Nlc3NfdG9rZW4sXG4gICAgICAgICAgZXhwaXJlZDogZXhwaXJlc19pbixcbiAgICAgICAgICByZWZyZXNoVG9rZW46IHJlZnJlc2hfdG9rZW4sXG4gICAgICAgICAgdG9rZW5UeXBlOiB0b2tlbl90eXBlLFxuICAgICAgICAgIHNjb3BlXG4gICAgICAgIH0pO1xuICAgICAgICAvLyDpgJrnn6XlkI7nu63or7fmsYLnu6fnu63miafooYxcbiAgICAgICAgdGhpcy5yZWZyZXNoVG9raW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMucmVmcmVzaFRva2VuJC5uZXh0KHJlcyk7XG4gICAgICAgIC8vIOmHjeaWsOWPkei1t+ivt+axglxuICAgICAgICByZXR1cm4gbmV4dC5oYW5kbGUodGhpcy5yZUF0dGFjaFRva2VuKHJlcSkpO1xuICAgICAgfSksXG4gICAgICBjYXRjaEVycm9yKGVyciA9PiB7XG4gICAgICAgIHRoaXMucmVmcmVzaFRva2luZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLlRvTG9naW4oKTtcbiAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gZXJyKTtcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0QWRkaXRpb25hbEhlYWRlcnMoaGVhZGVycz86IEh0dHBIZWFkZXJzKTogeyBbbmFtZTogc3RyaW5nXTogc3RyaW5nIH0ge1xuICAgIGNvbnN0IHJlczogeyBbbmFtZTogc3RyaW5nXTogc3RyaW5nIH0gPSB7fTtcbiAgICBjb25zdCBsYW5nID0gdGhpcy5pbmplY3Rvci5nZXQoWVVOWkFJX0kxOE5fVE9LRU4pLmN1cnJlbnRMYW5nO1xuICAgIGlmICghaGVhZGVycz8uaGFzKCdBY2NlcHQtTGFuZ3VhZ2UnKSAmJiBsYW5nKSB7XG4gICAgICByZXNbJ0FjY2VwdC1MYW5ndWFnZSddID0gbGFuZztcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlRGF0YShldjogSHR0cFJlc3BvbnNlQmFzZSwgcmVxOiBIdHRwUmVxdWVzdDxhbnk+LCBuZXh0OiBIdHRwSGFuZGxlcik6IE9ic2VydmFibGU8YW55PiB7XG4gICAgdGhpcy5jaGVja1N0YXR1cyhldik7XG4gICAgc3dpdGNoIChldi5zdGF0dXMpIHtcbiAgICAgIGNhc2UgMjAwOlxuICAgICAgICByZXR1cm4gb2YoZXYpO1xuICAgICAgY2FzZSA0MDE6XG4gICAgICAgIGlmICh0aGlzLmNvbmZpZy5yZWZyZXNoVG9rZW5FbmFibGVkICYmIHRoaXMuY29uZmlnLnJlZnJlc2hUb2tlblR5cGUgPT09ICdyZS1yZXF1ZXN0Jykge1xuICAgICAgICAgIGNvbnN0IHVuQXV0aG9yaXphdGlvblJlcSA9IHJlcS5jbG9uZSgpO1xuICAgICAgICAgIHVuQXV0aG9yaXphdGlvblJlcS5oZWFkZXJzLmRlbGV0ZSgnQXV0aG9yaXphdGlvbicpO1xuICAgICAgICAgIHJldHVybiB0aGlzLnRyeVJlZnJlc2hUb2tlbihldiwgdW5BdXRob3JpemF0aW9uUmVxLCBuZXh0KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLlRvTG9naW4oKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDQwMzpcbiAgICAgIGNhc2UgNDA0OlxuICAgICAgY2FzZSA1MDA6XG4gICAgICAgIGlmICh0aGlzLmp1bXApIHtcbiAgICAgICAgICB0aGlzLmdvVG8oYC9leGNlcHRpb24vJHtldi5zdGF0dXN9YCk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBpZiAoZXYgaW5zdGFuY2VvZiBIdHRwRXJyb3JSZXNwb25zZSkge1xuICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICfmnKrlj6/nn6XplJnor6/vvIzlpKfpg6jliIbmmK/nlLHkuo7lkI7nq6/kuI3mlK/mjIHot6jln59DT1JT5oiW5peg5pWI6YWN572u5byV6LW377yM6K+35Y+C6ICDIGh0dHBzOi8vbmcueXVuemFpbmZvLmNvbS9kb2NzL3NlcnZlciDop6PlhrPot6jln5/pl67popgnLFxuICAgICAgICAgICAgZXZcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBpZiAoZXYgaW5zdGFuY2VvZiBIdHRwRXJyb3JSZXNwb25zZSkge1xuICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gZXYpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gb2YoZXYpO1xuICAgIH1cbiAgfVxuXG4gIGludGVyY2VwdChyZXE6IEh0dHBSZXF1ZXN0PGFueT4sIG5leHQ6IEh0dHBIYW5kbGVyKTogT2JzZXJ2YWJsZTxIdHRwRXZlbnQ8YW55Pj4ge1xuICAgIGlmIChyZXEuY29udGV4dC5nZXQoQUxMT1dfQU5PTllNT1VTKSkgcmV0dXJuIG5leHQuaGFuZGxlKHJlcSk7XG4gICAgbG9nKCd5ei5kZWZhdWx0LmludGVyY2VwdG9yLnRzOiAnLCAncmVxdWVzdCAnLCByZXEpO1xuICAgIC8vIOe7n+S4gOWKoOWJjee8gFxuICAgIGxldCB1cmwgPSByZXEudXJsO1xuICAgIGlmICghdXJsLnN0YXJ0c1dpdGgoJ2h0dHBzOi8vJykgJiYgIXVybC5zdGFydHNXaXRoKCdodHRwOi8vJykpIHtcbiAgICAgIHVybCA9IHRoaXMuY29uZmlnLmJhc2VVcmwgKyB1cmw7XG4gICAgfVxuICAgIGlmICh1cmwuaW5jbHVkZXMoJy5qc29uJykgJiYgdXJsLmluY2x1ZGVzKCdhc3NldHMnKSkge1xuICAgICAgdXJsID0gcmVxLnVybDtcbiAgICB9XG4gICAgaWYgKHVybC5pbmNsdWRlcygnaTE4bicpKSByZXR1cm4gbmV4dC5oYW5kbGUocmVxKTtcbiAgICAvLyDliqDlhaXor63oqIDlpLRcbiAgICBjb25zdCBuZXdSZXEgPSByZXEuY2xvbmUoeyB1cmwsIHNldEhlYWRlcnM6IHRoaXMuZ2V0QWRkaXRpb25hbEhlYWRlcnMocmVxLmhlYWRlcnMpIH0pO1xuICAgIHJldHVybiBuZXh0LmhhbmRsZShuZXdSZXEpLnBpcGUoXG4gICAgICBtZXJnZU1hcChldiA9PiB7XG4gICAgICAgIC8vIOWFgeiuuOe7n+S4gOWvueivt+axgumUmeivr+WkhOeQhlxuICAgICAgICBpZiAoZXYgaW5zdGFuY2VvZiBIdHRwUmVzcG9uc2VCYXNlKSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlRGF0YShldiwgbmV3UmVxLCBuZXh0KTtcbiAgICAgICAgfVxuICAgICAgICAvLyDoi6XkuIDliIfpg73mraPluLjvvIzliJnlkI7nu63mk43kvZxcbiAgICAgICAgcmV0dXJuIG9mKGV2KTtcbiAgICAgIH0pLFxuICAgICAgY2F0Y2hFcnJvcigoZXJyOiBIdHRwRXJyb3JSZXNwb25zZSkgPT4gdGhpcy5oYW5kbGVEYXRhKGVyciwgbmV3UmVxLCBuZXh0KSlcbiAgICApO1xuICB9XG59XG5cbmV4cG9ydCB7IFl1bnphaURlZmF1bHRJbnRlcmNlcHRvciBhcyBZekRlZmF1bHRJbnRlcmNlcHRvciwgWXVuemFpRGVmYXVsdEludGVyY2VwdG9yIH07XG4iXX0=