vc-error-handlers 0.1.8 → 0.1.91
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.
- package/esm2020/lib/shared/constants/api-config.constants.mjs +109 -0
- package/esm2020/lib/shared/interceptors/http.interceptor.mjs +5 -18
- package/esm2020/lib/shared/services/global-error.service.mjs +115 -5
- package/esm2020/lib/shared/services/util.service.mjs +21 -0
- package/esm2020/lib/vc-error-handlers.component.mjs +10 -3
- package/fesm2015/vc-error-handlers.mjs +380 -152
- package/fesm2015/vc-error-handlers.mjs.map +1 -1
- package/fesm2020/vc-error-handlers.mjs +379 -152
- package/fesm2020/vc-error-handlers.mjs.map +1 -1
- package/lib/shared/constants/api-config.constants.d.ts +24 -0
- package/lib/shared/interceptors/http.interceptor.d.ts +1 -4
- package/lib/shared/services/global-error.service.d.ts +20 -1
- package/lib/shared/services/util.service.d.ts +6 -0
- package/lib/vc-error-handlers.component.d.ts +1 -0
- package/package.json +2 -2
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { Injectable, Component, Input, Directive, ViewChild, NgModule, Optional, InjectionToken, ErrorHandler } from '@angular/core';
|
|
3
3
|
import { Subject, throwError } from 'rxjs';
|
|
4
|
+
import * as i3 from '@angular/router';
|
|
5
|
+
import { NavigationStart, NavigationEnd, NavigationError } from '@angular/router';
|
|
4
6
|
import * as i1 from '@vcomply/authorizer';
|
|
5
7
|
import * as i2 from '@angular/common';
|
|
6
8
|
import { CommonModule } from '@angular/common';
|
|
7
|
-
import * as i3 from '@angular/router';
|
|
8
|
-
import { NavigationStart, NavigationEnd, NavigationError } from '@angular/router';
|
|
9
9
|
import { HttpResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
|
|
10
10
|
import * as Sentry from '@sentry/angular-ivy';
|
|
11
11
|
import { timeout, tap, catchError } from 'rxjs/operators';
|
|
@@ -38,71 +38,6 @@ var ErrorStatusCode;
|
|
|
38
38
|
ErrorStatusCode[ErrorStatusCode["JSChunkUnavailable"] = 600] = "JSChunkUnavailable";
|
|
39
39
|
})(ErrorStatusCode || (ErrorStatusCode = {}));
|
|
40
40
|
|
|
41
|
-
class GlobalErrorService {
|
|
42
|
-
constructor() {
|
|
43
|
-
this.globalError$ = new Subject();
|
|
44
|
-
this.localError$ = new Subject();
|
|
45
|
-
}
|
|
46
|
-
handleError(error, request) {
|
|
47
|
-
if (this.isUnauthenticated(error) ||
|
|
48
|
-
this.isUnauthorizedAccess(error) ||
|
|
49
|
-
this.isNetworkUnavailable(error)) {
|
|
50
|
-
this.globalError$.next(error);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
isUnauthenticated(error) {
|
|
54
|
-
return error.status === ErrorStatusCode.Unauthenticated;
|
|
55
|
-
}
|
|
56
|
-
isUnauthorizedAccess(error) {
|
|
57
|
-
return error.status === ErrorStatusCode.UnauthorizedAccess;
|
|
58
|
-
}
|
|
59
|
-
isNetworkUnavailable(error) {
|
|
60
|
-
return error.status === ErrorStatusCode.NetworkUnavailable;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
GlobalErrorService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: GlobalErrorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
64
|
-
GlobalErrorService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: GlobalErrorService, providedIn: 'root' });
|
|
65
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: GlobalErrorService, decorators: [{
|
|
66
|
-
type: Injectable,
|
|
67
|
-
args: [{
|
|
68
|
-
providedIn: 'root',
|
|
69
|
-
}]
|
|
70
|
-
}] });
|
|
71
|
-
|
|
72
|
-
class AuthService {
|
|
73
|
-
constructor(authorizer) {
|
|
74
|
-
this.authorizer = authorizer;
|
|
75
|
-
}
|
|
76
|
-
logoutUser() {
|
|
77
|
-
this.authorizer.logout();
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
AuthService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: AuthService, deps: [{ token: i1.AuthorizerService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
81
|
-
AuthService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: AuthService, providedIn: "root" });
|
|
82
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: AuthService, decorators: [{
|
|
83
|
-
type: Injectable,
|
|
84
|
-
args: [{
|
|
85
|
-
providedIn: "root",
|
|
86
|
-
}]
|
|
87
|
-
}], ctorParameters: function () { return [{ type: i1.AuthorizerService }]; } });
|
|
88
|
-
|
|
89
|
-
class RouterService {
|
|
90
|
-
redirectToLogin() {
|
|
91
|
-
window.location.href =
|
|
92
|
-
`https://${window.location.host}/` +
|
|
93
|
-
'signin?redirectURL=' +
|
|
94
|
-
encodeURIComponent(window.location.href);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
RouterService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: RouterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
98
|
-
RouterService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: RouterService, providedIn: 'root' });
|
|
99
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: RouterService, decorators: [{
|
|
100
|
-
type: Injectable,
|
|
101
|
-
args: [{
|
|
102
|
-
providedIn: 'root',
|
|
103
|
-
}]
|
|
104
|
-
}] });
|
|
105
|
-
|
|
106
41
|
const VCOMPLY_LOGO_URL = 'https://cdn.v-comply.com/logo/prod/v-logo.svg';
|
|
107
42
|
const API_TIMEOUT_TIME = 1000 * 15;
|
|
108
43
|
const ERROR_CONFIG = {
|
|
@@ -146,6 +81,115 @@ const ERROR_CONFIG = {
|
|
|
146
81
|
},
|
|
147
82
|
};
|
|
148
83
|
|
|
84
|
+
const PAGE_LEVEL_API_CONFIG = [
|
|
85
|
+
{
|
|
86
|
+
method: 'POST',
|
|
87
|
+
path: '/compliance_post',
|
|
88
|
+
query: { mode: 'xyz' },
|
|
89
|
+
body: { mode: 'abc' },
|
|
90
|
+
pageCodes: ['compliance:mr', 'risk:mr'],
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
method: 'GET',
|
|
94
|
+
path: '/compliance_post',
|
|
95
|
+
query: { mode: 'xyz' },
|
|
96
|
+
body: { mode: 'abc' },
|
|
97
|
+
pageCodes: ['compliance:mr', 'risk:mr'],
|
|
98
|
+
},
|
|
99
|
+
];
|
|
100
|
+
const COMPONENT_LEVEL_API_CONFIG = [
|
|
101
|
+
{
|
|
102
|
+
method: 'GET',
|
|
103
|
+
path: '/organization/?mode=organisationUsersList',
|
|
104
|
+
query: { type: 'active' },
|
|
105
|
+
body: null,
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
method: 'GET',
|
|
109
|
+
path: '/organization/?mode=organisationUsersList',
|
|
110
|
+
query: { type: 'power_users' },
|
|
111
|
+
body: null,
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
method: 'GET',
|
|
115
|
+
path: '/organization/?mode=organisationUsersList',
|
|
116
|
+
query: { type: 'light_users' },
|
|
117
|
+
body: null,
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
method: 'GET',
|
|
121
|
+
path: '/organization/?mode=organisationUsersList',
|
|
122
|
+
query: { type: 'inactive' },
|
|
123
|
+
body: null,
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
method: 'GET',
|
|
127
|
+
path: '/Global-Dashboard/ManageDashboards',
|
|
128
|
+
query: null,
|
|
129
|
+
body: null,
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
method: 'GET',
|
|
133
|
+
path: '/Global-Dashboard/MyDashboard',
|
|
134
|
+
query: null,
|
|
135
|
+
body: null,
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
method: 'GET',
|
|
139
|
+
path: '/grc_object/?mode=grcObject/getGRCTypeList',
|
|
140
|
+
query: null,
|
|
141
|
+
body: null,
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
method: 'GET',
|
|
145
|
+
path: '/compliance/?mode=responsibilityCenterTree',
|
|
146
|
+
query: null,
|
|
147
|
+
body: null,
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
method: 'GET',
|
|
151
|
+
path: '/organization/?mode=rcholidaylist',
|
|
152
|
+
query: null,
|
|
153
|
+
body: null,
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
method: 'GET',
|
|
157
|
+
path: '/organization/?mode=roles/getRoles',
|
|
158
|
+
query: null,
|
|
159
|
+
body: null,
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
method: 'GET',
|
|
163
|
+
path: '/organization/?mode=groupsList',
|
|
164
|
+
query: null,
|
|
165
|
+
body: null,
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
method: 'GET',
|
|
169
|
+
path: '/compliance_post/?mode=rcProfile',
|
|
170
|
+
query: null,
|
|
171
|
+
body: null,
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
method: 'GET',
|
|
175
|
+
path: '/organization_post/?mode=userProfile',
|
|
176
|
+
query: null,
|
|
177
|
+
body: null,
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
method: 'GET',
|
|
181
|
+
path: '/organization/?mode=roles/roleById',
|
|
182
|
+
query: null,
|
|
183
|
+
body: null,
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
method: 'GET',
|
|
187
|
+
path: '/organization/?mode=groupDetails',
|
|
188
|
+
query: null,
|
|
189
|
+
body: null,
|
|
190
|
+
}
|
|
191
|
+
];
|
|
192
|
+
|
|
149
193
|
class SnackBarService {
|
|
150
194
|
constructor() {
|
|
151
195
|
this.snackbarSubject = new Subject();
|
|
@@ -175,6 +219,195 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
|
|
|
175
219
|
}]
|
|
176
220
|
}], ctorParameters: function () { return []; } });
|
|
177
221
|
|
|
222
|
+
class UtilsService {
|
|
223
|
+
isJsonSubset(parentJson, subsetJson) {
|
|
224
|
+
for (let key in subsetJson) {
|
|
225
|
+
if (!parentJson.hasOwnProperty(key) || parentJson[key] !== subsetJson[key]) {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
UtilsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: UtilsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
233
|
+
UtilsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: UtilsService, providedIn: 'root' });
|
|
234
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: UtilsService, decorators: [{
|
|
235
|
+
type: Injectable,
|
|
236
|
+
args: [{
|
|
237
|
+
providedIn: 'root',
|
|
238
|
+
}]
|
|
239
|
+
}] });
|
|
240
|
+
|
|
241
|
+
class GlobalErrorService {
|
|
242
|
+
constructor(snackBarService, utilService, router) {
|
|
243
|
+
this.snackBarService = snackBarService;
|
|
244
|
+
this.utilService = utilService;
|
|
245
|
+
this.router = router;
|
|
246
|
+
this.globalError$ = new Subject();
|
|
247
|
+
this.localError$ = new Subject();
|
|
248
|
+
this.pageLevelApiConfig = PAGE_LEVEL_API_CONFIG;
|
|
249
|
+
this.componentLevelApiConfig = COMPONENT_LEVEL_API_CONFIG;
|
|
250
|
+
}
|
|
251
|
+
handleSoftErrors(event) {
|
|
252
|
+
const xData = event.headers.get('X-Data');
|
|
253
|
+
if (xData) {
|
|
254
|
+
const parsedData = JSON.parse(xData);
|
|
255
|
+
const statusCode = parsedData.statusCode;
|
|
256
|
+
const statusMessage = parsedData.message;
|
|
257
|
+
if (statusCode && statusCode !== 0) {
|
|
258
|
+
this.snackBarService.show(statusMessage || 'Error occurred', 'error');
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
handleError(error, request) {
|
|
263
|
+
if (this.isUnauthenticated(error) ||
|
|
264
|
+
this.isUnauthorizedAccess(error) ||
|
|
265
|
+
this.isNetworkUnavailable(error)) {
|
|
266
|
+
this.publishGlobalError(error);
|
|
267
|
+
}
|
|
268
|
+
else if (this.isServerError(error)) {
|
|
269
|
+
this.handleServerError(error, request);
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
this.handleSoftErrors(error);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
isServerError(error) {
|
|
276
|
+
const serverErrorCodes = [
|
|
277
|
+
ErrorStatusCode.InternalServerError,
|
|
278
|
+
ErrorStatusCode.ServiceUnavailable,
|
|
279
|
+
ErrorStatusCode.BadGateway,
|
|
280
|
+
ErrorStatusCode.RequestTimeout,
|
|
281
|
+
];
|
|
282
|
+
return serverErrorCodes.includes(error.status);
|
|
283
|
+
}
|
|
284
|
+
isUnauthenticated(error) {
|
|
285
|
+
return error.status === ErrorStatusCode.Unauthenticated;
|
|
286
|
+
}
|
|
287
|
+
isUnauthorizedAccess(error) {
|
|
288
|
+
return error.status === ErrorStatusCode.UnauthorizedAccess;
|
|
289
|
+
}
|
|
290
|
+
isNetworkUnavailable(error) {
|
|
291
|
+
return error.status === ErrorStatusCode.NetworkUnavailable;
|
|
292
|
+
}
|
|
293
|
+
handleServerError(error, request) {
|
|
294
|
+
if (this.isPageLevelError(error, request)) {
|
|
295
|
+
this.publishGlobalError(error);
|
|
296
|
+
}
|
|
297
|
+
else if (this.isComponentLevelError(error, request)) {
|
|
298
|
+
this.publishLocalError(error, request);
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
this.showServerSnackBarError();
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
publishGlobalError(error) {
|
|
305
|
+
this.globalError$.next(error);
|
|
306
|
+
}
|
|
307
|
+
publishLocalError(error, request) {
|
|
308
|
+
this.localError$.next({ error, request });
|
|
309
|
+
}
|
|
310
|
+
showServerSnackBarError() {
|
|
311
|
+
const message = ERROR_CONFIG.SERVER_ERROR.snackBarMessage;
|
|
312
|
+
this.snackBarService.show(message, 'error');
|
|
313
|
+
}
|
|
314
|
+
isPageLevelError(error, request) {
|
|
315
|
+
const { method, path, query, body } = this.parseRequest(request);
|
|
316
|
+
const pageCode = this.getPageCode();
|
|
317
|
+
const isConfigMatched = this.pageLevelApiConfig.some((apiConfig) => {
|
|
318
|
+
if (apiConfig.method !== method)
|
|
319
|
+
return false;
|
|
320
|
+
if (apiConfig.path !== path)
|
|
321
|
+
return false;
|
|
322
|
+
const isQuerySubset = this.utilService.isJsonSubset(apiConfig.query, query);
|
|
323
|
+
if (!isQuerySubset)
|
|
324
|
+
return false;
|
|
325
|
+
const isBodyMatch = this.utilService.isJsonSubset(apiConfig.body, body);
|
|
326
|
+
if (!isBodyMatch)
|
|
327
|
+
return false;
|
|
328
|
+
return apiConfig.pageCodes.includes(pageCode);
|
|
329
|
+
});
|
|
330
|
+
return isConfigMatched;
|
|
331
|
+
}
|
|
332
|
+
isComponentLevelError(error, request) {
|
|
333
|
+
const { method, url: path, params, body } = request;
|
|
334
|
+
const query = {};
|
|
335
|
+
params.keys().forEach((key) => {
|
|
336
|
+
query[key] = params.get(key);
|
|
337
|
+
});
|
|
338
|
+
const isConfigFound = this.componentLevelApiConfig.some((apiConfig) => {
|
|
339
|
+
if (apiConfig.method !== method)
|
|
340
|
+
return false;
|
|
341
|
+
if (!path.includes(apiConfig.path))
|
|
342
|
+
return false;
|
|
343
|
+
const isQuerySubset = this.utilService.isJsonSubset(query, apiConfig.query);
|
|
344
|
+
if (!isQuerySubset)
|
|
345
|
+
return false;
|
|
346
|
+
if (apiConfig.body) {
|
|
347
|
+
const isBodyMatch = this.utilService.isJsonSubset(apiConfig.body, body);
|
|
348
|
+
if (!isBodyMatch)
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
return true;
|
|
352
|
+
});
|
|
353
|
+
return isConfigFound;
|
|
354
|
+
}
|
|
355
|
+
parseRequest(request) {
|
|
356
|
+
const { method, url: path, params, body } = request;
|
|
357
|
+
const query = {};
|
|
358
|
+
params.keys().forEach((key) => {
|
|
359
|
+
query[key] = params.get(key);
|
|
360
|
+
});
|
|
361
|
+
return { method, path, query, body };
|
|
362
|
+
}
|
|
363
|
+
getPageCode() {
|
|
364
|
+
const currentRoute = this.router.routerState.snapshot.root.firstChild;
|
|
365
|
+
return currentRoute?.data?.pageCode;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
GlobalErrorService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: GlobalErrorService, deps: [{ token: SnackBarService }, { token: UtilsService }, { token: i3.Router }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
369
|
+
GlobalErrorService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: GlobalErrorService, providedIn: 'root' });
|
|
370
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: GlobalErrorService, decorators: [{
|
|
371
|
+
type: Injectable,
|
|
372
|
+
args: [{
|
|
373
|
+
providedIn: 'root',
|
|
374
|
+
}]
|
|
375
|
+
}], ctorParameters: function () { return [{ type: SnackBarService }, { type: UtilsService }, { type: i3.Router }]; } });
|
|
376
|
+
|
|
377
|
+
class AuthService {
|
|
378
|
+
constructor(authorizer) {
|
|
379
|
+
this.authorizer = authorizer;
|
|
380
|
+
}
|
|
381
|
+
logoutUser() {
|
|
382
|
+
this.authorizer.logout();
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
AuthService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: AuthService, deps: [{ token: i1.AuthorizerService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
386
|
+
AuthService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: AuthService, providedIn: "root" });
|
|
387
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: AuthService, decorators: [{
|
|
388
|
+
type: Injectable,
|
|
389
|
+
args: [{
|
|
390
|
+
providedIn: "root",
|
|
391
|
+
}]
|
|
392
|
+
}], ctorParameters: function () { return [{ type: i1.AuthorizerService }]; } });
|
|
393
|
+
|
|
394
|
+
class RouterService {
|
|
395
|
+
redirectToLogin() {
|
|
396
|
+
window.location.href =
|
|
397
|
+
`https://${window.location.host}/` +
|
|
398
|
+
'signin?redirectURL=' +
|
|
399
|
+
encodeURIComponent(window.location.href);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
RouterService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: RouterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
403
|
+
RouterService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: RouterService, providedIn: 'root' });
|
|
404
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: RouterService, decorators: [{
|
|
405
|
+
type: Injectable,
|
|
406
|
+
args: [{
|
|
407
|
+
providedIn: 'root',
|
|
408
|
+
}]
|
|
409
|
+
}] });
|
|
410
|
+
|
|
178
411
|
class SnackBarComponent {
|
|
179
412
|
constructor(snackbarService) {
|
|
180
413
|
this.snackbarService = snackbarService;
|
|
@@ -597,6 +830,74 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
|
|
|
597
830
|
}]
|
|
598
831
|
}], ctorParameters: function () { return [{ type: DialogService }]; } });
|
|
599
832
|
|
|
833
|
+
class ServerErrorComponent {
|
|
834
|
+
constructor() {
|
|
835
|
+
this.errorConfig = ERROR_CONFIG.SERVER_ERROR;
|
|
836
|
+
this.VcomplyLogo = VCOMPLY_LOGO_URL;
|
|
837
|
+
}
|
|
838
|
+
refreshPage() {
|
|
839
|
+
window.location.reload();
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
ServerErrorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ServerErrorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
843
|
+
ServerErrorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: ServerErrorComponent, selector: "lib-vc-error-server-error", ngImport: i0, template: `
|
|
844
|
+
<div class="errorPage">
|
|
845
|
+
<div class="errorPage-top">
|
|
846
|
+
<img [src]="VcomplyLogo" alt="VComply" width="24" height="24" />
|
|
847
|
+
</div>
|
|
848
|
+
<div class="errorPage-container">
|
|
849
|
+
<div class="errorPage-inner">
|
|
850
|
+
<div class="errorPage-inner-image">
|
|
851
|
+
<img
|
|
852
|
+
[src]="errorConfig.imageUrl"
|
|
853
|
+
alt="Error Image"
|
|
854
|
+
width="246"
|
|
855
|
+
height="178"
|
|
856
|
+
/>
|
|
857
|
+
</div>
|
|
858
|
+
<div class="errorPage-inner-right">
|
|
859
|
+
<div class="errorPage-heading">{{ errorConfig.title }}</div>
|
|
860
|
+
<div class="errorPage-text">{{ errorConfig.description }}</div>
|
|
861
|
+
<div class="errorPage-details">{{ errorConfig.details }}</div>
|
|
862
|
+
<button class="errorPage-btn" (click)="refreshPage()">
|
|
863
|
+
{{ errorConfig.buttonText }} <i class="icons"></i>
|
|
864
|
+
</button>
|
|
865
|
+
</div>
|
|
866
|
+
</div>
|
|
867
|
+
</div>
|
|
868
|
+
</div>
|
|
869
|
+
`, isInline: true, styles: ["@import\"https://cdn.v-comply.com/design-system/css/icons/icons.css\";.errorPage{background:#161b2f;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999}.errorPage-top{width:100%;height:3rem;display:flex;align-items:center;padding-left:.75rem}.errorPage-container{background:#f2f2f5;border-radius:.75rem;border:1px solid #e3e3e9;box-shadow:0 4px 8px #1d5dd31a;height:calc(100vh - 3.75rem);display:flex;align-items:center;justify-content:center;padding:0 4rem;margin:0 .75rem;position:relative}.errorPage-inner{display:flex;align-items:center}.errorPage-inner-image{width:16rem}.errorPage-inner-right{margin-left:2rem;width:calc(100% - 18rem)}.errorPage-inner-right .errorPage-heading{-webkit-text-fill-color:#e3e3e9;-webkit-text-stroke-color:#a9aab6;-webkit-text-stroke-width:1px;color:#e3e3e9;font-size:78px;font-weight:bold;line-height:110px;margin-bottom:1.5rem}.errorPage-inner-right .errorPage-text{color:#141724;font-size:19px;font-weight:500;line-height:1.75rem;margin-bottom:.5rem}.errorPage-inner-right .errorPage-details{color:#565a6f;font-size:13px;line-height:20px;margin-bottom:1.75rem}.errorPage-inner-right .errorPage-btn{background:#1e5dd3;border-radius:.25rem;border:none;color:#fff;display:inline-flex;align-items:center;font-size:11px;font-weight:500;line-height:2rem;padding:0 1rem}.errorPage-inner-right .errorPage-btn i{font-size:14px;margin-left:.25rem}.errorPage-copyright{font-size:11px;color:#787a8c;font-weight:500;position:absolute;bottom:8px;right:16px;line-height:16px}\n"] });
|
|
870
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ServerErrorComponent, decorators: [{
|
|
871
|
+
type: Component,
|
|
872
|
+
args: [{ selector: 'lib-vc-error-server-error', template: `
|
|
873
|
+
<div class="errorPage">
|
|
874
|
+
<div class="errorPage-top">
|
|
875
|
+
<img [src]="VcomplyLogo" alt="VComply" width="24" height="24" />
|
|
876
|
+
</div>
|
|
877
|
+
<div class="errorPage-container">
|
|
878
|
+
<div class="errorPage-inner">
|
|
879
|
+
<div class="errorPage-inner-image">
|
|
880
|
+
<img
|
|
881
|
+
[src]="errorConfig.imageUrl"
|
|
882
|
+
alt="Error Image"
|
|
883
|
+
width="246"
|
|
884
|
+
height="178"
|
|
885
|
+
/>
|
|
886
|
+
</div>
|
|
887
|
+
<div class="errorPage-inner-right">
|
|
888
|
+
<div class="errorPage-heading">{{ errorConfig.title }}</div>
|
|
889
|
+
<div class="errorPage-text">{{ errorConfig.description }}</div>
|
|
890
|
+
<div class="errorPage-details">{{ errorConfig.details }}</div>
|
|
891
|
+
<button class="errorPage-btn" (click)="refreshPage()">
|
|
892
|
+
{{ errorConfig.buttonText }} <i class="icons"></i>
|
|
893
|
+
</button>
|
|
894
|
+
</div>
|
|
895
|
+
</div>
|
|
896
|
+
</div>
|
|
897
|
+
</div>
|
|
898
|
+
`, styles: ["@import\"https://cdn.v-comply.com/design-system/css/icons/icons.css\";.errorPage{background:#161b2f;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999}.errorPage-top{width:100%;height:3rem;display:flex;align-items:center;padding-left:.75rem}.errorPage-container{background:#f2f2f5;border-radius:.75rem;border:1px solid #e3e3e9;box-shadow:0 4px 8px #1d5dd31a;height:calc(100vh - 3.75rem);display:flex;align-items:center;justify-content:center;padding:0 4rem;margin:0 .75rem;position:relative}.errorPage-inner{display:flex;align-items:center}.errorPage-inner-image{width:16rem}.errorPage-inner-right{margin-left:2rem;width:calc(100% - 18rem)}.errorPage-inner-right .errorPage-heading{-webkit-text-fill-color:#e3e3e9;-webkit-text-stroke-color:#a9aab6;-webkit-text-stroke-width:1px;color:#e3e3e9;font-size:78px;font-weight:bold;line-height:110px;margin-bottom:1.5rem}.errorPage-inner-right .errorPage-text{color:#141724;font-size:19px;font-weight:500;line-height:1.75rem;margin-bottom:.5rem}.errorPage-inner-right .errorPage-details{color:#565a6f;font-size:13px;line-height:20px;margin-bottom:1.75rem}.errorPage-inner-right .errorPage-btn{background:#1e5dd3;border-radius:.25rem;border:none;color:#fff;display:inline-flex;align-items:center;font-size:11px;font-weight:500;line-height:2rem;padding:0 1rem}.errorPage-inner-right .errorPage-btn i{font-size:14px;margin-left:.25rem}.errorPage-copyright{font-size:11px;color:#787a8c;font-weight:500;position:absolute;bottom:8px;right:16px;line-height:16px}\n"] }]
|
|
899
|
+
}] });
|
|
900
|
+
|
|
600
901
|
class VcErrorHandlersComponent {
|
|
601
902
|
constructor(errorService, snackBarService) {
|
|
602
903
|
this.errorService = errorService;
|
|
@@ -605,6 +906,7 @@ class VcErrorHandlersComponent {
|
|
|
605
906
|
this.unauthorized = false;
|
|
606
907
|
this.sessionExpired = false;
|
|
607
908
|
this.chunkUnavailable = false;
|
|
909
|
+
this.serverError = false;
|
|
608
910
|
this.isOnline = navigator.onLine;
|
|
609
911
|
this.onNetworkOnline = () => {
|
|
610
912
|
this.isOnline = true;
|
|
@@ -641,6 +943,9 @@ class VcErrorHandlersComponent {
|
|
|
641
943
|
else if (error.status === ErrorStatusCode.NetworkUnavailable) {
|
|
642
944
|
this.handleNetworkError();
|
|
643
945
|
}
|
|
946
|
+
else if (this.errorService.isServerError(error)) {
|
|
947
|
+
this.serverError = true;
|
|
948
|
+
}
|
|
644
949
|
}
|
|
645
950
|
subscribeNetworkDetection() {
|
|
646
951
|
window.addEventListener('online', this.onNetworkOnline);
|
|
@@ -668,7 +973,8 @@ VcErrorHandlersComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0
|
|
|
668
973
|
<lib-vc-error-chunk-unavailable
|
|
669
974
|
*ngIf="chunkUnavailable"
|
|
670
975
|
></lib-vc-error-chunk-unavailable>
|
|
671
|
-
|
|
976
|
+
<lib-vc-error-server-error *ngIf="serverError"></lib-vc-error-server-error>
|
|
977
|
+
`, isInline: true, components: [{ type: SnackBarComponent, selector: "app-snack-bar" }, { type: SessionExpiredComponent, selector: "lib-vc-error-session-expired" }, { type: UnauthorizedComponent, selector: "lib-vc-error-unauthorized" }, { type: ChunkUnavailableComponent, selector: "lib-vc-error-chunk-unavailable" }, { type: ServerErrorComponent, selector: "lib-vc-error-server-error" }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
672
978
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: VcErrorHandlersComponent, decorators: [{
|
|
673
979
|
type: Component,
|
|
674
980
|
args: [{
|
|
@@ -682,6 +988,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
|
|
|
682
988
|
<lib-vc-error-chunk-unavailable
|
|
683
989
|
*ngIf="chunkUnavailable"
|
|
684
990
|
></lib-vc-error-chunk-unavailable>
|
|
991
|
+
<lib-vc-error-server-error *ngIf="serverError"></lib-vc-error-server-error>
|
|
685
992
|
`,
|
|
686
993
|
}]
|
|
687
994
|
}], ctorParameters: function () { return [{ type: GlobalErrorService }, { type: SnackBarService }]; } });
|
|
@@ -765,74 +1072,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
|
|
|
765
1072
|
`, styles: ["@import\"https://cdn.v-comply.com/design-system/css/icons/icons.css\";.errorPage{background:#161b2f;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999}.errorPage-top{width:100%;height:3rem;display:flex;align-items:center;padding-left:.75rem}.errorPage-container{background:#f2f2f5;border-radius:.75rem;border:1px solid #e3e3e9;box-shadow:0 4px 8px #1d5dd31a;height:calc(100vh - 3.75rem);display:flex;align-items:center;justify-content:center;padding:0 4rem;margin:0 .75rem;position:relative}.errorPage-inner{display:flex;align-items:center}.errorPage-inner-image{width:16rem}.errorPage-inner-right{margin-left:2rem;width:calc(100% - 18rem)}.errorPage-inner-right .errorPage-heading{-webkit-text-fill-color:#e3e3e9;-webkit-text-stroke-color:#a9aab6;-webkit-text-stroke-width:1px;color:#e3e3e9;font-size:78px;font-weight:bold;line-height:110px;margin-bottom:1.5rem}.errorPage-inner-right .errorPage-text{color:#141724;font-size:19px;font-weight:500;line-height:1.75rem;margin-bottom:.5rem}.errorPage-inner-right .errorPage-details{color:#565a6f;font-size:13px;line-height:20px;margin-bottom:1.75rem}.errorPage-inner-right .errorPage-btn{background:#1e5dd3;border-radius:.25rem;border:none;color:#fff;display:inline-flex;align-items:center;font-size:11px;font-weight:500;line-height:2rem;padding:0 1rem}.errorPage-inner-right .errorPage-btn i{font-size:14px;margin-left:.25rem}.errorPage-copyright{font-size:11px;color:#787a8c;font-weight:500;position:absolute;bottom:8px;right:16px;line-height:16px}\n"] }]
|
|
766
1073
|
}], ctorParameters: function () { return [{ type: i3.Router }]; } });
|
|
767
1074
|
|
|
768
|
-
class ServerErrorComponent {
|
|
769
|
-
constructor() {
|
|
770
|
-
this.errorConfig = ERROR_CONFIG.SERVER_ERROR;
|
|
771
|
-
this.VcomplyLogo = VCOMPLY_LOGO_URL;
|
|
772
|
-
}
|
|
773
|
-
refreshPage() {
|
|
774
|
-
window.location.reload();
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
ServerErrorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ServerErrorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
778
|
-
ServerErrorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: ServerErrorComponent, selector: "lib-vc-error-server-error", ngImport: i0, template: `
|
|
779
|
-
<div class="errorPage">
|
|
780
|
-
<div class="errorPage-top">
|
|
781
|
-
<img [src]="VcomplyLogo" alt="VComply" width="24" height="24" />
|
|
782
|
-
</div>
|
|
783
|
-
<div class="errorPage-container">
|
|
784
|
-
<div class="errorPage-inner">
|
|
785
|
-
<div class="errorPage-inner-image">
|
|
786
|
-
<img
|
|
787
|
-
[src]="errorConfig.imageUrl"
|
|
788
|
-
alt="Error Image"
|
|
789
|
-
width="246"
|
|
790
|
-
height="178"
|
|
791
|
-
/>
|
|
792
|
-
</div>
|
|
793
|
-
<div class="errorPage-inner-right">
|
|
794
|
-
<div class="errorPage-heading">{{ errorConfig.title }}</div>
|
|
795
|
-
<div class="errorPage-text">{{ errorConfig.description }}</div>
|
|
796
|
-
<div class="errorPage-details">{{ errorConfig.details }}</div>
|
|
797
|
-
<button class="errorPage-btn" (click)="refreshPage()">
|
|
798
|
-
{{ errorConfig.buttonText }} <i class="icons"></i>
|
|
799
|
-
</button>
|
|
800
|
-
</div>
|
|
801
|
-
</div>
|
|
802
|
-
</div>
|
|
803
|
-
</div>
|
|
804
|
-
`, isInline: true, styles: ["@import\"https://cdn.v-comply.com/design-system/css/icons/icons.css\";.errorPage{background:#161b2f;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999}.errorPage-top{width:100%;height:3rem;display:flex;align-items:center;padding-left:.75rem}.errorPage-container{background:#f2f2f5;border-radius:.75rem;border:1px solid #e3e3e9;box-shadow:0 4px 8px #1d5dd31a;height:calc(100vh - 3.75rem);display:flex;align-items:center;justify-content:center;padding:0 4rem;margin:0 .75rem;position:relative}.errorPage-inner{display:flex;align-items:center}.errorPage-inner-image{width:16rem}.errorPage-inner-right{margin-left:2rem;width:calc(100% - 18rem)}.errorPage-inner-right .errorPage-heading{-webkit-text-fill-color:#e3e3e9;-webkit-text-stroke-color:#a9aab6;-webkit-text-stroke-width:1px;color:#e3e3e9;font-size:78px;font-weight:bold;line-height:110px;margin-bottom:1.5rem}.errorPage-inner-right .errorPage-text{color:#141724;font-size:19px;font-weight:500;line-height:1.75rem;margin-bottom:.5rem}.errorPage-inner-right .errorPage-details{color:#565a6f;font-size:13px;line-height:20px;margin-bottom:1.75rem}.errorPage-inner-right .errorPage-btn{background:#1e5dd3;border-radius:.25rem;border:none;color:#fff;display:inline-flex;align-items:center;font-size:11px;font-weight:500;line-height:2rem;padding:0 1rem}.errorPage-inner-right .errorPage-btn i{font-size:14px;margin-left:.25rem}.errorPage-copyright{font-size:11px;color:#787a8c;font-weight:500;position:absolute;bottom:8px;right:16px;line-height:16px}\n"] });
|
|
805
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ServerErrorComponent, decorators: [{
|
|
806
|
-
type: Component,
|
|
807
|
-
args: [{ selector: 'lib-vc-error-server-error', template: `
|
|
808
|
-
<div class="errorPage">
|
|
809
|
-
<div class="errorPage-top">
|
|
810
|
-
<img [src]="VcomplyLogo" alt="VComply" width="24" height="24" />
|
|
811
|
-
</div>
|
|
812
|
-
<div class="errorPage-container">
|
|
813
|
-
<div class="errorPage-inner">
|
|
814
|
-
<div class="errorPage-inner-image">
|
|
815
|
-
<img
|
|
816
|
-
[src]="errorConfig.imageUrl"
|
|
817
|
-
alt="Error Image"
|
|
818
|
-
width="246"
|
|
819
|
-
height="178"
|
|
820
|
-
/>
|
|
821
|
-
</div>
|
|
822
|
-
<div class="errorPage-inner-right">
|
|
823
|
-
<div class="errorPage-heading">{{ errorConfig.title }}</div>
|
|
824
|
-
<div class="errorPage-text">{{ errorConfig.description }}</div>
|
|
825
|
-
<div class="errorPage-details">{{ errorConfig.details }}</div>
|
|
826
|
-
<button class="errorPage-btn" (click)="refreshPage()">
|
|
827
|
-
{{ errorConfig.buttonText }} <i class="icons"></i>
|
|
828
|
-
</button>
|
|
829
|
-
</div>
|
|
830
|
-
</div>
|
|
831
|
-
</div>
|
|
832
|
-
</div>
|
|
833
|
-
`, styles: ["@import\"https://cdn.v-comply.com/design-system/css/icons/icons.css\";.errorPage{background:#161b2f;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999}.errorPage-top{width:100%;height:3rem;display:flex;align-items:center;padding-left:.75rem}.errorPage-container{background:#f2f2f5;border-radius:.75rem;border:1px solid #e3e3e9;box-shadow:0 4px 8px #1d5dd31a;height:calc(100vh - 3.75rem);display:flex;align-items:center;justify-content:center;padding:0 4rem;margin:0 .75rem;position:relative}.errorPage-inner{display:flex;align-items:center}.errorPage-inner-image{width:16rem}.errorPage-inner-right{margin-left:2rem;width:calc(100% - 18rem)}.errorPage-inner-right .errorPage-heading{-webkit-text-fill-color:#e3e3e9;-webkit-text-stroke-color:#a9aab6;-webkit-text-stroke-width:1px;color:#e3e3e9;font-size:78px;font-weight:bold;line-height:110px;margin-bottom:1.5rem}.errorPage-inner-right .errorPage-text{color:#141724;font-size:19px;font-weight:500;line-height:1.75rem;margin-bottom:.5rem}.errorPage-inner-right .errorPage-details{color:#565a6f;font-size:13px;line-height:20px;margin-bottom:1.75rem}.errorPage-inner-right .errorPage-btn{background:#1e5dd3;border-radius:.25rem;border:none;color:#fff;display:inline-flex;align-items:center;font-size:11px;font-weight:500;line-height:2rem;padding:0 1rem}.errorPage-inner-right .errorPage-btn i{font-size:14px;margin-left:.25rem}.errorPage-copyright{font-size:11px;color:#787a8c;font-weight:500;position:absolute;bottom:8px;right:16px;line-height:16px}\n"] }]
|
|
834
|
-
}] });
|
|
835
|
-
|
|
836
1075
|
class SnackBarModule {
|
|
837
1076
|
}
|
|
838
1077
|
SnackBarModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SnackBarModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
@@ -897,37 +1136,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
|
|
|
897
1136
|
}] }]; } });
|
|
898
1137
|
|
|
899
1138
|
class HttpReqInterceptor {
|
|
900
|
-
constructor(errorService
|
|
1139
|
+
constructor(errorService) {
|
|
901
1140
|
this.errorService = errorService;
|
|
902
|
-
this.snackBarService = snackBarService;
|
|
903
1141
|
}
|
|
904
1142
|
intercept(req, next) {
|
|
905
1143
|
return next.handle(req).pipe(timeout(API_TIMEOUT_TIME), tap((event) => {
|
|
906
1144
|
if (event instanceof HttpResponse) {
|
|
907
|
-
this.handleSoftErrors(event);
|
|
1145
|
+
this.errorService.handleSoftErrors(event);
|
|
908
1146
|
}
|
|
909
1147
|
}), catchError((error) => {
|
|
910
1148
|
this.errorService.handleError(error, req);
|
|
911
1149
|
return throwError(error);
|
|
912
1150
|
}));
|
|
913
1151
|
}
|
|
914
|
-
handleSoftErrors(event) {
|
|
915
|
-
const xData = event.headers.get('X-Data');
|
|
916
|
-
if (xData) {
|
|
917
|
-
const parsedData = JSON.parse(xData);
|
|
918
|
-
const statusCode = parsedData.statusCode;
|
|
919
|
-
const statusMessage = parsedData.message;
|
|
920
|
-
if (statusCode && statusCode !== 0) {
|
|
921
|
-
this.snackBarService.show(statusMessage || 'Error occurred', 'error');
|
|
922
|
-
}
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
1152
|
}
|
|
926
|
-
HttpReqInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: HttpReqInterceptor, deps: [{ token: GlobalErrorService }
|
|
1153
|
+
HttpReqInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: HttpReqInterceptor, deps: [{ token: GlobalErrorService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
927
1154
|
HttpReqInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: HttpReqInterceptor });
|
|
928
1155
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: HttpReqInterceptor, decorators: [{
|
|
929
1156
|
type: Injectable
|
|
930
|
-
}], ctorParameters: function () { return [{ type: GlobalErrorService }
|
|
1157
|
+
}], ctorParameters: function () { return [{ type: GlobalErrorService }]; } });
|
|
931
1158
|
|
|
932
1159
|
const FOR_ROOT_SENTRY_OPTIONS_TOKEN = new InjectionToken('forRoot() SentryErrorHandler options');
|
|
933
1160
|
class VcErrorHandlersModule {
|