@arsedizioni/ars-utils 18.2.338 → 18.2.340

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.
@@ -3,8 +3,15 @@ import { Observable } from 'rxjs';
3
3
  import * as i0 from "@angular/core";
4
4
  export declare class ClipperAuthInterceptor implements HttpInterceptor {
5
5
  private clipperService;
6
+ private broadcastService;
6
7
  private dialogService;
7
8
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>;
9
+ /**
10
+ * Handle 401 error
11
+ * @param request : the request
12
+ * @param next : the http handler
13
+ */
14
+ private handle401Error;
8
15
  /**
9
16
  * Add token to request
10
17
  * @param request : the request
@@ -1,23 +1,18 @@
1
1
  import { OnDestroy, Signal } from '@angular/core';
2
2
  import { ApiResult, FolderTree, NameValueItem } from '@arsedizioni/ars-utils/core';
3
3
  import { LoginOAuthType } from '@arsedizioni/ars-utils/ui.oauth';
4
- import { Observable, Subscription } from 'rxjs';
4
+ import { Subscription } from 'rxjs';
5
5
  import { ClipperDashboard, ClipperDocumentInfo, ClipperDocumentStructure, ClipperDocumentUpdateStateParams, ClipperExportDocumentsParams, ClipperLoginInfo, ClipperLoginResult, ClipperModule, ClipperOTPInfo, ClipperQueryArsEventsParams, ClipperQueryArsEventsResult, ClipperReferencesSearchParams, ClipperSearchFacetsResult, ClipperSearchParams, ClipperSearchResult, ClipperSendDocumentsByEmailParams, ClipperTaxonomyParams, ClipperUserLink, ClipperUserSearch } from '../definitions';
6
6
  import * as i0 from "@angular/core";
7
7
  export declare class ClipperService implements OnDestroy {
8
- private readonly REFRESH_INTERVAL;
9
8
  private httpClient;
9
+ private broadcastServiceSubscription?;
10
10
  private broadcastService;
11
11
  private dialogService;
12
- private tokenRefreshInterval;
13
- private tokenRefreshTimer?;
14
- private tokenRefreshTimerSubscription?;
15
- private broadcastServiceSubscription?;
16
- private refreshing;
17
- private _loginInfo;
18
- get loginInfo(): ClipperLoginInfo;
19
12
  private _serviceUri;
20
13
  get serviceUri(): string;
14
+ private _loginInfo;
15
+ get loginInfo(): ClipperLoginInfo;
21
16
  readonly loggedIn: import("@angular/core").WritableSignal<boolean>;
22
17
  readonly loggingIn: import("@angular/core").WritableSignal<boolean>;
23
18
  readonly snapshot: import("@angular/core").WritableSignal<ClipperSearchResult>;
@@ -27,28 +22,17 @@ export declare class ClipperService implements OnDestroy {
27
22
  readonly bagTotal: Signal<number>;
28
23
  readonly visible: import("@angular/core").WritableSignal<boolean>;
29
24
  readonly supportsRS: import("@angular/core").WritableSignal<boolean>;
30
- constructor();
31
25
  ngOnDestroy(): void;
32
26
  /**
33
27
  * Initialize service
34
28
  * @param serviceUri : the service uri
35
- * @param tokenRefreshInterval : the token refresh interval
36
29
  */
37
- initialize(serviceUri?: string | null | undefined, tokenRefreshInterval?: number | null | undefined): void;
38
- /**
39
- * Set JWT token
40
- * @param token : token
41
- */
42
- private setToken;
30
+ initialize(serviceUri: string): void;
43
31
  /**
44
32
  * Set JWT tokens
45
- * @param valur : token
33
+ * @param value : the login result
46
34
  */
47
- private setToken2;
48
- /**
49
- * Enable JWT token auto refresh
50
- */
51
- private enableTokenRefresh;
35
+ private setToken;
52
36
  /**
53
37
  * Return current JWT token
54
38
  * @param refresh: true to get the refresh token. Default is false.
@@ -63,21 +47,11 @@ export declare class ClipperService implements OnDestroy {
63
47
  * @param oauthAccessToken: the optional OAuth2 access token
64
48
  * @returns: the login result
65
49
  */
66
- login(email?: string | null | undefined, password?: string | null | undefined, remember?: boolean | null | undefined, oauth?: LoginOAuthType | null | undefined, oauthAccessToken?: string | null | undefined): Observable<ApiResult<ClipperLoginResult>>;
67
- /**
68
- * Perform login
69
- * @param email: the optioanl email if using OAuth2
70
- * @parma password: the optional password if using OAuth2
71
- * @param remember: remember credentials
72
- * @param oauth: the optional open authentication supported
73
- * @param oauthAccessToken: the optional OAuth2 access token
74
- * @returns: the login result
75
- */
76
- login2(email?: string | null | undefined, password?: string | null | undefined, remember?: boolean | null | undefined, oauth?: LoginOAuthType | null | undefined, oauthAccessToken?: string | null | undefined): Observable<ApiResult<ClipperLoginResult>>;
50
+ login(email?: string | null | undefined, password?: string | null | undefined, remember?: boolean | null | undefined, oauth?: LoginOAuthType | null | undefined, oauthAccessToken?: string | null | undefined): import("rxjs").Observable<ApiResult<ClipperLoginResult>>;
77
51
  /**
78
52
  * Perform logout
79
53
  */
80
- logout(): Observable<any>;
54
+ logout(): import("rxjs").Observable<any>;
81
55
  /**
82
56
  * Reset login refresh timer and login state
83
57
  */
@@ -86,95 +60,91 @@ export declare class ClipperService implements OnDestroy {
86
60
  * Clear login data
87
61
  */
88
62
  clear(): void;
89
- /**
90
- * Perform token refresh
91
- */
92
- private refresh;
93
63
  /**
94
64
  * Perform token refresh
95
65
  */
96
- refresh2(): Observable<void>;
66
+ refresh(): import("rxjs").Observable<void>;
97
67
  /**
98
68
  * Get a new one time password
99
69
  * @param id: the optional repository id
100
70
  */
101
- newOTP(id: string): Observable<ApiResult<ClipperOTPInfo>>;
71
+ newOTP(id: string): import("rxjs").Observable<ApiResult<ClipperOTPInfo>>;
102
72
  /**
103
73
  * Load Ars events calendar
104
74
  */
105
- events(params: ClipperQueryArsEventsParams): Observable<ApiResult<ClipperQueryArsEventsResult>>;
75
+ events(params: ClipperQueryArsEventsParams): import("rxjs").Observable<ApiResult<ClipperQueryArsEventsResult>>;
106
76
  /**
107
77
  * Query documents
108
78
  */
109
- query(params: ClipperSearchParams): Observable<ApiResult<ClipperSearchResult>>;
79
+ query(params: ClipperSearchParams): import("rxjs").Observable<ApiResult<ClipperSearchResult>>;
110
80
  /**
111
81
  * Get facets for a query
112
82
  */
113
- queryFacets(params: ClipperSearchParams): Observable<ApiResult<ClipperSearchFacetsResult>>;
83
+ queryFacets(params: ClipperSearchParams): import("rxjs").Observable<ApiResult<ClipperSearchFacetsResult>>;
114
84
  /**
115
85
  * Update document state
116
86
  */
117
- updateState(params: ClipperDocumentUpdateStateParams): Observable<ApiResult<number>>;
87
+ updateState(params: ClipperDocumentUpdateStateParams): import("rxjs").Observable<ApiResult<number>>;
118
88
  /**
119
89
  * Export a document in pdf format
120
90
  */
121
- exportPdf(id: string): Observable<Blob>;
91
+ exportPdf(id: string): import("rxjs").Observable<Blob>;
122
92
  /**
123
93
  * Export document list (query or selected items) or export deadlines as ics
124
94
  */
125
- export(params: ClipperExportDocumentsParams): Observable<Blob>;
95
+ export(params: ClipperExportDocumentsParams): import("rxjs").Observable<Blob>;
126
96
  /**
127
97
  * Send documents link by email
128
98
  */
129
- sendTo(params: ClipperSendDocumentsByEmailParams): Observable<ApiResult<number>>;
99
+ sendTo(params: ClipperSendDocumentsByEmailParams): import("rxjs").Observable<ApiResult<number>>;
130
100
  /**
131
101
  * Display a page the full document report
132
102
  */
133
- report(id: string): Observable<Blob>;
103
+ report(id: string): import("rxjs").Observable<Blob>;
134
104
  /**
135
105
  * Get document comment
136
106
  */
137
- comment(id: string): Observable<ApiResult<string>>;
107
+ comment(id: string): import("rxjs").Observable<ApiResult<string>>;
138
108
  /**
139
109
  * Get document info
140
110
  */
141
- info(id: string): Observable<ApiResult<ClipperDocumentInfo>>;
111
+ info(id: string): import("rxjs").Observable<ApiResult<ClipperDocumentInfo>>;
142
112
  /**
143
113
  * Get document structure
144
114
  */
145
- index(id: string): Observable<ApiResult<ClipperDocumentStructure>>;
115
+ index(id: string): import("rxjs").Observable<ApiResult<ClipperDocumentStructure>>;
146
116
  /**
147
117
  * Get document last update
148
118
  */
149
- lastUpdate(id: string): Observable<ApiResult<string>>;
119
+ lastUpdate(id: string): import("rxjs").Observable<ApiResult<string>>;
150
120
  /**
151
121
  * Query document references
152
122
  */
153
- references(params: ClipperReferencesSearchParams): Observable<ApiResult<ClipperSearchResult>>;
123
+ references(params: ClipperReferencesSearchParams): import("rxjs").Observable<ApiResult<ClipperSearchResult>>;
154
124
  /**
155
125
  * Get facets for a document references
156
126
  */
157
- referencesFacets(params: ClipperReferencesSearchParams): Observable<ApiResult<ClipperSearchFacetsResult>>;
127
+ referencesFacets(params: ClipperReferencesSearchParams): import("rxjs").Observable<ApiResult<ClipperSearchFacetsResult>>;
158
128
  /**
159
129
  * Get document juris articles
160
130
  */
161
- jurisArticles(params: ClipperSearchParams): Observable<ApiResult<ClipperSearchResult>>;
131
+ jurisArticles(params: ClipperSearchParams): import("rxjs").Observable<ApiResult<ClipperSearchResult>>;
162
132
  /**
163
133
  * Get calendar snapshot based on the deadlines
164
134
  */
165
- calendarSnapshot(params: any): Observable<ApiResult<any>>;
135
+ calendarSnapshot(params: any): import("rxjs").Observable<ApiResult<any>>;
166
136
  /**
167
137
  * Retrieve the taxonomy
168
138
  */
169
- getTaxonomy(params?: ClipperTaxonomyParams | null): Observable<ApiResult<FolderTree>>;
139
+ getTaxonomy(params?: ClipperTaxonomyParams | null): import("rxjs").Observable<ApiResult<FolderTree>>;
170
140
  /**
171
141
  * Retrieve topics
172
142
  */
173
- getTopics(): Observable<ApiResult<NameValueItem<string>[]>>;
143
+ getTopics(): import("rxjs").Observable<ApiResult<NameValueItem<string>[]>>;
174
144
  /**
175
145
  * Retrieve tags
176
146
  */
177
- getTags(): Observable<ApiResult<NameValueItem<string>[]>>;
147
+ getTags(): import("rxjs").Observable<ApiResult<NameValueItem<string>[]>>;
178
148
  /**
179
149
  * Retrieve current dashboard
180
150
  */
@@ -189,12 +159,12 @@ export declare class ClipperService implements OnDestroy {
189
159
  * Save a user link
190
160
  * @param item: the user link
191
161
  */
192
- saveLink(item: ClipperUserLink): Observable<ApiResult<boolean>>;
162
+ saveLink(item: ClipperUserLink): import("rxjs").Observable<ApiResult<boolean>>;
193
163
  /**
194
164
  * Delete a user link
195
165
  * @param item: the user link
196
166
  */
197
- deleteLink(item: ClipperUserLink): Observable<ApiResult<boolean>>;
167
+ deleteLink(item: ClipperUserLink): import("rxjs").Observable<ApiResult<boolean>>;
198
168
  /**
199
169
  * Load working documents
200
170
  */
@@ -217,17 +187,17 @@ export declare class ClipperService implements OnDestroy {
217
187
  * Load working searches
218
188
  * @param: module: the module to load searches for
219
189
  */
220
- loadSearches(module: ClipperModule): Observable<ApiResult<ClipperUserSearch[]>>;
190
+ loadSearches(module: ClipperModule): import("rxjs").Observable<ApiResult<ClipperUserSearch[]>>;
221
191
  /**
222
192
  * Save a working search
223
193
  * @param documentIds : the document ids to add
224
194
  */
225
- saveSearch(params: ClipperUserSearch): Observable<ApiResult<ClipperUserSearch>>;
195
+ saveSearch(params: ClipperUserSearch): import("rxjs").Observable<ApiResult<ClipperUserSearch>>;
226
196
  /**
227
197
  * Remove one working search
228
198
  * @param id : the id to remove
229
199
  */
230
- deleteSearch(id: number): Observable<ApiResult<number>>;
200
+ deleteSearch(id: number): import("rxjs").Observable<ApiResult<number>>;
231
201
  static ɵfac: i0.ɵɵFactoryDeclaration<ClipperService, never>;
232
202
  static ɵprov: i0.ɵɵInjectableDeclaration<ClipperService>;
233
203
  }
@@ -1,49 +1,52 @@
1
+ import { HttpErrorResponse } from '@angular/common/http';
1
2
  import { Injectable, inject } from '@angular/core';
2
3
  import { DialogService } from '@arsedizioni/ars-utils/ui';
3
- import { catchError, throwError } from 'rxjs';
4
+ import { catchError, switchMap, throwError } from 'rxjs';
4
5
  import { ClipperService } from '../services/clipper.service';
6
+ import { BroadcastService } from '@arsedizioni/ars-utils/core';
7
+ import { ClipperMessages } from '../messages';
5
8
  import * as i0 from "@angular/core";
6
9
  export class ClipperAuthInterceptor {
7
10
  constructor() {
8
11
  this.clipperService = inject(ClipperService);
12
+ this.broadcastService = inject(BroadcastService);
9
13
  this.dialogService = inject(DialogService);
10
14
  }
11
15
  intercept(request, next) {
12
16
  if (request.url.startsWith(this.clipperService.serviceUri)) {
13
17
  request = request.clone({ withCredentials: true });
14
18
  return next.handle(this.addTokenToRequest(request))
15
- .pipe(catchError((err) => {
16
- // Get the message
17
- let message = err.error?.message || err.message || "Impossibile eseguire l'operazione richiesta.";
18
- let invalidSession = err.status === 401;
19
- switch (err.status) {
20
- case 0:
21
- case 500:
22
- case 502:
23
- case 503:
24
- case 504:
25
- message = null; // No messages
26
- break;
27
- case 403:
28
- message = "<p>Non hai i permessi necessari per eseguire l'operazione richiesta.</p>";
29
- break;
30
- default:
31
- message = '<p>' + message.replaceAll('\r\n', '</p><p>') + '</p>';
32
- break;
19
+ .pipe(catchError(error => {
20
+ if (error instanceof HttpErrorResponse &&
21
+ !request.url.includes("/login") &&
22
+ error.status === 401) {
23
+ return this.handle401Error(request, next);
33
24
  }
34
- // Display message
35
- if (message) {
36
- setTimeout(() => {
37
- this.dialogService.error(message, null, 'Errore in Clipper', 'Ok', 500, invalidSession ? 5000 : null).afterClosed().subscribe(() => {
38
- if (invalidSession) {
39
- if (this.clipperService.loggedIn()) {
40
- this.clipperService.reset();
41
- }
42
- }
43
- });
44
- }, 250);
45
- }
46
- return throwError(() => err);
25
+ // Show a message
26
+ const invalidSession = error.status == "403";
27
+ this.dialogService.clearBusy();
28
+ this.dialogService.error("<p>" + (error.error?.message ?? error.message ?? "Impossibile eseguire l'operazione richiesta.").replaceAll("\r\n", "</p><p>") + "</p>", null, "Errore in Clipper", undefined, undefined, invalidSession ? 5000 : 15000).afterClosed().subscribe(() => {
29
+ if (invalidSession) {
30
+ this.clipperService.clear();
31
+ this.broadcastService.sendMessage(ClipperMessages.LOGOUT);
32
+ }
33
+ });
34
+ return throwError(() => error);
35
+ }));
36
+ }
37
+ return next.handle(request);
38
+ }
39
+ /**
40
+ * Handle 401 error
41
+ * @param request : the request
42
+ * @param next : the http handler
43
+ */
44
+ handle401Error(request, next) {
45
+ if (this.clipperService.loggedIn()) {
46
+ return this.clipperService.refresh().pipe(switchMap(() => {
47
+ return next.handle(this.addTokenToRequest(request));
48
+ }), catchError(error => {
49
+ return throwError(() => error);
47
50
  }));
48
51
  }
49
52
  return next.handle(request);
@@ -74,4 +77,4 @@ export class ClipperAuthInterceptor {
74
77
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: ClipperAuthInterceptor, decorators: [{
75
78
  type: Injectable
76
79
  }] });
77
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5pbnRlcmNlcHRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2Fycy11dGlscy9jbGlwcGVyLmNvbW1vbi9jb21tb24vaW50ZXJjZXB0b3JzL2F1dGguaW50ZXJjZXB0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbkQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzFELE9BQU8sRUFBYyxVQUFVLEVBQUUsVUFBVSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzFELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQzs7QUFHN0QsTUFBTSxPQUFPLHNCQUFzQjtJQURuQztRQUVVLG1CQUFjLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3hDLGtCQUFhLEdBQUcsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0tBd0UvQztJQXRFQyxTQUFTLENBQ1AsT0FBeUIsRUFDekIsSUFBaUI7UUFFakIsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7WUFDM0QsT0FBTyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztZQUNuRCxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxDQUFDO2lCQUNoRCxJQUFJLENBQ0gsVUFBVSxDQUFDLENBQUMsR0FBUSxFQUFFLEVBQUU7Z0JBQ3RCLGtCQUFrQjtnQkFDbEIsSUFBSSxPQUFPLEdBQUcsR0FBRyxDQUFDLEtBQUssRUFBRSxPQUFPLElBQUksR0FBRyxDQUFDLE9BQU8sSUFBSSw4Q0FBOEMsQ0FBQztnQkFDbEcsSUFBSSxjQUFjLEdBQUcsR0FBRyxDQUFDLE1BQU0sS0FBSyxHQUFHLENBQUM7Z0JBQ3hDLFFBQVEsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDO29CQUNuQixLQUFLLENBQUMsQ0FBQztvQkFDUCxLQUFLLEdBQUcsQ0FBQztvQkFDVCxLQUFLLEdBQUcsQ0FBQztvQkFDVCxLQUFLLEdBQUcsQ0FBQztvQkFDVCxLQUFLLEdBQUc7d0JBQ04sT0FBTyxHQUFHLElBQUksQ0FBQyxDQUFDLGNBQWM7d0JBQzlCLE1BQU07b0JBQ1IsS0FBSyxHQUFHO3dCQUNOLE9BQU8sR0FBRywwRUFBMEUsQ0FBQzt3QkFDckYsTUFBTTtvQkFDUjt3QkFDRSxPQUFPLEdBQUcsS0FBSyxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLFNBQVMsQ0FBQyxHQUFHLE1BQU0sQ0FBQzt3QkFDakUsTUFBTTtnQkFDVixDQUFDO2dCQUNELGtCQUFrQjtnQkFDbEIsSUFBSSxPQUFPLEVBQUUsQ0FBQztvQkFDWixVQUFVLENBQUMsR0FBRyxFQUFFO3dCQUNkLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsbUJBQW1CLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxjQUFjLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRTs0QkFDakksSUFBSSxjQUFjLEVBQUUsQ0FBQztnQ0FDbkIsSUFBSSxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUM7b0NBQ25DLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFFLENBQUM7Z0NBQzlCLENBQUM7NEJBQ0gsQ0FBQzt3QkFDSCxDQUFDLENBQUMsQ0FBQztvQkFDTCxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7Z0JBQ1YsQ0FBQztnQkFFRCxPQUFPLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUMvQixDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ1YsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM5QixDQUFDO0lBR0Q7Ozs7T0FJRztJQUNLLGlCQUFpQixDQUN2QixPQUF5QixFQUN6QixRQUFnQixJQUFJO1FBRXBCLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1lBQzNELElBQUksQ0FBQyxLQUFLO2dCQUFFLEtBQUssR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ25ELElBQUksS0FBSyxFQUFFLENBQUM7Z0JBQ1YsT0FBTyxPQUFPLENBQUMsS0FBSyxDQUFDO29CQUNuQixVQUFVLEVBQUU7d0JBQ1YsYUFBYSxFQUFFLFNBQVMsR0FBRyxLQUFLO3dCQUNoQyxhQUFhLEVBQUUsYUFBYTtxQkFDN0I7aUJBQ0YsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztRQUNILENBQUM7UUFDRCxPQUFPLE9BQU8sQ0FBQztJQUNqQixDQUFDOzhHQXhFVSxzQkFBc0I7a0hBQXRCLHNCQUFzQjs7MkZBQXRCLHNCQUFzQjtrQkFEbEMsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEh0dHBFdmVudCwgSHR0cEhhbmRsZXIsIEh0dHBJbnRlcmNlcHRvciwgSHR0cFJlcXVlc3QgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XHJcbmltcG9ydCB7IEluamVjdGFibGUsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBEaWFsb2dTZXJ2aWNlIH0gZnJvbSAnQGFyc2VkaXppb25pL2Fycy11dGlscy91aSc7XHJcbmltcG9ydCB7IE9ic2VydmFibGUsIGNhdGNoRXJyb3IsIHRocm93RXJyb3IgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgQ2xpcHBlclNlcnZpY2UgfSBmcm9tICcuLi9zZXJ2aWNlcy9jbGlwcGVyLnNlcnZpY2UnO1xyXG5cclxuQEluamVjdGFibGUoKVxyXG5leHBvcnQgY2xhc3MgQ2xpcHBlckF1dGhJbnRlcmNlcHRvciBpbXBsZW1lbnRzIEh0dHBJbnRlcmNlcHRvciB7XHJcbiAgcHJpdmF0ZSBjbGlwcGVyU2VydmljZSA9IGluamVjdChDbGlwcGVyU2VydmljZSk7XHJcbiAgcHJpdmF0ZSBkaWFsb2dTZXJ2aWNlID0gaW5qZWN0KERpYWxvZ1NlcnZpY2UpO1xyXG5cclxuICBpbnRlcmNlcHQoXHJcbiAgICByZXF1ZXN0OiBIdHRwUmVxdWVzdDxhbnk+LFxyXG4gICAgbmV4dDogSHR0cEhhbmRsZXJcclxuICApOiBPYnNlcnZhYmxlPEh0dHBFdmVudDxhbnk+PiB7XHJcbiAgICBpZiAocmVxdWVzdC51cmwuc3RhcnRzV2l0aCh0aGlzLmNsaXBwZXJTZXJ2aWNlLnNlcnZpY2VVcmkpKSB7XHJcbiAgICAgIHJlcXVlc3QgPSByZXF1ZXN0LmNsb25lKHsgd2l0aENyZWRlbnRpYWxzOiB0cnVlIH0pO1xyXG4gICAgICByZXR1cm4gbmV4dC5oYW5kbGUodGhpcy5hZGRUb2tlblRvUmVxdWVzdChyZXF1ZXN0KSlcclxuICAgICAgICAucGlwZShcclxuICAgICAgICAgIGNhdGNoRXJyb3IoKGVycjogYW55KSA9PiB7XHJcbiAgICAgICAgICAgIC8vIEdldCB0aGUgbWVzc2FnZVxyXG4gICAgICAgICAgICBsZXQgbWVzc2FnZSA9IGVyci5lcnJvcj8ubWVzc2FnZSB8fCBlcnIubWVzc2FnZSB8fCBcIkltcG9zc2liaWxlIGVzZWd1aXJlIGwnb3BlcmF6aW9uZSByaWNoaWVzdGEuXCI7XHJcbiAgICAgICAgICAgIGxldCBpbnZhbGlkU2Vzc2lvbiA9IGVyci5zdGF0dXMgPT09IDQwMTtcclxuICAgICAgICAgICAgc3dpdGNoIChlcnIuc3RhdHVzKSB7XHJcbiAgICAgICAgICAgICAgY2FzZSAwOlxyXG4gICAgICAgICAgICAgIGNhc2UgNTAwOlxyXG4gICAgICAgICAgICAgIGNhc2UgNTAyOlxyXG4gICAgICAgICAgICAgIGNhc2UgNTAzOlxyXG4gICAgICAgICAgICAgIGNhc2UgNTA0OlxyXG4gICAgICAgICAgICAgICAgbWVzc2FnZSA9IG51bGw7IC8vIE5vIG1lc3NhZ2VzXHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICBjYXNlIDQwMzpcclxuICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBcIjxwPk5vbiBoYWkgaSBwZXJtZXNzaSBuZWNlc3NhcmkgcGVyIGVzZWd1aXJlIGwnb3BlcmF6aW9uZSByaWNoaWVzdGEuPC9wPlwiO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSAnPHA+JyArIG1lc3NhZ2UucmVwbGFjZUFsbCgnXFxyXFxuJywgJzwvcD48cD4nKSArICc8L3A+JztcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIC8vIERpc3BsYXkgbWVzc2FnZVxyXG4gICAgICAgICAgICBpZiAobWVzc2FnZSkge1xyXG4gICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5kaWFsb2dTZXJ2aWNlLmVycm9yKG1lc3NhZ2UsIG51bGwsICdFcnJvcmUgaW4gQ2xpcHBlcicsICdPaycsIDUwMCwgaW52YWxpZFNlc3Npb24gPyA1MDAwIDogbnVsbCkuYWZ0ZXJDbG9zZWQoKS5zdWJzY3JpYmUoKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICBpZiAoaW52YWxpZFNlc3Npb24pIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jbGlwcGVyU2VydmljZS5sb2dnZWRJbigpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsaXBwZXJTZXJ2aWNlLnJlc2V0KCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICB9LCAyNTApO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnIpO1xyXG4gICAgICAgICAgfSkpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG5leHQuaGFuZGxlKHJlcXVlc3QpO1xyXG4gIH1cclxuXHJcblxyXG4gIC8qKlxyXG4gICAqIEFkZCB0b2tlbiB0byByZXF1ZXN0XHJcbiAgICogQHBhcmFtIHJlcXVlc3QgOiB0aGUgcmVxdWVzdFxyXG4gICAqIEBwYXJhbSB0b2tlbjogdGhlIHRva2VuIG9yIG51bGwgdG8gdXNlIGN1cnJlM250XHJcbiAgICovXHJcbiAgcHJpdmF0ZSBhZGRUb2tlblRvUmVxdWVzdChcclxuICAgIHJlcXVlc3Q6IEh0dHBSZXF1ZXN0PGFueT4sXHJcbiAgICB0b2tlbjogc3RyaW5nID0gbnVsbFxyXG4gICk6IEh0dHBSZXF1ZXN0PGFueT4ge1xyXG4gICAgaWYgKHJlcXVlc3QudXJsLnN0YXJ0c1dpdGgodGhpcy5jbGlwcGVyU2VydmljZS5zZXJ2aWNlVXJpKSkge1xyXG4gICAgICBpZiAoIXRva2VuKSB0b2tlbiA9IHRoaXMuY2xpcHBlclNlcnZpY2UuZ2V0VG9rZW4oKTtcclxuICAgICAgaWYgKHRva2VuKSB7XHJcbiAgICAgICAgcmV0dXJuIHJlcXVlc3QuY2xvbmUoe1xyXG4gICAgICAgICAgc2V0SGVhZGVyczoge1xyXG4gICAgICAgICAgICBBdXRob3JpemF0aW9uOiAnQmVhcmVyICcgKyB0b2tlbixcclxuICAgICAgICAgICAgJ25nc3ctYnlwYXNzJzogJ25nc3ctYnlwYXNzJ1xyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIHJlcXVlc3Q7XHJcbiAgfVxyXG5cclxufVxyXG4iXX0=
80
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5pbnRlcmNlcHRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2Fycy11dGlscy9jbGlwcGVyLmNvbW1vbi9jb21tb24vaW50ZXJjZXB0b3JzL2F1dGguaW50ZXJjZXB0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGlCQUFpQixFQUF3RCxNQUFNLHNCQUFzQixDQUFDO0FBQy9HLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUMxRCxPQUFPLEVBQWMsVUFBVSxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDckUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQzdELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQy9ELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxhQUFhLENBQUM7O0FBRzlDLE1BQU0sT0FBTyxzQkFBc0I7SUFEbkM7UUFFVSxtQkFBYyxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUN4QyxxQkFBZ0IsR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUM1QyxrQkFBYSxHQUFHLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztLQWtGL0M7SUEvRUMsU0FBUyxDQUNQLE9BQXlCLEVBQ3pCLElBQWlCO1FBRWpCLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1lBQzNELE9BQU8sR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsZUFBZSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7WUFDbkQsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLElB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RCxPQUFPLE9BQU8sQ0FBQztJQUNqQixDQUFDOzhHQW5GVSxzQkFBc0I7a0hBQXRCLHNCQUFzQjs7MkZBQXRCLHNCQUFzQjtrQkFEbEMsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEh0dHBFcnJvclJlc3BvbnNlLCBIdHRwRXZlbnQsIEh0dHBIYW5kbGVyLCBIdHRwSW50ZXJjZXB0b3IsIEh0dHBSZXF1ZXN0IH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xyXG5pbXBvcnQgeyBJbmplY3RhYmxlLCBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgRGlhbG9nU2VydmljZSB9IGZyb20gJ0BhcnNlZGl6aW9uaS9hcnMtdXRpbHMvdWknO1xyXG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBjYXRjaEVycm9yLCBzd2l0Y2hNYXAsIHRocm93RXJyb3IgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgQ2xpcHBlclNlcnZpY2UgfSBmcm9tICcuLi9zZXJ2aWNlcy9jbGlwcGVyLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBCcm9hZGNhc3RTZXJ2aWNlIH0gZnJvbSAnQGFyc2VkaXppb25pL2Fycy11dGlscy9jb3JlJztcclxuaW1wb3J0IHsgQ2xpcHBlck1lc3NhZ2VzIH0gZnJvbSAnLi4vbWVzc2FnZXMnO1xyXG5cclxuQEluamVjdGFibGUoKVxyXG5leHBvcnQgY2xhc3MgQ2xpcHBlckF1dGhJbnRlcmNlcHRvciBpbXBsZW1lbnRzIEh0dHBJbnRlcmNlcHRvciB7XHJcbiAgcHJpdmF0ZSBjbGlwcGVyU2VydmljZSA9IGluamVjdChDbGlwcGVyU2VydmljZSk7XHJcbiAgcHJpdmF0ZSBicm9hZGNhc3RTZXJ2aWNlID0gaW5qZWN0KEJyb2FkY2FzdFNlcnZpY2UpO1xyXG4gIHByaXZhdGUgZGlhbG9nU2VydmljZSA9IGluamVjdChEaWFsb2dTZXJ2aWNlKTtcclxuXHJcblxyXG4gIGludGVyY2VwdChcclxuICAgIHJlcXVlc3Q6IEh0dHBSZXF1ZXN0PGFueT4sXHJcbiAgICBuZXh0OiBIdHRwSGFuZGxlclxyXG4gICk6IE9ic2VydmFibGU8SHR0cEV2ZW50PGFueT4+IHtcclxuICAgIGlmIChyZXF1ZXN0LnVybC5zdGFydHNXaXRoKHRoaXMuY2xpcHBlclNlcnZpY2Uuc2VydmljZVVyaSkpIHtcclxuICAgICAgcmVxdWVzdCA9IHJlcXVlc3QuY2xvbmUoeyB3aXRoQ3JlZGVudGlhbHM6IHRydWUgfSk7XHJcbiAgICAgIHJldHVybiBuZXh0LmhhbmRsZSh0aGlzLmFkZFRva2VuVG9SZXF1ZXN0KHJlcXVlc3QpKVxyXG4gICAgICAgIC5waXBlKFxyXG4gICAgICAgICAgY2F0Y2hFcnJvcihlcnJvciA9PiB7XHJcbiAgICAgICAgICAgIGlmIChcclxuICAgICAgICAgICAgICBlcnJvciBpbnN0YW5jZW9mIEh0dHBFcnJvclJlc3BvbnNlICYmXHJcbiAgICAgICAgICAgICAgIXJlcXVlc3QudXJsLmluY2x1ZGVzKFwiL2xvZ2luXCIpICYmXHJcbiAgICAgICAgICAgICAgZXJyb3Iuc3RhdHVzID09PSA0MDFcclxuICAgICAgICAgICAgKSB7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlNDAxRXJyb3IocmVxdWVzdCwgbmV4dCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy8gU2hvdyBhIG1lc3NhZ2VcclxuICAgICAgICAgICAgY29uc3QgaW52YWxpZFNlc3Npb24gPSBlcnJvci5zdGF0dXMgPT0gXCI0MDNcIjtcclxuICAgICAgICAgICAgdGhpcy5kaWFsb2dTZXJ2aWNlLmNsZWFyQnVzeSgpO1xyXG4gICAgICAgICAgICB0aGlzLmRpYWxvZ1NlcnZpY2UuZXJyb3IoXHJcbiAgICAgICAgICAgICAgXCI8cD5cIiArIChlcnJvci5lcnJvcj8ubWVzc2FnZSA/PyBlcnJvci5tZXNzYWdlID8/IFwiSW1wb3NzaWJpbGUgZXNlZ3VpcmUgbCdvcGVyYXppb25lIHJpY2hpZXN0YS5cIikucmVwbGFjZUFsbChcIlxcclxcblwiLCBcIjwvcD48cD5cIikgKyBcIjwvcD5cIixcclxuICAgICAgICAgICAgICBudWxsLFxyXG4gICAgICAgICAgICAgIFwiRXJyb3JlIGluIENsaXBwZXJcIixcclxuICAgICAgICAgICAgICB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgICAgdW5kZWZpbmVkLFxyXG4gICAgICAgICAgICAgIGludmFsaWRTZXNzaW9uID8gNTAwMCA6IDE1MDAwKS5hZnRlckNsb3NlZCgpLnN1YnNjcmliZSgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBpZiAoaW52YWxpZFNlc3Npb24pIHtcclxuICAgICAgICAgICAgICAgICAgdGhpcy5jbGlwcGVyU2VydmljZS5jbGVhcigpO1xyXG4gICAgICAgICAgICAgICAgICB0aGlzLmJyb2FkY2FzdFNlcnZpY2Uuc2VuZE1lc3NhZ2UoQ2xpcHBlck1lc3NhZ2VzLkxPR09VVCk7ICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gZXJyb3IpO1xyXG4gICAgICAgICAgfSkpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG5leHQuaGFuZGxlKHJlcXVlc3QpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSGFuZGxlIDQwMSBlcnJvclxyXG4gICAqIEBwYXJhbSByZXF1ZXN0IDogdGhlIHJlcXVlc3RcclxuICAgKiBAcGFyYW0gbmV4dCA6IHRoZSBodHRwIGhhbmRsZXJcclxuICAgKi9cclxuICBwcml2YXRlIGhhbmRsZTQwMUVycm9yKHJlcXVlc3Q6IEh0dHBSZXF1ZXN0PGFueT4sIG5leHQ6IEh0dHBIYW5kbGVyKSB7XHJcbiAgICBpZiAodGhpcy5jbGlwcGVyU2VydmljZS5sb2dnZWRJbigpKSB7XHJcbiAgICAgIHJldHVybiB0aGlzLmNsaXBwZXJTZXJ2aWNlLnJlZnJlc2goKS5waXBlKFxyXG4gICAgICAgIHN3aXRjaE1hcCgoKSA9PiB7XHJcbiAgICAgICAgICByZXR1cm4gbmV4dC5oYW5kbGUodGhpcy5hZGRUb2tlblRvUmVxdWVzdChyZXF1ZXN0KSk7XHJcbiAgICAgICAgfSksXHJcbiAgICAgICAgY2F0Y2hFcnJvcihlcnJvciA9PiB7XHJcbiAgICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnJvcik7XHJcbiAgICAgICAgfSlcclxuICAgICAgKTtcclxuICAgIH1cclxuICAgIHJldHVybiBuZXh0LmhhbmRsZShyZXF1ZXN0KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEFkZCB0b2tlbiB0byByZXF1ZXN0XHJcbiAgICogQHBhcmFtIHJlcXVlc3QgOiB0aGUgcmVxdWVzdFxyXG4gICAqIEBwYXJhbSB0b2tlbjogdGhlIHRva2VuIG9yIG51bGwgdG8gdXNlIGN1cnJlM250XHJcbiAgICovXHJcbiAgcHJpdmF0ZSBhZGRUb2tlblRvUmVxdWVzdChcclxuICAgIHJlcXVlc3Q6IEh0dHBSZXF1ZXN0PGFueT4sXHJcbiAgICB0b2tlbjogc3RyaW5nIHwgbnVsbCA9IG51bGxcclxuICApOiBIdHRwUmVxdWVzdDxhbnk+IHtcclxuICAgIGlmIChyZXF1ZXN0LnVybC5zdGFydHNXaXRoKHRoaXMuY2xpcHBlclNlcnZpY2Uuc2VydmljZVVyaSkpIHtcclxuICAgICAgaWYgKCF0b2tlbikgdG9rZW4gPSB0aGlzLmNsaXBwZXJTZXJ2aWNlLmdldFRva2VuKCk7XHJcbiAgICAgIGlmICh0b2tlbikge1xyXG4gICAgICAgIHJldHVybiByZXF1ZXN0LmNsb25lKHtcclxuICAgICAgICAgIHNldEhlYWRlcnM6IHtcclxuICAgICAgICAgICAgQXV0aG9yaXphdGlvbjogJ0JlYXJlciAnICsgdG9rZW4sXHJcbiAgICAgICAgICAgICduZ3N3LWJ5cGFzcyc6ICduZ3N3LWJ5cGFzcydcclxuICAgICAgICAgIH0sXHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiByZXF1ZXN0O1xyXG4gIH1cclxuXHJcbn1cclxuIl19