studiokit-scaffolding-js 5.2.0-next.2.1 → 5.2.0-next.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.
- package/lib/components/HOC/ModelErrorRedirectComponent.js +2 -2
- package/lib/redux/configureStore.js +13 -10
- package/lib/redux/sagas/authSaga.js +4 -3
- package/lib/redux/sagas/downtimeApiErrorSaga.js +1 -1
- package/lib/redux/sagas/lockDownBrowserErrorSaga.js +1 -1
- package/lib/redux/sagas/modelFetchSaga.d.ts +0 -1
- package/lib/redux/sagas/modelFetchSaga.js +72 -59
- package/lib/redux/sagas/rootSaga.js +4 -2
- package/lib/services/fetchService.js +18 -14
- package/lib/types/net/ErrorHandler.d.ts +2 -1
- package/lib/types/net/FetchErrorData.d.ts +6 -3
- package/lib/types/net/FetchErrorData.js +8 -8
- package/lib/utils/user.js +2 -2
- package/package.json +1 -1
|
@@ -71,13 +71,13 @@ function modelErrorRedirectComponent(WrappedComponent) {
|
|
|
71
71
|
model._metadata &&
|
|
72
72
|
model._metadata.hasError &&
|
|
73
73
|
model._metadata.lastFetchErrorData &&
|
|
74
|
-
model._metadata.lastFetchErrorData.
|
|
74
|
+
model._metadata.lastFetchErrorData.status === 404;
|
|
75
75
|
var errorRoute = previousModelStatus === modelStatus_1.MODEL_STATUS.UNINITIALIZED &&
|
|
76
76
|
modelStatus === modelStatus_1.MODEL_STATUS.ERROR &&
|
|
77
77
|
model._metadata &&
|
|
78
78
|
model._metadata.hasError &&
|
|
79
79
|
model._metadata.lastFetchErrorData &&
|
|
80
|
-
model._metadata.lastFetchErrorData.
|
|
80
|
+
model._metadata.lastFetchErrorData.status === 500;
|
|
81
81
|
if (notFoundRoute) {
|
|
82
82
|
var pathname = window.location.pathname;
|
|
83
83
|
return (react_1.default.createElement(react_router_dom_1.Redirect, { to: {
|
|
@@ -43,7 +43,16 @@ var actionCreator_1 = require("./actionCreator");
|
|
|
43
43
|
var actions_1 = require("./actions");
|
|
44
44
|
var configureReducers_1 = __importDefault(require("./configureReducers"));
|
|
45
45
|
var rootSaga_1 = __importDefault(require("./sagas/rootSaga"));
|
|
46
|
-
var keysToFilter = [
|
|
46
|
+
var keysToFilter = [
|
|
47
|
+
'puid',
|
|
48
|
+
'employeeNumber',
|
|
49
|
+
'access_token',
|
|
50
|
+
'refresh_token',
|
|
51
|
+
'password',
|
|
52
|
+
'Password',
|
|
53
|
+
'content',
|
|
54
|
+
'data'
|
|
55
|
+
];
|
|
47
56
|
var filterData = function (obj) {
|
|
48
57
|
return lodash_1.transform(obj, function (result, value, key) {
|
|
49
58
|
if (keysToFilter.includes(key)) {
|
|
@@ -65,17 +74,11 @@ var stripState = function (obj, parentKey) {
|
|
|
65
74
|
};
|
|
66
75
|
exports.stripState = stripState;
|
|
67
76
|
var actionTransformer = function (action) {
|
|
68
|
-
var _a;
|
|
69
77
|
// action breadcrumb filtering
|
|
70
78
|
if (
|
|
71
|
-
// do not track
|
|
72
|
-
action.type === actions_1.
|
|
73
|
-
action.type === actions_1.
|
|
74
|
-
// do not track modal actions
|
|
75
|
-
action.type === actions_1.MODAL_ACTION_TYPE.MODAL_ENTERING ||
|
|
76
|
-
action.type === actions_1.MODAL_ACTION_TYPE.MODAL_EXITED ||
|
|
77
|
-
// do not track API requests for tokens
|
|
78
|
-
(action.type === actions_1.MODEL_FETCH_REQUEST_TYPE && ((_a = action.data) === null || _a === void 0 ? void 0 : _a.modelName) === 'getToken')) {
|
|
79
|
+
// do not track modal actions
|
|
80
|
+
action.type === actions_1.MODAL_ACTION_TYPE.MODAL_ENTERING ||
|
|
81
|
+
action.type === actions_1.MODAL_ACTION_TYPE.MODAL_EXITED) {
|
|
79
82
|
return null;
|
|
80
83
|
}
|
|
81
84
|
return filterData(action);
|
|
@@ -68,7 +68,7 @@ var clientCredentials;
|
|
|
68
68
|
var oauthToken = null;
|
|
69
69
|
var tokenPersistenceService;
|
|
70
70
|
var refreshLock;
|
|
71
|
-
var logger
|
|
71
|
+
var logger;
|
|
72
72
|
//#endregion Local Variables
|
|
73
73
|
function getTokenFromCode(code) {
|
|
74
74
|
var getTokenModelName, formBody, formBodyString, _a, fetchResultAction, fetchErrorAction;
|
|
@@ -139,7 +139,7 @@ function getTokenFromRefreshToken(oauthTokenParam) {
|
|
|
139
139
|
if (fetchErrorAction) {
|
|
140
140
|
// ignore time outs and server errors
|
|
141
141
|
// TODO - how to ignore timeouts? which code?
|
|
142
|
-
if (((_b = fetchErrorAction.errorData) === null || _b === void 0 ? void 0 : _b.
|
|
142
|
+
if (((_b = fetchErrorAction.errorData) === null || _b === void 0 ? void 0 : _b.status) && fetchErrorAction.errorData.status >= 500) {
|
|
143
143
|
return [2 /*return*/, oauthTokenParam];
|
|
144
144
|
}
|
|
145
145
|
return [2 /*return*/, null];
|
|
@@ -286,7 +286,7 @@ function handleAuthFailure(action) {
|
|
|
286
286
|
return __generator(this, function (_a) {
|
|
287
287
|
switch (_a.label) {
|
|
288
288
|
case 0:
|
|
289
|
-
if (!(oauthToken && action.errorData && action.errorData.
|
|
289
|
+
if (!(oauthToken && action.errorData && action.errorData.status === 401)) return [3 /*break*/, 2];
|
|
290
290
|
logger.debug('token expired - refreshing');
|
|
291
291
|
return [4 /*yield*/, effects_1.call(performTokenRefresh)];
|
|
292
292
|
case 1:
|
|
@@ -329,6 +329,7 @@ function authSaga(clientCredentialsParam, tokenPersistenceServiceParam, ticketPr
|
|
|
329
329
|
return __generator(this, function (_b) {
|
|
330
330
|
switch (_b.label) {
|
|
331
331
|
case 0:
|
|
332
|
+
logger = logger_1.getLogger();
|
|
332
333
|
/* istanbul ignore if */
|
|
333
334
|
if (!clientCredentialsParam) {
|
|
334
335
|
throw new Error("'clientCredentialsParam' is required for authSaga");
|
|
@@ -40,7 +40,7 @@ function downtimeApiErrorSaga(runIndefinitely) {
|
|
|
40
40
|
return [4 /*yield*/, effects_1.take(function (action) {
|
|
41
41
|
var _a, _b, _c;
|
|
42
42
|
return actions_1.isModelTryFetchErrorAction(action) &&
|
|
43
|
-
((_a = action.errorData) === null || _a === void 0 ? void 0 : _a.
|
|
43
|
+
((_a = action.errorData) === null || _a === void 0 ? void 0 : _a.status) === types_1.HTTP_STATUS_CODE.FORBIDDEN &&
|
|
44
44
|
!!((_c = (_b = action.errorData) === null || _b === void 0 ? void 0 : _b.title) === null || _c === void 0 ? void 0 : _c.includes("We'll be right back!"));
|
|
45
45
|
})
|
|
46
46
|
// redirect to downtime route
|
|
@@ -48,7 +48,7 @@ function lockDownBrowserSaga(runIndefinitely) {
|
|
|
48
48
|
var _a;
|
|
49
49
|
if (!actions_1.isModelTryFetchErrorAction(action))
|
|
50
50
|
return false;
|
|
51
|
-
message = ((_a = action.errorData) === null || _a === void 0 ? void 0 : _a.
|
|
51
|
+
message = ((_a = action.errorData) === null || _a === void 0 ? void 0 : _a.detail) || '';
|
|
52
52
|
return message === null || message === void 0 ? void 0 : message.includes('LockDown Browser');
|
|
53
53
|
})
|
|
54
54
|
// redirect to known LDB error route
|
|
@@ -4,7 +4,6 @@ import { EndpointMappings, ErrorHandler, TokenAccessFunction } from '../../types
|
|
|
4
4
|
import { ModelFetchRequestAction, PeriodicModelFetchRequestAction } from '../actions';
|
|
5
5
|
/** The total number of tries for `fetchData`, including the initial request. */
|
|
6
6
|
export declare const TRY_LIMIT = 5;
|
|
7
|
-
export declare const getState: (state?: any) => any;
|
|
8
7
|
export declare const matchesTerminationAction: (incomingAction: AnyAction, dataRequestAction: PeriodicModelFetchRequestAction) => boolean;
|
|
9
8
|
export declare const takeMatchesTerminationAction: (dataRequestAction: PeriodicModelFetchRequestAction) => (incomingAction: AnyAction) => boolean;
|
|
10
9
|
export declare const defaultTokenAccessFunction: TokenAccessFunction;
|
|
@@ -30,7 +30,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
30
30
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
31
31
|
};
|
|
32
32
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
|
-
exports.fetchModelRecurring = exports.fetchModelLoop = exports.fetchModel = exports.setEndpointMappings = exports.defaultErrorHandler = exports.defaultTokenAccessFunction = exports.takeMatchesTerminationAction = exports.matchesTerminationAction = exports.
|
|
33
|
+
exports.fetchModelRecurring = exports.fetchModelLoop = exports.fetchModel = exports.setEndpointMappings = exports.defaultErrorHandler = exports.defaultTokenAccessFunction = exports.takeMatchesTerminationAction = exports.matchesTerminationAction = exports.TRY_LIMIT = void 0;
|
|
34
34
|
var lodash_1 = require("lodash");
|
|
35
35
|
var moment_timezone_1 = __importDefault(require("moment-timezone"));
|
|
36
36
|
var effects_1 = require("redux-saga/effects");
|
|
@@ -43,8 +43,6 @@ var actions_1 = require("../actions");
|
|
|
43
43
|
/** The total number of tries for `fetchData`, including the initial request. */
|
|
44
44
|
exports.TRY_LIMIT = 5;
|
|
45
45
|
//#region Helpers
|
|
46
|
-
var getState = function (state) { return state; };
|
|
47
|
-
exports.getState = getState;
|
|
48
46
|
var matchesTerminationAction = function (incomingAction, dataRequestAction) {
|
|
49
47
|
return incomingAction.type === actions_1.PERIODIC_MODEL_FETCH_TERMINATION_TYPE.TERMINATE &&
|
|
50
48
|
incomingAction.taskId === dataRequestAction.taskId;
|
|
@@ -146,7 +144,7 @@ function isUserIdle() {
|
|
|
146
144
|
var endpointMappings;
|
|
147
145
|
var tokenAccessFunction;
|
|
148
146
|
var errorHandler;
|
|
149
|
-
var logger
|
|
147
|
+
var logger;
|
|
150
148
|
//#endregion Local Variables
|
|
151
149
|
/** Set the shared EndpointMappings variable, exposed for testability */
|
|
152
150
|
function setEndpointMappings(endpointMappingsParam) {
|
|
@@ -160,10 +158,9 @@ exports.setEndpointMappings = setEndpointMappings;
|
|
|
160
158
|
* @param modelFetchRequestAction A model fetch request action with the request configuration
|
|
161
159
|
*/
|
|
162
160
|
function fetchModel(modelFetchRequestAction) {
|
|
163
|
-
var prepareFetchResult, prepareFetchError, modelPath, fetchConfig, endpointMapping, isCollectionItemCreate, isCollectionItemDelete, tryLimit, tryCount, didFail, lastFetchResult, lastErrorData, fetchResult, oauthToken, resultActionType, data, modelPathLevels,
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
switch (_c.label) {
|
|
161
|
+
var prepareFetchResult, prepareFetchError, error, modelPath, fetchConfig, endpointMapping, isCollectionItemCreate, isCollectionItemDelete, tryLimit, tryCount, didFail, lastFetchResult, lastError, lastErrorData, fetchResult, oauthToken, resultActionType, data, modelPathLevels, caughtError_1, error, errorString, errorData, errorData, error;
|
|
162
|
+
return __generator(this, function (_a) {
|
|
163
|
+
switch (_a.label) {
|
|
167
164
|
case 0:
|
|
168
165
|
prepareFetchResult = undefined;
|
|
169
166
|
prepareFetchError = undefined;
|
|
@@ -174,16 +171,17 @@ function fetchModel(modelFetchRequestAction) {
|
|
|
174
171
|
prepareFetchError = error;
|
|
175
172
|
}
|
|
176
173
|
if (!prepareFetchResult) {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
174
|
+
error = prepareFetchError;
|
|
175
|
+
error.name = 'PrepareFetchError';
|
|
176
|
+
logger.error(error);
|
|
177
|
+
errorHandler(error, modelFetchRequestAction);
|
|
180
178
|
return [2 /*return*/];
|
|
181
179
|
}
|
|
182
180
|
modelPath = prepareFetchResult.modelPath, fetchConfig = prepareFetchResult.fetchConfig, endpointMapping = prepareFetchResult.endpointMapping, isCollectionItemCreate = prepareFetchResult.isCollectionItemCreate, isCollectionItemDelete = prepareFetchResult.isCollectionItemDelete;
|
|
183
181
|
tryLimit = modelFetchRequestAction.noRetry ? 1 : exports.TRY_LIMIT;
|
|
184
182
|
tryCount = 0;
|
|
185
183
|
didFail = false;
|
|
186
|
-
|
|
184
|
+
_a.label = 1;
|
|
187
185
|
case 1:
|
|
188
186
|
didFail = false;
|
|
189
187
|
tryCount++;
|
|
@@ -197,14 +195,14 @@ function fetchModel(modelFetchRequestAction) {
|
|
|
197
195
|
})];
|
|
198
196
|
case 2:
|
|
199
197
|
// dispatch that the fetch request started, which updates `_metadata` and `guid`, if provided, at the target redux `modelPath`
|
|
200
|
-
|
|
198
|
+
_a.sent();
|
|
201
199
|
fetchResult = undefined;
|
|
202
|
-
|
|
200
|
+
_a.label = 3;
|
|
203
201
|
case 3:
|
|
204
|
-
|
|
202
|
+
_a.trys.push([3, 13, , 17]);
|
|
205
203
|
return [4 /*yield*/, effects_1.call(tokenAccessFunction, modelFetchRequestAction.modelName)];
|
|
206
204
|
case 4:
|
|
207
|
-
oauthToken =
|
|
205
|
+
oauthToken = _a.sent();
|
|
208
206
|
if (oauthToken === null || oauthToken === void 0 ? void 0 : oauthToken.access_token) {
|
|
209
207
|
fetchConfig.headers = lodash_1.merge({}, fetchConfig.headers, {
|
|
210
208
|
Authorization: "Bearer " + oauthToken.access_token
|
|
@@ -214,10 +212,13 @@ function fetchModel(modelFetchRequestAction) {
|
|
|
214
212
|
// store `fetchResult` for reference after the do-while loop
|
|
215
213
|
];
|
|
216
214
|
case 5:
|
|
217
|
-
fetchResult =
|
|
215
|
+
fetchResult = _a.sent();
|
|
218
216
|
// store `fetchResult` for reference after the do-while loop
|
|
219
217
|
lastFetchResult = fetchResult;
|
|
220
|
-
|
|
218
|
+
// throw on missing result or unsuccessful result to trigger catch+retry
|
|
219
|
+
if (!(fetchResult === null || fetchResult === void 0 ? void 0 : fetchResult.ok)) {
|
|
220
|
+
throw new Error('fetchResult');
|
|
221
|
+
}
|
|
221
222
|
resultActionType = modelFetchRequestAction.noStore
|
|
222
223
|
? actions_1.MODEL_FETCH_RESULT_TYPE.TRANSIENT_FETCH_RESULT_RECEIVED
|
|
223
224
|
: actions_1.MODEL_FETCH_RESULT_TYPE.FETCH_RESULT_RECEIVED;
|
|
@@ -242,7 +243,7 @@ function fetchModel(modelFetchRequestAction) {
|
|
|
242
243
|
];
|
|
243
244
|
case 6:
|
|
244
245
|
// add by new result's id
|
|
245
|
-
|
|
246
|
+
_a.sent();
|
|
246
247
|
// remove temp item under guid key
|
|
247
248
|
return [4 /*yield*/, effects_1.put({
|
|
248
249
|
type: actions_1.MODEL_REMOVE_KEY_TYPE,
|
|
@@ -250,7 +251,7 @@ function fetchModel(modelFetchRequestAction) {
|
|
|
250
251
|
})];
|
|
251
252
|
case 7:
|
|
252
253
|
// remove temp item under guid key
|
|
253
|
-
|
|
254
|
+
_a.sent();
|
|
254
255
|
return [3 /*break*/, 12];
|
|
255
256
|
case 8:
|
|
256
257
|
if (!isCollectionItemDelete) return [3 /*break*/, 10];
|
|
@@ -259,7 +260,7 @@ function fetchModel(modelFetchRequestAction) {
|
|
|
259
260
|
modelPath: modelPath
|
|
260
261
|
})];
|
|
261
262
|
case 9:
|
|
262
|
-
|
|
263
|
+
_a.sent();
|
|
263
264
|
return [3 /*break*/, 12];
|
|
264
265
|
case 10: return [4 /*yield*/, effects_1.put({
|
|
265
266
|
type: resultActionType,
|
|
@@ -269,49 +270,60 @@ function fetchModel(modelFetchRequestAction) {
|
|
|
269
270
|
data: data
|
|
270
271
|
})];
|
|
271
272
|
case 11:
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
case 12: return [3 /*break*/,
|
|
275
|
-
case 13:
|
|
276
|
-
|
|
277
|
-
throw new Error();
|
|
278
|
-
case 14: return [3 /*break*/, 19];
|
|
279
|
-
case 15:
|
|
280
|
-
error_1 = _c.sent();
|
|
273
|
+
_a.sent();
|
|
274
|
+
_a.label = 12;
|
|
275
|
+
case 12: return [3 /*break*/, 17];
|
|
276
|
+
case 13:
|
|
277
|
+
caughtError_1 = _a.sent();
|
|
281
278
|
didFail = true;
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
279
|
+
error = caughtError_1 instanceof Error ? caughtError_1 : new Error();
|
|
280
|
+
errorString = typeof caughtError_1 === 'string' ? caughtError_1 : error.message;
|
|
281
|
+
errorData = {
|
|
282
|
+
title: 'ModelFetchError',
|
|
283
|
+
detail: errorString === 'fetchResult' ? '' : errorString,
|
|
284
|
+
status: types_1.CUSTOM_ERROR_STATUS_CODE.UNKNOWN
|
|
286
285
|
};
|
|
286
|
+
// use `errorData` from the `fetchResult` if it exists
|
|
287
|
+
if (errorString === 'fetchResult' && (fetchResult === null || fetchResult === void 0 ? void 0 : fetchResult.data) && types_1.isFetchErrorData(fetchResult.data)) {
|
|
288
|
+
errorData = fetchResult.data;
|
|
289
|
+
}
|
|
290
|
+
// update `error` with custom name and details, but preserve stack trace
|
|
291
|
+
error.name = 'ModelFetchError';
|
|
292
|
+
error.message = errorData.detail;
|
|
293
|
+
// track `errorData` and `error` for after the while-loop
|
|
287
294
|
lastErrorData = errorData;
|
|
288
|
-
|
|
295
|
+
lastError = error;
|
|
296
|
+
// dispatch that this try failed
|
|
289
297
|
return [4 /*yield*/, effects_1.put({
|
|
290
298
|
type: actions_1.MODEL_FETCH_ERROR_TYPE.TRY_FETCH_FAILED,
|
|
291
299
|
modelPath: modelPath,
|
|
292
300
|
guid: modelFetchRequestAction.guid,
|
|
293
301
|
errorData: errorData
|
|
294
|
-
})
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
302
|
+
})
|
|
303
|
+
// log to the console
|
|
304
|
+
];
|
|
305
|
+
case 14:
|
|
306
|
+
// dispatch that this try failed
|
|
307
|
+
_a.sent();
|
|
308
|
+
// log to the console
|
|
309
|
+
logger.error(caughtError_1);
|
|
299
310
|
// Do not continue to retry if the response is between 400-500 (except 408: server timeout)
|
|
300
|
-
if (errorData.
|
|
311
|
+
if (errorData.status >= 400 && errorData.status < 500 && errorData.status !== 408) {
|
|
301
312
|
tryCount = tryLimit;
|
|
302
313
|
}
|
|
303
|
-
if (!(tryCount < tryLimit)) return [3 /*break*/,
|
|
314
|
+
if (!(tryCount < tryLimit)) return [3 /*break*/, 16];
|
|
304
315
|
return [4 /*yield*/, effects_1.delay(Math.pow(2, (tryCount - 1)) * 100)]; // 100, 200, 400, 800
|
|
316
|
+
case 15:
|
|
317
|
+
_a.sent(); // 100, 200, 400, 800
|
|
318
|
+
_a.label = 16;
|
|
319
|
+
case 16: return [3 /*break*/, 17];
|
|
305
320
|
case 17:
|
|
306
|
-
_c.sent(); // 100, 200, 400, 800
|
|
307
|
-
_c.label = 18;
|
|
308
|
-
case 18: return [3 /*break*/, 19];
|
|
309
|
-
case 19:
|
|
310
321
|
if (tryCount < tryLimit && didFail) return [3 /*break*/, 1];
|
|
311
|
-
|
|
312
|
-
case
|
|
313
|
-
if (!(tryCount === tryLimit && didFail)) return [3 /*break*/,
|
|
322
|
+
_a.label = 18;
|
|
323
|
+
case 18:
|
|
324
|
+
if (!(tryCount === tryLimit && didFail)) return [3 /*break*/, 20];
|
|
314
325
|
errorData = lastErrorData;
|
|
326
|
+
error = lastError;
|
|
315
327
|
// dispatch that the fetch failed, which updates `_metadata` (and `guid`, if provided) at the target redux `modelPath`
|
|
316
328
|
return [4 /*yield*/, effects_1.put({
|
|
317
329
|
type: modelFetchRequestAction.noStore
|
|
@@ -323,15 +335,15 @@ function fetchModel(modelFetchRequestAction) {
|
|
|
323
335
|
})
|
|
324
336
|
// Send error to error handler, except for 401s
|
|
325
337
|
];
|
|
326
|
-
case
|
|
338
|
+
case 19:
|
|
327
339
|
// dispatch that the fetch failed, which updates `_metadata` (and `guid`, if provided) at the target redux `modelPath`
|
|
328
|
-
|
|
340
|
+
_a.sent();
|
|
329
341
|
// Send error to error handler, except for 401s
|
|
330
|
-
if (
|
|
331
|
-
errorHandler(
|
|
342
|
+
if (errorData.status !== 401) {
|
|
343
|
+
errorHandler(error, modelFetchRequestAction, fetchConfig, lastFetchResult, errorData);
|
|
332
344
|
}
|
|
333
|
-
|
|
334
|
-
case
|
|
345
|
+
_a.label = 20;
|
|
346
|
+
case 20: return [2 /*return*/];
|
|
335
347
|
}
|
|
336
348
|
});
|
|
337
349
|
}
|
|
@@ -342,7 +354,7 @@ exports.fetchModel = fetchModel;
|
|
|
342
354
|
* @param action An action with the request configuration
|
|
343
355
|
*/
|
|
344
356
|
function fetchModelLoop(action) {
|
|
345
|
-
var hasFetched,
|
|
357
|
+
var hasFetched, error_1;
|
|
346
358
|
return __generator(this, function (_a) {
|
|
347
359
|
switch (_a.label) {
|
|
348
360
|
case 0:
|
|
@@ -365,10 +377,10 @@ function fetchModelLoop(action) {
|
|
|
365
377
|
_a.label = 6;
|
|
366
378
|
case 6: return [3 /*break*/, 12];
|
|
367
379
|
case 7:
|
|
368
|
-
|
|
369
|
-
logger.error(
|
|
380
|
+
error_1 = _a.sent();
|
|
381
|
+
logger.error(error_1);
|
|
370
382
|
// catch and log any unexpected errors not caught inside `fetchData`
|
|
371
|
-
errorHandler(
|
|
383
|
+
errorHandler(error_1, action);
|
|
372
384
|
return [3 /*break*/, 12];
|
|
373
385
|
case 8: return [4 /*yield*/, effects_1.cancelled()];
|
|
374
386
|
case 9:
|
|
@@ -463,6 +475,7 @@ function modelFetchSaga(endpointMappingsParam, apiRootParam, tokenAccessFunction
|
|
|
463
475
|
setEndpointMappings(endpointMappingsParam);
|
|
464
476
|
errorHandler = errorHandlerParam;
|
|
465
477
|
tokenAccessFunction = tokenAccessFunctionParam;
|
|
478
|
+
logger = logger_1.getLogger();
|
|
466
479
|
return [4 /*yield*/, effects_1.takeEvery(actions_1.MODEL_FETCH_REQUEST_TYPE.FETCH_REQUEST, fetchModel)];
|
|
467
480
|
case 1:
|
|
468
481
|
_a.sent();
|
|
@@ -102,11 +102,13 @@ function dependentSagas() {
|
|
|
102
102
|
}
|
|
103
103
|
});
|
|
104
104
|
}
|
|
105
|
-
var errorHandler = function (error, fetchConfig, fetchResult) {
|
|
105
|
+
var errorHandler = function (error, modelFetchRequestAction, fetchConfig, fetchResult, fetchErrorData) {
|
|
106
106
|
Sentry.captureException(error, {
|
|
107
107
|
contexts: {
|
|
108
|
+
'Fetch Action': __assign({}, modelFetchRequestAction),
|
|
108
109
|
'Fetch Config': (fetchConfig || {}),
|
|
109
|
-
'Fetch Result': (fetchResult || {})
|
|
110
|
+
'Fetch Result': (fetchResult || {}),
|
|
111
|
+
'Fetch Error Data': (fetchErrorData || {})
|
|
110
112
|
}
|
|
111
113
|
});
|
|
112
114
|
};
|
|
@@ -87,9 +87,10 @@ function isContentTypeJson(contentType) {
|
|
|
87
87
|
*/
|
|
88
88
|
// TODO: provide logging injection
|
|
89
89
|
function doFetch(config) {
|
|
90
|
-
var method, headers, isBodyJson, body, response, result, isResponseJson, _a, _b;
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
var method, headers, isBodyJson, body, response, result, isResponseJson, _a, _b, errorData;
|
|
91
|
+
var _c, _d, _e, _f, _g, _h;
|
|
92
|
+
return __generator(this, function (_j) {
|
|
93
|
+
switch (_j.label) {
|
|
93
94
|
case 0:
|
|
94
95
|
if (!config.path) {
|
|
95
96
|
throw new Error("'config.path' is required for fetchService");
|
|
@@ -111,7 +112,7 @@ function doFetch(config) {
|
|
|
111
112
|
body: body
|
|
112
113
|
})];
|
|
113
114
|
case 1:
|
|
114
|
-
response =
|
|
115
|
+
response = _j.sent();
|
|
115
116
|
if (!response) {
|
|
116
117
|
return [2 /*return*/, undefined];
|
|
117
118
|
}
|
|
@@ -140,23 +141,26 @@ function doFetch(config) {
|
|
|
140
141
|
if (!isResponseJson) return [3 /*break*/, 4];
|
|
141
142
|
return [4 /*yield*/, effects_1.call(function () { return response.json(); })];
|
|
142
143
|
case 3:
|
|
143
|
-
_b =
|
|
144
|
+
_b = _j.sent();
|
|
144
145
|
return [3 /*break*/, 6];
|
|
145
146
|
case 4: return [4 /*yield*/, effects_1.call(function () { return response.text(); })];
|
|
146
147
|
case 5:
|
|
147
|
-
_b =
|
|
148
|
-
|
|
148
|
+
_b = _j.sent();
|
|
149
|
+
_j.label = 6;
|
|
149
150
|
case 6:
|
|
150
151
|
_a.data = _b;
|
|
151
|
-
|
|
152
|
+
_j.label = 7;
|
|
152
153
|
case 7:
|
|
153
154
|
if (!response.ok) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
155
|
+
errorData = {
|
|
156
|
+
title: ((_c = result.data) === null || _c === void 0 ? void 0 : _c.title) || 'FetchError',
|
|
157
|
+
detail: ((_d = result.data) === null || _d === void 0 ? void 0 : _d.detail) || response.statusText,
|
|
158
|
+
status: ((_e = result.data) === null || _e === void 0 ? void 0 : _e.status) || response.status,
|
|
159
|
+
type: (_f = result.data) === null || _f === void 0 ? void 0 : _f.type,
|
|
160
|
+
instance: (_g = result.data) === null || _g === void 0 ? void 0 : _g.instance,
|
|
161
|
+
traceId: (_h = result.data) === null || _h === void 0 ? void 0 : _h.traceId
|
|
162
|
+
};
|
|
163
|
+
result.data = errorData;
|
|
160
164
|
}
|
|
161
165
|
return [2 /*return*/, result];
|
|
162
166
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ModelFetchRequestAction, PeriodicModelFetchRequestAction } from '../../redux/actions/ModelAction';
|
|
2
2
|
import { FetchConfig } from './FetchConfig';
|
|
3
|
+
import { FetchErrorData } from './FetchErrorData';
|
|
3
4
|
import { FetchResult } from './FetchResult';
|
|
4
|
-
export declare type ErrorHandler = (error: Error, modelFetchRequestAction: ModelFetchRequestAction | PeriodicModelFetchRequestAction, fetchConfig?: FetchConfig, fetchResult?: FetchResult) => void;
|
|
5
|
+
export declare type ErrorHandler = (error: Error, modelFetchRequestAction: ModelFetchRequestAction | PeriodicModelFetchRequestAction, fetchConfig?: FetchConfig, fetchResult?: FetchResult, fetchErrorData?: FetchErrorData) => void;
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
export declare enum
|
|
1
|
+
export declare enum CUSTOM_ERROR_STATUS_CODE {
|
|
2
2
|
UNKNOWN = -1,
|
|
3
3
|
NO_NETWORK_CONNECTION = -2
|
|
4
4
|
}
|
|
5
5
|
export interface FetchErrorData {
|
|
6
|
+
status: number;
|
|
6
7
|
title: string;
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
detail: string;
|
|
9
|
+
type?: string;
|
|
10
|
+
instance?: string;
|
|
11
|
+
traceId?: string;
|
|
9
12
|
}
|
|
10
13
|
export declare const isFetchErrorData: (errorData: any) => errorData is FetchErrorData;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isFetchErrorData = exports.
|
|
4
|
-
var
|
|
5
|
-
(function (
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
})(
|
|
3
|
+
exports.isFetchErrorData = exports.CUSTOM_ERROR_STATUS_CODE = void 0;
|
|
4
|
+
var CUSTOM_ERROR_STATUS_CODE;
|
|
5
|
+
(function (CUSTOM_ERROR_STATUS_CODE) {
|
|
6
|
+
CUSTOM_ERROR_STATUS_CODE[CUSTOM_ERROR_STATUS_CODE["UNKNOWN"] = -1] = "UNKNOWN";
|
|
7
|
+
CUSTOM_ERROR_STATUS_CODE[CUSTOM_ERROR_STATUS_CODE["NO_NETWORK_CONNECTION"] = -2] = "NO_NETWORK_CONNECTION";
|
|
8
|
+
})(CUSTOM_ERROR_STATUS_CODE = exports.CUSTOM_ERROR_STATUS_CODE || (exports.CUSTOM_ERROR_STATUS_CODE = {}));
|
|
9
9
|
var isFetchErrorData = function (errorData) {
|
|
10
10
|
return typeof errorData === 'object' &&
|
|
11
|
+
Object.prototype.hasOwnProperty.call(errorData, 'status') &&
|
|
11
12
|
Object.prototype.hasOwnProperty.call(errorData, 'title') &&
|
|
12
|
-
Object.prototype.hasOwnProperty.call(errorData, '
|
|
13
|
-
Object.prototype.hasOwnProperty.call(errorData, 'code');
|
|
13
|
+
Object.prototype.hasOwnProperty.call(errorData, 'detail');
|
|
14
14
|
};
|
|
15
15
|
exports.isFetchErrorData = isFetchErrorData;
|
package/lib/utils/user.js
CHANGED
|
@@ -32,7 +32,7 @@ var startImpersonation = function (guid, userId) {
|
|
|
32
32
|
noStoreSaga_1.unregisterNoStoreActionHook(guid);
|
|
33
33
|
if (!data || types_1.isFetchErrorData(data)) {
|
|
34
34
|
actionCreator_1.addNotification({
|
|
35
|
-
text: (data === null || data === void 0 ? void 0 : data.
|
|
35
|
+
text: (data === null || data === void 0 ? void 0 : data.detail) || 'Could not start impersonation',
|
|
36
36
|
type: constants_1.NOTIFICATION_TYPE.ERROR
|
|
37
37
|
});
|
|
38
38
|
}
|
|
@@ -54,7 +54,7 @@ var stopImpersonation = function (guid) {
|
|
|
54
54
|
noStoreSaga_1.unregisterNoStoreActionHook(guid);
|
|
55
55
|
if (!data || types_1.isFetchErrorData(data)) {
|
|
56
56
|
actionCreator_1.addNotification({
|
|
57
|
-
text: (data === null || data === void 0 ? void 0 : data.
|
|
57
|
+
text: (data === null || data === void 0 ? void 0 : data.detail) || 'Could not stop impersonation',
|
|
58
58
|
type: constants_1.NOTIFICATION_TYPE.ERROR
|
|
59
59
|
});
|
|
60
60
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "studiokit-scaffolding-js",
|
|
3
|
-
"version": "5.2.0-next.2.
|
|
3
|
+
"version": "5.2.0-next.2.2",
|
|
4
4
|
"description": "Common scaffolding for Studio apps at Purdue",
|
|
5
5
|
"repository": "https://gitlab.com/purdue-informatics/studiokit/studiokit-scaffolding-js",
|
|
6
6
|
"license": "MIT",
|