1 | import type { Middleware, UnknownAction } from 'redux'
|
2 | import type { ThunkMiddleware } from 'redux-thunk'
|
3 | import { thunk as thunkMiddleware, withExtraArgument } from 'redux-thunk'
|
4 | import type { ActionCreatorInvariantMiddlewareOptions } from './actionCreatorInvariantMiddleware'
|
5 | import { createActionCreatorInvariantMiddleware } from './actionCreatorInvariantMiddleware'
|
6 | import type { ImmutableStateInvariantMiddlewareOptions } from './immutableStateInvariantMiddleware'
|
7 |
|
8 | import { createImmutableStateInvariantMiddleware } from './immutableStateInvariantMiddleware'
|
9 |
|
10 |
|
11 | import type { SerializableStateInvariantMiddlewareOptions } from './serializableStateInvariantMiddleware'
|
12 | import { createSerializableStateInvariantMiddleware } from './serializableStateInvariantMiddleware'
|
13 | import type { ExcludeFromTuple } from './tsHelpers'
|
14 | import { Tuple } from './utils'
|
15 |
|
16 | function isBoolean(x: any): x is boolean {
|
17 | return typeof x === 'boolean'
|
18 | }
|
19 |
|
20 | interface ThunkOptions<E = any> {
|
21 | extraArgument: E
|
22 | }
|
23 |
|
24 | interface GetDefaultMiddlewareOptions {
|
25 | thunk?: boolean | ThunkOptions
|
26 | immutableCheck?: boolean | ImmutableStateInvariantMiddlewareOptions
|
27 | serializableCheck?: boolean | SerializableStateInvariantMiddlewareOptions
|
28 | actionCreatorCheck?: boolean | ActionCreatorInvariantMiddlewareOptions
|
29 | }
|
30 |
|
31 | export type ThunkMiddlewareFor<
|
32 | S,
|
33 | O extends GetDefaultMiddlewareOptions = {},
|
34 | > = O extends {
|
35 | thunk: false
|
36 | }
|
37 | ? never
|
38 | : O extends { thunk: { extraArgument: infer E } }
|
39 | ? ThunkMiddleware<S, UnknownAction, E>
|
40 | : ThunkMiddleware<S, UnknownAction>
|
41 |
|
42 | export type GetDefaultMiddleware<S = any> = <
|
43 | O extends GetDefaultMiddlewareOptions = {
|
44 | thunk: true
|
45 | immutableCheck: true
|
46 | serializableCheck: true
|
47 | actionCreatorCheck: true
|
48 | },
|
49 | >(
|
50 | options?: O,
|
51 | ) => Tuple<ExcludeFromTuple<[ThunkMiddlewareFor<S, O>], never>>
|
52 |
|
53 | export const buildGetDefaultMiddleware = <S = any>(): GetDefaultMiddleware<S> =>
|
54 | function getDefaultMiddleware(options) {
|
55 | const {
|
56 | thunk = true,
|
57 | immutableCheck = true,
|
58 | serializableCheck = true,
|
59 | actionCreatorCheck = true,
|
60 | } = options ?? {}
|
61 |
|
62 | let middlewareArray = new Tuple<Middleware[]>()
|
63 |
|
64 | if (thunk) {
|
65 | if (isBoolean(thunk)) {
|
66 | middlewareArray.push(thunkMiddleware)
|
67 | } else {
|
68 | middlewareArray.push(withExtraArgument(thunk.extraArgument))
|
69 | }
|
70 | }
|
71 |
|
72 | if (process.env.NODE_ENV !== 'production') {
|
73 | if (immutableCheck) {
|
74 |
|
75 | let immutableOptions: ImmutableStateInvariantMiddlewareOptions = {}
|
76 |
|
77 | if (!isBoolean(immutableCheck)) {
|
78 | immutableOptions = immutableCheck
|
79 | }
|
80 |
|
81 | middlewareArray.unshift(
|
82 | createImmutableStateInvariantMiddleware(immutableOptions),
|
83 | )
|
84 |
|
85 | }
|
86 |
|
87 | if (serializableCheck) {
|
88 | let serializableOptions: SerializableStateInvariantMiddlewareOptions =
|
89 | {}
|
90 |
|
91 | if (!isBoolean(serializableCheck)) {
|
92 | serializableOptions = serializableCheck
|
93 | }
|
94 |
|
95 | middlewareArray.push(
|
96 | createSerializableStateInvariantMiddleware(serializableOptions),
|
97 | )
|
98 | }
|
99 | if (actionCreatorCheck) {
|
100 | let actionCreatorOptions: ActionCreatorInvariantMiddlewareOptions = {}
|
101 |
|
102 | if (!isBoolean(actionCreatorCheck)) {
|
103 | actionCreatorOptions = actionCreatorCheck
|
104 | }
|
105 |
|
106 | middlewareArray.unshift(
|
107 | createActionCreatorInvariantMiddleware(actionCreatorOptions),
|
108 | )
|
109 | }
|
110 | }
|
111 |
|
112 | return middlewareArray as any
|
113 | }
|