This repository was archived by the owner on Mar 19, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathUnhandledErrorStoreModule.ts
More file actions
84 lines (76 loc) · 2.8 KB
/
UnhandledErrorStoreModule.ts
File metadata and controls
84 lines (76 loc) · 2.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import { Action } from 'wdk-client/Actions';
import { ActionsObservable, StateObservable } from 'redux-observable';
import { Observable, EMPTY, fromEvent, merge } from 'rxjs';
import { filter, tap, mergeMapTo, map, mapTo } from 'rxjs/operators';
import { notifyUnhandledError, clearUnhandledErrors, UnhandledError } from 'wdk-client/Actions/UnhandledErrorActions';
import { RootState } from 'wdk-client/Core/State/Types';
import { EpicDependencies } from 'wdk-client/Core/Store';
import { updateLocation } from 'wdk-client/Actions/RouterActions';
export const key = 'unhandledErrors';
export interface State {
errors: UnhandledError[]
}
const initialState: State = {
errors: []
}
export function reduce(state: State = initialState, action: Action): State {
switch(action.type) {
case notifyUnhandledError.type:
return {
...state,
errors: [ ...state.errors, action.payload.unhandledError ]
}
case clearUnhandledErrors.type:
return {
errors: []
};
default:
return state;
}
}
// TODO Allow this to be configured by wdk-client consumer
function ignoreError(message: string): boolean {
return (
/ResizeObserver loop limit exceeded/.test(message) ||
/empty textures are not allowed/.test(message)
)
}
export function observe(action$: ActionsObservable<Action>, state$: StateObservable<RootState>, { wdkService }: EpicDependencies): Observable<Action> {
// map unhandled promise rejections to unhandledError action
const rejection$: Observable<Action> = fromEvent<PromiseRejectionEvent>(window, 'unhandledrejection').pipe(
filter((event: PromiseRejectionEvent) => {
return !ignoreError(String(event.reason));
}),
map((event: PromiseRejectionEvent) => notifyUnhandledError(event.reason))
);
// map unhandled errors to unhandledError action
const error$: Observable<Action> = fromEvent<ErrorEvent>(window, 'error').pipe(
filter((event: ErrorEvent) => {
return !ignoreError(event.message);
}),
map((event: ErrorEvent) => {
return notifyUnhandledError(event.error ?? event.message)
})
);
// clear errors when route changes
const clear$: Observable<Action> = action$.pipe(
filter(updateLocation.isOfType),
mapTo(clearUnhandledErrors())
);
// log errors as they come in
const notify$: Observable<never> = action$.pipe(
filter(notifyUnhandledError.isOfType),
tap(async action => {
try {
const { unhandledError: { error, id, info } } = action.payload;
console.error(error);
await wdkService.submitErrorIfNot500(error instanceof Error ? error : new Error(String(error)), { id, info });
}
catch (error) {
console.error('Error logging request failed:', error);
}
}),
mergeMapTo(EMPTY),
);
return merge(rejection$, error$, clear$, notify$);
}