@depup/reduxjs__toolkit 2.12.0-depup.28

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.
Files changed (173) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +33 -0
  3. package/changes.json +18 -0
  4. package/dist/cjs/index.js +6 -0
  5. package/dist/cjs/redux-toolkit.development.cjs +2406 -0
  6. package/dist/cjs/redux-toolkit.development.cjs.map +1 -0
  7. package/dist/cjs/redux-toolkit.production.min.cjs +3 -0
  8. package/dist/cjs/redux-toolkit.production.min.cjs.map +1 -0
  9. package/dist/index.d.mts +2665 -0
  10. package/dist/index.d.ts +2665 -0
  11. package/dist/query/cjs/index.js +6 -0
  12. package/dist/query/cjs/rtk-query.development.cjs +3092 -0
  13. package/dist/query/cjs/rtk-query.development.cjs.map +1 -0
  14. package/dist/query/cjs/rtk-query.production.min.cjs +2 -0
  15. package/dist/query/cjs/rtk-query.production.min.cjs.map +1 -0
  16. package/dist/query/index.d.mts +3066 -0
  17. package/dist/query/index.d.ts +3066 -0
  18. package/dist/query/react/cjs/index.js +6 -0
  19. package/dist/query/react/cjs/rtk-query-react.development.cjs +748 -0
  20. package/dist/query/react/cjs/rtk-query-react.development.cjs.map +1 -0
  21. package/dist/query/react/cjs/rtk-query-react.production.min.cjs +2 -0
  22. package/dist/query/react/cjs/rtk-query-react.production.min.cjs.map +1 -0
  23. package/dist/query/react/index.d.mts +1009 -0
  24. package/dist/query/react/index.d.ts +1009 -0
  25. package/dist/query/react/rtk-query-react.browser.mjs +2 -0
  26. package/dist/query/react/rtk-query-react.browser.mjs.map +1 -0
  27. package/dist/query/react/rtk-query-react.legacy-esm.js +740 -0
  28. package/dist/query/react/rtk-query-react.legacy-esm.js.map +1 -0
  29. package/dist/query/react/rtk-query-react.modern.mjs +705 -0
  30. package/dist/query/react/rtk-query-react.modern.mjs.map +1 -0
  31. package/dist/query/rtk-query.browser.mjs +2 -0
  32. package/dist/query/rtk-query.browser.mjs.map +1 -0
  33. package/dist/query/rtk-query.legacy-esm.js +3117 -0
  34. package/dist/query/rtk-query.legacy-esm.js.map +1 -0
  35. package/dist/query/rtk-query.modern.mjs +3052 -0
  36. package/dist/query/rtk-query.modern.mjs.map +1 -0
  37. package/dist/react/cjs/index.js +6 -0
  38. package/dist/react/cjs/redux-toolkit-react.development.cjs +55 -0
  39. package/dist/react/cjs/redux-toolkit-react.development.cjs.map +1 -0
  40. package/dist/react/cjs/redux-toolkit-react.production.min.cjs +2 -0
  41. package/dist/react/cjs/redux-toolkit-react.production.min.cjs.map +1 -0
  42. package/dist/react/index.d.mts +22 -0
  43. package/dist/react/index.d.ts +22 -0
  44. package/dist/react/redux-toolkit-react.browser.mjs +2 -0
  45. package/dist/react/redux-toolkit-react.browser.mjs.map +1 -0
  46. package/dist/react/redux-toolkit-react.legacy-esm.js +47 -0
  47. package/dist/react/redux-toolkit-react.legacy-esm.js.map +1 -0
  48. package/dist/react/redux-toolkit-react.modern.mjs +28 -0
  49. package/dist/react/redux-toolkit-react.modern.mjs.map +1 -0
  50. package/dist/redux-toolkit.browser.mjs +3 -0
  51. package/dist/redux-toolkit.browser.mjs.map +1 -0
  52. package/dist/redux-toolkit.legacy-esm.js +2351 -0
  53. package/dist/redux-toolkit.legacy-esm.js.map +1 -0
  54. package/dist/redux-toolkit.modern.mjs +2330 -0
  55. package/dist/redux-toolkit.modern.mjs.map +1 -0
  56. package/dist/uncheckedindexed.ts +16 -0
  57. package/package.json +310 -0
  58. package/query/package.json +13 -0
  59. package/query/react/package.json +13 -0
  60. package/react/package.json +13 -0
  61. package/skills/build-modern-redux-apps/modern-redux/SKILL.md +304 -0
  62. package/skills/build-modern-redux-apps/modern-redux/references/store-lifetime.md +53 -0
  63. package/skills/build-modern-redux-apps/redux-dataflow/SKILL.md +264 -0
  64. package/skills/evolve-and-diagnose-redux-apps/debug-redux-toolkit-apps/SKILL.md +269 -0
  65. package/skills/evolve-and-diagnose-redux-apps/migrate-to-modern-redux/SKILL.md +226 -0
  66. package/skills/manage-server-data/adopt-rtk-query/SKILL.md +385 -0
  67. package/skills/manage-server-data/adopt-rtk-query/references/endpoint-lifecycle.md +36 -0
  68. package/skills/model-redux-state/build-slices-and-selectors/SKILL.md +364 -0
  69. package/skills/model-redux-state/build-slices-and-selectors/references/slice-patterns.md +59 -0
  70. package/skills/model-redux-state/design-state-ownership/SKILL.md +322 -0
  71. package/skills/model-redux-state/design-state-ownership/references/state-ownership.md +28 -0
  72. package/skills/orchestrate-side-effects/handle-side-effects/SKILL.md +271 -0
  73. package/skills/orchestrate-side-effects/handle-side-effects/references/listener-workflows.md +34 -0
  74. package/src/actionCreatorInvariantMiddleware.ts +34 -0
  75. package/src/autoBatchEnhancer.ts +146 -0
  76. package/src/combineSlices.ts +487 -0
  77. package/src/configureStore.ts +248 -0
  78. package/src/createAction.ts +324 -0
  79. package/src/createAsyncThunk.ts +791 -0
  80. package/src/createDraftSafeSelector.ts +30 -0
  81. package/src/createReducer.ts +217 -0
  82. package/src/createSlice.ts +1079 -0
  83. package/src/devtoolsExtension.ts +241 -0
  84. package/src/dynamicMiddleware/index.ts +93 -0
  85. package/src/dynamicMiddleware/react/index.ts +101 -0
  86. package/src/dynamicMiddleware/types.ts +82 -0
  87. package/src/entities/create_adapter.ts +47 -0
  88. package/src/entities/entity_state.ts +38 -0
  89. package/src/entities/index.ts +8 -0
  90. package/src/entities/models.ts +198 -0
  91. package/src/entities/sorted_state_adapter.ts +266 -0
  92. package/src/entities/state_adapter.ts +58 -0
  93. package/src/entities/state_selectors.ts +73 -0
  94. package/src/entities/unsorted_state_adapter.ts +204 -0
  95. package/src/entities/utils.ts +68 -0
  96. package/src/formatProdErrorMessage.ts +13 -0
  97. package/src/getDefaultEnhancers.ts +31 -0
  98. package/src/getDefaultMiddleware.ts +113 -0
  99. package/src/immerImports.ts +7 -0
  100. package/src/immutableStateInvariantMiddleware.ts +274 -0
  101. package/src/index.ts +213 -0
  102. package/src/listenerMiddleware/exceptions.ts +20 -0
  103. package/src/listenerMiddleware/index.ts +562 -0
  104. package/src/listenerMiddleware/task.ts +100 -0
  105. package/src/listenerMiddleware/types.ts +886 -0
  106. package/src/listenerMiddleware/utils.ts +30 -0
  107. package/src/mapBuilders.ts +298 -0
  108. package/src/matchers.ts +365 -0
  109. package/src/nanoid.ts +20 -0
  110. package/src/query/HandledError.ts +6 -0
  111. package/src/query/apiTypes.ts +120 -0
  112. package/src/query/baseQueryTypes.ts +101 -0
  113. package/src/query/core/apiState.ts +377 -0
  114. package/src/query/core/buildInitiate.ts +596 -0
  115. package/src/query/core/buildMiddleware/batchActions.ts +207 -0
  116. package/src/query/core/buildMiddleware/cacheCollection.ts +204 -0
  117. package/src/query/core/buildMiddleware/cacheLifecycle.ts +379 -0
  118. package/src/query/core/buildMiddleware/devMiddleware.ts +34 -0
  119. package/src/query/core/buildMiddleware/index.ts +162 -0
  120. package/src/query/core/buildMiddleware/invalidationByTags.ts +139 -0
  121. package/src/query/core/buildMiddleware/polling.ts +187 -0
  122. package/src/query/core/buildMiddleware/queryLifecycle.ts +508 -0
  123. package/src/query/core/buildMiddleware/types.ts +173 -0
  124. package/src/query/core/buildMiddleware/windowEventHandling.ts +64 -0
  125. package/src/query/core/buildSelectors.ts +413 -0
  126. package/src/query/core/buildSlice.ts +735 -0
  127. package/src/query/core/buildThunks.ts +1124 -0
  128. package/src/query/core/index.ts +58 -0
  129. package/src/query/core/module.ts +727 -0
  130. package/src/query/core/rtkImports.ts +24 -0
  131. package/src/query/core/setupListeners.ts +118 -0
  132. package/src/query/createApi.ts +506 -0
  133. package/src/query/defaultSerializeQueryArgs.ts +52 -0
  134. package/src/query/endpointDefinitions.ts +1717 -0
  135. package/src/query/fakeBaseQuery.ts +21 -0
  136. package/src/query/fetchBaseQuery.ts +385 -0
  137. package/src/query/index.ts +105 -0
  138. package/src/query/react/ApiProvider.tsx +69 -0
  139. package/src/query/react/buildHooks.ts +2297 -0
  140. package/src/query/react/constants.ts +2 -0
  141. package/src/query/react/index.ts +45 -0
  142. package/src/query/react/module.ts +275 -0
  143. package/src/query/react/namedHooks.ts +59 -0
  144. package/src/query/react/reactImports.ts +10 -0
  145. package/src/query/react/reactReduxImports.ts +1 -0
  146. package/src/query/react/rtkqImports.ts +8 -0
  147. package/src/query/react/useSerializedStableValue.ts +17 -0
  148. package/src/query/react/useShallowStableValue.ts +13 -0
  149. package/src/query/retry.ts +233 -0
  150. package/src/query/standardSchema.ts +35 -0
  151. package/src/query/tsHelpers.ts +48 -0
  152. package/src/query/utils/capitalize.ts +3 -0
  153. package/src/query/utils/copyWithStructuralSharing.ts +27 -0
  154. package/src/query/utils/countObjectKeys.ts +14 -0
  155. package/src/query/utils/filterMap.ts +27 -0
  156. package/src/query/utils/getCurrent.ts +6 -0
  157. package/src/query/utils/getOrInsert.ts +41 -0
  158. package/src/query/utils/immerImports.ts +9 -0
  159. package/src/query/utils/index.ts +11 -0
  160. package/src/query/utils/isAbsoluteUrl.ts +9 -0
  161. package/src/query/utils/isDocumentVisible.ts +12 -0
  162. package/src/query/utils/isNotNullish.ts +7 -0
  163. package/src/query/utils/isOnline.ts +12 -0
  164. package/src/query/utils/isValidUrl.ts +9 -0
  165. package/src/query/utils/joinUrls.ts +26 -0
  166. package/src/query/utils/signals.ts +33 -0
  167. package/src/react/index.ts +7 -0
  168. package/src/reduxImports.ts +8 -0
  169. package/src/reselectImports.ts +1 -0
  170. package/src/serializableStateInvariantMiddleware.ts +285 -0
  171. package/src/tsHelpers.ts +214 -0
  172. package/src/uncheckedindexed.ts +16 -0
  173. package/src/utils.ts +125 -0
@@ -0,0 +1,1124 @@
1
+ import type {
2
+ AsyncThunk,
3
+ AsyncThunkPayloadCreator,
4
+ Draft,
5
+ ThunkAction,
6
+ ThunkDispatch,
7
+ UnknownAction,
8
+ } from '@reduxjs/toolkit'
9
+ import type { Patch } from 'immer'
10
+ import { isDraftable, produceWithPatches } from '../utils/immerImports'
11
+ import type { Api, ApiContext } from '../apiTypes'
12
+ import type {
13
+ BaseQueryError,
14
+ BaseQueryFn,
15
+ QueryReturnValue,
16
+ } from '../baseQueryTypes'
17
+ import type { InternalSerializeQueryArgs } from '../defaultSerializeQueryArgs'
18
+ import type {
19
+ AssertTagTypes,
20
+ EndpointDefinition,
21
+ EndpointDefinitions,
22
+ InfiniteQueryArgFrom,
23
+ InfiniteQueryCombinedArg,
24
+ InfiniteQueryDefinition,
25
+ MutationDefinition,
26
+ PageParamFrom,
27
+ QueryArgFrom,
28
+ QueryDefinition,
29
+ ResultDescription,
30
+ ResultTypeFrom,
31
+ SchemaFailureConverter,
32
+ SchemaFailureHandler,
33
+ SchemaFailureInfo,
34
+ SchemaType,
35
+ } from '../endpointDefinitions'
36
+ import {
37
+ calculateProvidedBy,
38
+ ENDPOINT_QUERY,
39
+ isInfiniteQueryDefinition,
40
+ isQueryDefinition,
41
+ } from '../endpointDefinitions'
42
+ import { HandledError } from '../HandledError'
43
+ import type { UnwrapPromise } from '../tsHelpers'
44
+ import type {
45
+ RootState,
46
+ QueryKeys,
47
+ QuerySubstateIdentifier,
48
+ InfiniteData,
49
+ InfiniteQueryConfigOptions,
50
+ QueryCacheKey,
51
+ InfiniteQueryDirection,
52
+ InfiniteQueryKeys,
53
+ } from './apiState'
54
+ import { QueryStatus, STATUS_UNINITIALIZED } from './apiState'
55
+ import type {
56
+ InfiniteQueryActionCreatorResult,
57
+ QueryActionCreatorResult,
58
+ StartInfiniteQueryActionCreatorOptions,
59
+ StartQueryActionCreatorOptions,
60
+ } from './buildInitiate'
61
+ import { forceQueryFnSymbol, isUpsertQuery } from './buildInitiate'
62
+ import type { AllSelectors } from './buildSelectors'
63
+ import type { ApiEndpointQuery, PrefetchOptions } from './module'
64
+ import {
65
+ createAsyncThunk,
66
+ isAllOf,
67
+ isFulfilled,
68
+ isPending,
69
+ isRejected,
70
+ isRejectedWithValue,
71
+ SHOULD_AUTOBATCH,
72
+ } from './rtkImports'
73
+ import {
74
+ parseWithSchema,
75
+ NamedSchemaError,
76
+ shouldSkip,
77
+ } from '../standardSchema'
78
+
79
+ export type BuildThunksApiEndpointQuery<
80
+ Definition extends QueryDefinition<any, any, any, any, any>,
81
+ > = Matchers<QueryThunk, Definition>
82
+
83
+ export type BuildThunksApiEndpointInfiniteQuery<
84
+ Definition extends InfiniteQueryDefinition<any, any, any, any, any>,
85
+ > = Matchers<InfiniteQueryThunk<any>, Definition>
86
+
87
+ export type BuildThunksApiEndpointMutation<
88
+ Definition extends MutationDefinition<any, any, any, any, any>,
89
+ > = Matchers<MutationThunk, Definition>
90
+
91
+ type EndpointThunk<
92
+ Thunk extends QueryThunk | MutationThunk | InfiniteQueryThunk<any>,
93
+ Definition extends EndpointDefinition<any, any, any, any>,
94
+ > =
95
+ Definition extends EndpointDefinition<
96
+ infer QueryArg,
97
+ infer BaseQueryFn,
98
+ any,
99
+ infer ResultType
100
+ >
101
+ ? Thunk extends AsyncThunk<unknown, infer ATArg, infer ATConfig>
102
+ ? AsyncThunk<
103
+ ResultType,
104
+ ATArg & { originalArgs: QueryArg },
105
+ ATConfig & { rejectValue: BaseQueryError<BaseQueryFn> }
106
+ >
107
+ : never
108
+ : Definition extends InfiniteQueryDefinition<
109
+ infer QueryArg,
110
+ infer PageParam,
111
+ infer BaseQueryFn,
112
+ any,
113
+ infer ResultType
114
+ >
115
+ ? Thunk extends AsyncThunk<unknown, infer ATArg, infer ATConfig>
116
+ ? AsyncThunk<
117
+ InfiniteData<ResultType, PageParam>,
118
+ ATArg & { originalArgs: QueryArg },
119
+ ATConfig & { rejectValue: BaseQueryError<BaseQueryFn> }
120
+ >
121
+ : never
122
+ : never
123
+
124
+ export type PendingAction<
125
+ Thunk extends QueryThunk | MutationThunk | InfiniteQueryThunk<any>,
126
+ Definition extends EndpointDefinition<any, any, any, any>,
127
+ > = ReturnType<EndpointThunk<Thunk, Definition>['pending']>
128
+
129
+ export type FulfilledAction<
130
+ Thunk extends QueryThunk | MutationThunk | InfiniteQueryThunk<any>,
131
+ Definition extends EndpointDefinition<any, any, any, any>,
132
+ > = ReturnType<EndpointThunk<Thunk, Definition>['fulfilled']>
133
+
134
+ export type RejectedAction<
135
+ Thunk extends QueryThunk | MutationThunk | InfiniteQueryThunk<any>,
136
+ Definition extends EndpointDefinition<any, any, any, any>,
137
+ > = ReturnType<EndpointThunk<Thunk, Definition>['rejected']>
138
+
139
+ export type Matcher<M> = (value: any) => value is M
140
+
141
+ export interface Matchers<
142
+ Thunk extends QueryThunk | MutationThunk | InfiniteQueryThunk<any>,
143
+ Definition extends EndpointDefinition<any, any, any, any>,
144
+ > {
145
+ matchPending: Matcher<PendingAction<Thunk, Definition>>
146
+ matchFulfilled: Matcher<FulfilledAction<Thunk, Definition>>
147
+ matchRejected: Matcher<RejectedAction<Thunk, Definition>>
148
+ }
149
+
150
+ export type QueryThunkArg = QuerySubstateIdentifier &
151
+ StartQueryActionCreatorOptions & {
152
+ type: 'query'
153
+ originalArgs: unknown
154
+ endpointName: string
155
+ }
156
+
157
+ export type InfiniteQueryThunkArg<
158
+ D extends InfiniteQueryDefinition<any, any, any, any, any>,
159
+ > = QuerySubstateIdentifier &
160
+ StartInfiniteQueryActionCreatorOptions<D> & {
161
+ type: `query`
162
+ originalArgs: unknown
163
+ endpointName: string
164
+ param: unknown
165
+ direction?: InfiniteQueryDirection
166
+ refetchCachedPages?: boolean
167
+ }
168
+
169
+ type MutationThunkArg = {
170
+ type: 'mutation'
171
+ originalArgs: unknown
172
+ endpointName: string
173
+ track?: boolean
174
+ fixedCacheKey?: string
175
+ }
176
+
177
+ export type ThunkResult = unknown
178
+
179
+ export type ThunkApiMetaConfig = {
180
+ pendingMeta: { startedTimeStamp: number; [SHOULD_AUTOBATCH]: true }
181
+ fulfilledMeta: {
182
+ fulfilledTimeStamp: number
183
+ baseQueryMeta: unknown
184
+ [SHOULD_AUTOBATCH]: true
185
+ }
186
+ rejectedMeta: { baseQueryMeta: unknown; [SHOULD_AUTOBATCH]: true }
187
+ }
188
+ export type QueryThunk = AsyncThunk<
189
+ ThunkResult,
190
+ QueryThunkArg,
191
+ ThunkApiMetaConfig
192
+ >
193
+ export type InfiniteQueryThunk<
194
+ D extends InfiniteQueryDefinition<any, any, any, any, any>,
195
+ > = AsyncThunk<ThunkResult, InfiniteQueryThunkArg<D>, ThunkApiMetaConfig>
196
+ export type MutationThunk = AsyncThunk<
197
+ ThunkResult,
198
+ MutationThunkArg,
199
+ ThunkApiMetaConfig
200
+ >
201
+
202
+ function defaultTransformResponse(baseQueryReturnValue: unknown) {
203
+ return baseQueryReturnValue
204
+ }
205
+
206
+ export type MaybeDrafted<T> = T | Draft<T>
207
+ export type Recipe<T> = (data: MaybeDrafted<T>) => void | MaybeDrafted<T>
208
+ export type UpsertRecipe<T> = (
209
+ data: MaybeDrafted<T> | undefined,
210
+ ) => void | MaybeDrafted<T>
211
+
212
+ export type PatchQueryDataThunk<
213
+ Definitions extends EndpointDefinitions,
214
+ PartialState,
215
+ > = <EndpointName extends QueryKeys<Definitions>>(
216
+ endpointName: EndpointName,
217
+ arg: QueryArgFrom<Definitions[EndpointName]>,
218
+ patches: readonly Patch[],
219
+ updateProvided?: boolean,
220
+ ) => ThunkAction<void, PartialState, any, UnknownAction>
221
+
222
+ export type AllQueryKeys<Definitions extends EndpointDefinitions> =
223
+ | QueryKeys<Definitions>
224
+ | InfiniteQueryKeys<Definitions>
225
+
226
+ export type QueryArgFromAnyQueryDefinition<
227
+ Definitions extends EndpointDefinitions,
228
+ EndpointName extends AllQueryKeys<Definitions>,
229
+ > =
230
+ Definitions[EndpointName] extends InfiniteQueryDefinition<
231
+ any,
232
+ any,
233
+ any,
234
+ any,
235
+ any
236
+ >
237
+ ? InfiniteQueryArgFrom<Definitions[EndpointName]>
238
+ : Definitions[EndpointName] extends QueryDefinition<any, any, any, any>
239
+ ? QueryArgFrom<Definitions[EndpointName]>
240
+ : never
241
+
242
+ export type DataFromAnyQueryDefinition<
243
+ Definitions extends EndpointDefinitions,
244
+ EndpointName extends AllQueryKeys<Definitions>,
245
+ > =
246
+ Definitions[EndpointName] extends InfiniteQueryDefinition<
247
+ any,
248
+ any,
249
+ any,
250
+ any,
251
+ any
252
+ >
253
+ ? InfiniteData<
254
+ ResultTypeFrom<Definitions[EndpointName]>,
255
+ PageParamFrom<Definitions[EndpointName]>
256
+ >
257
+ : Definitions[EndpointName] extends QueryDefinition<any, any, any, any>
258
+ ? ResultTypeFrom<Definitions[EndpointName]>
259
+ : unknown
260
+
261
+ export type UpsertThunkResult<
262
+ Definitions extends EndpointDefinitions,
263
+ EndpointName extends AllQueryKeys<Definitions>,
264
+ > =
265
+ Definitions[EndpointName] extends InfiniteQueryDefinition<
266
+ any,
267
+ any,
268
+ any,
269
+ any,
270
+ any
271
+ >
272
+ ? InfiniteQueryActionCreatorResult<Definitions[EndpointName]>
273
+ : Definitions[EndpointName] extends QueryDefinition<any, any, any, any>
274
+ ? QueryActionCreatorResult<Definitions[EndpointName]>
275
+ : QueryActionCreatorResult<never>
276
+
277
+ export type UpdateQueryDataThunk<
278
+ Definitions extends EndpointDefinitions,
279
+ PartialState,
280
+ > = <EndpointName extends AllQueryKeys<Definitions>>(
281
+ endpointName: EndpointName,
282
+ arg: QueryArgFromAnyQueryDefinition<Definitions, EndpointName>,
283
+ updateRecipe: Recipe<DataFromAnyQueryDefinition<Definitions, EndpointName>>,
284
+ updateProvided?: boolean,
285
+ ) => ThunkAction<PatchCollection, PartialState, any, UnknownAction>
286
+
287
+ export type UpsertQueryDataThunk<
288
+ Definitions extends EndpointDefinitions,
289
+ PartialState,
290
+ > = <EndpointName extends AllQueryKeys<Definitions>>(
291
+ endpointName: EndpointName,
292
+ arg: QueryArgFromAnyQueryDefinition<Definitions, EndpointName>,
293
+ value: DataFromAnyQueryDefinition<Definitions, EndpointName>,
294
+ ) => ThunkAction<
295
+ UpsertThunkResult<Definitions, EndpointName>,
296
+ PartialState,
297
+ any,
298
+ UnknownAction
299
+ >
300
+
301
+ /**
302
+ * An object returned from dispatching a `api.util.updateQueryData` call.
303
+ */
304
+ export type PatchCollection = {
305
+ /**
306
+ * An `immer` Patch describing the cache update.
307
+ */
308
+ patches: Patch[]
309
+ /**
310
+ * An `immer` Patch to revert the cache update.
311
+ */
312
+ inversePatches: Patch[]
313
+ /**
314
+ * A function that will undo the cache update.
315
+ */
316
+ undo: () => void
317
+ }
318
+
319
+ type TransformCallback = (
320
+ baseQueryReturnValue: unknown,
321
+ meta: unknown,
322
+ arg: unknown,
323
+ ) => any
324
+
325
+ export const addShouldAutoBatch = <T extends Record<string, any>>(
326
+ arg: T = {} as T,
327
+ ): T & { [SHOULD_AUTOBATCH]: true } => {
328
+ return { ...arg, [SHOULD_AUTOBATCH]: true }
329
+ }
330
+
331
+ export function buildThunks<
332
+ BaseQuery extends BaseQueryFn,
333
+ ReducerPath extends string,
334
+ Definitions extends EndpointDefinitions,
335
+ >({
336
+ reducerPath,
337
+ baseQuery,
338
+ context: { endpointDefinitions },
339
+ serializeQueryArgs,
340
+ api,
341
+ assertTagType,
342
+ selectors,
343
+ onSchemaFailure,
344
+ catchSchemaFailure: globalCatchSchemaFailure,
345
+ skipSchemaValidation: globalSkipSchemaValidation,
346
+ }: {
347
+ baseQuery: BaseQuery
348
+ reducerPath: ReducerPath
349
+ context: ApiContext<Definitions>
350
+ serializeQueryArgs: InternalSerializeQueryArgs
351
+ api: Api<BaseQuery, Definitions, ReducerPath, any>
352
+ assertTagType: AssertTagTypes
353
+ selectors: AllSelectors
354
+ onSchemaFailure: SchemaFailureHandler | undefined
355
+ catchSchemaFailure: SchemaFailureConverter<BaseQuery> | undefined
356
+ skipSchemaValidation: boolean | SchemaType[] | undefined
357
+ }) {
358
+ type State = RootState<any, string, ReducerPath>
359
+
360
+ const patchQueryData: PatchQueryDataThunk<EndpointDefinitions, State> =
361
+ (endpointName, arg, patches, updateProvided) => (dispatch, getState) => {
362
+ const endpointDefinition = endpointDefinitions[endpointName]
363
+
364
+ const queryCacheKey = serializeQueryArgs({
365
+ queryArgs: arg,
366
+ endpointDefinition,
367
+ endpointName,
368
+ })
369
+
370
+ dispatch(
371
+ api.internalActions.queryResultPatched({ queryCacheKey, patches }),
372
+ )
373
+
374
+ if (!updateProvided) {
375
+ return
376
+ }
377
+
378
+ const newValue = api.endpoints[endpointName].select(arg)(
379
+ // Work around TS 4.1 mismatch
380
+ getState() as RootState<any, any, any>,
381
+ )
382
+
383
+ const providedTags = calculateProvidedBy(
384
+ endpointDefinition.providesTags,
385
+ newValue.data,
386
+ undefined,
387
+ arg,
388
+ {},
389
+ assertTagType,
390
+ )
391
+
392
+ dispatch(
393
+ api.internalActions.updateProvidedBy([{ queryCacheKey, providedTags }]),
394
+ )
395
+ }
396
+
397
+ function addToStart<T>(items: Array<T>, item: T, max = 0): Array<T> {
398
+ const newItems = [item, ...items]
399
+ return max && newItems.length > max ? newItems.slice(0, -1) : newItems
400
+ }
401
+
402
+ function addToEnd<T>(items: Array<T>, item: T, max = 0): Array<T> {
403
+ const newItems = [...items, item]
404
+ return max && newItems.length > max ? newItems.slice(1) : newItems
405
+ }
406
+
407
+ const updateQueryData: UpdateQueryDataThunk<EndpointDefinitions, State> =
408
+ (endpointName, arg, updateRecipe, updateProvided = true) =>
409
+ (dispatch, getState) => {
410
+ const endpointDefinition = api.endpoints[endpointName]
411
+
412
+ const currentState = endpointDefinition.select(arg)(
413
+ // Work around TS 4.1 mismatch
414
+ getState() as RootState<any, any, any>,
415
+ )
416
+
417
+ const ret: PatchCollection = {
418
+ patches: [],
419
+ inversePatches: [],
420
+ undo: () =>
421
+ dispatch(
422
+ api.util.patchQueryData(
423
+ endpointName,
424
+ arg,
425
+ ret.inversePatches,
426
+ updateProvided,
427
+ ),
428
+ ),
429
+ }
430
+ if (currentState.status === STATUS_UNINITIALIZED) {
431
+ return ret
432
+ }
433
+ let newValue
434
+ if ('data' in currentState) {
435
+ if (isDraftable(currentState.data)) {
436
+ const [value, patches, inversePatches] = produceWithPatches(
437
+ currentState.data,
438
+ updateRecipe,
439
+ )
440
+ ret.patches.push(...patches)
441
+ ret.inversePatches.push(...inversePatches)
442
+ newValue = value
443
+ } else {
444
+ newValue = updateRecipe(currentState.data)
445
+ ret.patches.push({ op: 'replace', path: [], value: newValue })
446
+ ret.inversePatches.push({
447
+ op: 'replace',
448
+ path: [],
449
+ value: currentState.data,
450
+ })
451
+ }
452
+ }
453
+
454
+ if (ret.patches.length === 0) {
455
+ return ret
456
+ }
457
+
458
+ dispatch(
459
+ api.util.patchQueryData(endpointName, arg, ret.patches, updateProvided),
460
+ )
461
+
462
+ return ret
463
+ }
464
+
465
+ const upsertQueryData: UpsertQueryDataThunk<Definitions, State> =
466
+ (endpointName, arg, value) => (dispatch) => {
467
+ type EndpointName = typeof endpointName
468
+ const res = dispatch(
469
+ (
470
+ api.endpoints[endpointName] as ApiEndpointQuery<
471
+ QueryDefinition<any, any, any, any, any>,
472
+ Definitions
473
+ >
474
+ ).initiate(arg, {
475
+ subscribe: false,
476
+ forceRefetch: true,
477
+ [forceQueryFnSymbol]: () => ({ data: value }),
478
+ }),
479
+ ) as UpsertThunkResult<Definitions, EndpointName>
480
+
481
+ return res
482
+ }
483
+
484
+ const getTransformCallbackForEndpoint = (
485
+ endpointDefinition: EndpointDefinition<any, any, any, any>,
486
+ transformFieldName: 'transformResponse' | 'transformErrorResponse',
487
+ ): TransformCallback => {
488
+ return endpointDefinition.query && endpointDefinition[transformFieldName]
489
+ ? (endpointDefinition[transformFieldName]! as TransformCallback)
490
+ : defaultTransformResponse
491
+ }
492
+
493
+ // The generic async payload function for all of our thunks
494
+ const executeEndpoint: AsyncThunkPayloadCreator<
495
+ ThunkResult,
496
+ QueryThunkArg | MutationThunkArg | InfiniteQueryThunkArg<any>,
497
+ ThunkApiMetaConfig & { state: RootState<any, string, ReducerPath> }
498
+ > = async (
499
+ arg,
500
+ {
501
+ signal,
502
+ abort,
503
+ rejectWithValue,
504
+ fulfillWithValue,
505
+ dispatch,
506
+ getState,
507
+ extra,
508
+ },
509
+ ) => {
510
+ const endpointDefinition = endpointDefinitions[arg.endpointName]
511
+ const { metaSchema, skipSchemaValidation = globalSkipSchemaValidation } =
512
+ endpointDefinition
513
+
514
+ const isQuery = arg.type === ENDPOINT_QUERY
515
+
516
+ try {
517
+ let transformResponse: TransformCallback = defaultTransformResponse
518
+
519
+ const baseQueryApi = {
520
+ signal,
521
+ abort,
522
+ dispatch,
523
+ getState,
524
+ extra,
525
+ endpoint: arg.endpointName,
526
+ type: arg.type,
527
+ forced: isQuery ? isForcedQuery(arg, getState()) : undefined,
528
+ queryCacheKey: isQuery ? arg.queryCacheKey : undefined,
529
+ }
530
+
531
+ const forceQueryFn = isQuery ? arg[forceQueryFnSymbol] : undefined
532
+
533
+ let finalQueryReturnValue: QueryReturnValue
534
+
535
+ // Infinite query wrapper, which executes the request and returns
536
+ // the InfiniteData `{pages, pageParams}` structure
537
+ const fetchPage = async (
538
+ data: InfiniteData<unknown, unknown>,
539
+ param: unknown,
540
+ maxPages: number,
541
+ previous?: boolean,
542
+ ): Promise<QueryReturnValue> => {
543
+ // This should handle cases where there is no `getPrevPageParam`,
544
+ // or `getPPP` returned nullish
545
+ if (param == null && data.pages.length) {
546
+ return Promise.resolve({ data })
547
+ }
548
+
549
+ const finalQueryArg: InfiniteQueryCombinedArg<any, any> = {
550
+ queryArg: arg.originalArgs,
551
+ pageParam: param,
552
+ }
553
+
554
+ const pageResponse = await executeRequest(finalQueryArg)
555
+
556
+ const addTo = previous ? addToStart : addToEnd
557
+
558
+ return {
559
+ data: {
560
+ pages: addTo(data.pages, pageResponse.data, maxPages),
561
+ pageParams: addTo(data.pageParams, param, maxPages),
562
+ },
563
+ meta: pageResponse.meta,
564
+ }
565
+ }
566
+
567
+ // Wrapper for executing either `query` or `queryFn`,
568
+ // and handling any errors
569
+ async function executeRequest(
570
+ finalQueryArg: unknown,
571
+ ): Promise<QueryReturnValue> {
572
+ let result: QueryReturnValue
573
+ const { extraOptions, argSchema, rawResponseSchema, responseSchema } =
574
+ endpointDefinition
575
+
576
+ if (argSchema && !shouldSkip(skipSchemaValidation, 'arg')) {
577
+ finalQueryArg = await parseWithSchema(
578
+ argSchema,
579
+ finalQueryArg,
580
+ 'argSchema',
581
+ {}, // we don't have a meta yet, so we can't pass it
582
+ )
583
+ }
584
+
585
+ if (forceQueryFn) {
586
+ // upsertQueryData relies on this to pass in the user-provided value
587
+ result = forceQueryFn()
588
+ } else if (endpointDefinition.query) {
589
+ // We should only run `transformResponse` when the endpoint has a `query` method,
590
+ // and we're not doing an `upsertQueryData`.
591
+ transformResponse = getTransformCallbackForEndpoint(
592
+ endpointDefinition,
593
+ 'transformResponse',
594
+ )
595
+
596
+ result = await baseQuery(
597
+ endpointDefinition.query(finalQueryArg as any),
598
+ baseQueryApi,
599
+ extraOptions as any,
600
+ )
601
+ } else {
602
+ result = await endpointDefinition.queryFn(
603
+ finalQueryArg as any,
604
+ baseQueryApi,
605
+ extraOptions as any,
606
+ (arg) => baseQuery(arg, baseQueryApi, extraOptions as any),
607
+ )
608
+ }
609
+
610
+ if (
611
+ typeof process !== 'undefined' &&
612
+ process.env.NODE_ENV === 'development'
613
+ ) {
614
+ const what = endpointDefinition.query ? '`baseQuery`' : '`queryFn`'
615
+ let err: undefined | string
616
+ if (!result) {
617
+ err = `${what} did not return anything.`
618
+ } else if (typeof result !== 'object') {
619
+ err = `${what} did not return an object.`
620
+ } else if (result.error && result.data) {
621
+ err = `${what} returned an object containing both \`error\` and \`result\`.`
622
+ } else if (result.error === undefined && result.data === undefined) {
623
+ err = `${what} returned an object containing neither a valid \`error\` and \`result\`. At least one of them should not be \`undefined\``
624
+ } else {
625
+ for (const key of Object.keys(result)) {
626
+ if (key !== 'error' && key !== 'data' && key !== 'meta') {
627
+ err = `The object returned by ${what} has the unknown property ${key}.`
628
+ break
629
+ }
630
+ }
631
+ }
632
+ if (err) {
633
+ console.error(
634
+ `Error encountered handling the endpoint ${arg.endpointName}.
635
+ ${err}
636
+ It needs to return an object with either the shape \`{ data: <value> }\` or \`{ error: <value> }\` that may contain an optional \`meta\` property.
637
+ Object returned was:`,
638
+ result,
639
+ )
640
+ }
641
+ }
642
+
643
+ if (result.error) throw new HandledError(result.error, result.meta)
644
+
645
+ let { data } = result
646
+
647
+ if (
648
+ rawResponseSchema &&
649
+ !shouldSkip(skipSchemaValidation, 'rawResponse')
650
+ ) {
651
+ data = await parseWithSchema(
652
+ rawResponseSchema,
653
+ result.data,
654
+ 'rawResponseSchema',
655
+ result.meta,
656
+ )
657
+ }
658
+
659
+ let transformedResponse = await transformResponse(
660
+ data,
661
+ result.meta,
662
+ finalQueryArg,
663
+ )
664
+
665
+ if (responseSchema && !shouldSkip(skipSchemaValidation, 'response')) {
666
+ transformedResponse = await parseWithSchema(
667
+ responseSchema,
668
+ transformedResponse,
669
+ 'responseSchema',
670
+ result.meta,
671
+ )
672
+ }
673
+
674
+ return {
675
+ ...result,
676
+ data: transformedResponse,
677
+ }
678
+ }
679
+
680
+ if (isQuery && 'infiniteQueryOptions' in endpointDefinition) {
681
+ // This is an infinite query endpoint
682
+ const { infiniteQueryOptions } = endpointDefinition
683
+
684
+ // Runtime checks should guarantee this is a positive number if provided
685
+ const { maxPages = Infinity } = infiniteQueryOptions
686
+
687
+ // Priority: per-call override > endpoint config > default (true)
688
+ const refetchCachedPages =
689
+ (arg as InfiniteQueryThunkArg<any>).refetchCachedPages ??
690
+ infiniteQueryOptions.refetchCachedPages ??
691
+ true
692
+
693
+ let result: QueryReturnValue
694
+
695
+ // Start by looking up the existing InfiniteData value from state,
696
+ // falling back to an empty value if it doesn't exist yet
697
+ const blankData = { pages: [], pageParams: [] }
698
+ const cachedData = selectors.selectQueryEntry(
699
+ getState(),
700
+ arg.queryCacheKey,
701
+ )?.data as InfiniteData<unknown, unknown> | undefined
702
+
703
+ // When the arg changes or the user forces a refetch,
704
+ // we don't include the `direction` flag. This lets us distinguish
705
+ // between actually refetching with a forced query, vs just fetching
706
+ // the next page.
707
+ const isForcedQueryNeedingRefetch = // arg.forceRefetch
708
+ isForcedQuery(arg, getState()) &&
709
+ !(arg as InfiniteQueryThunkArg<any>).direction
710
+ const existingData = (
711
+ isForcedQueryNeedingRefetch || !cachedData ? blankData : cachedData
712
+ ) as InfiniteData<unknown, unknown>
713
+
714
+ // If the thunk specified a direction and we do have at least one page,
715
+ // fetch the next or previous page
716
+ if ('direction' in arg && arg.direction && existingData.pages.length) {
717
+ const previous = arg.direction === 'backward'
718
+ const pageParamFn = previous ? getPreviousPageParam : getNextPageParam
719
+ const param = pageParamFn(
720
+ infiniteQueryOptions,
721
+ existingData,
722
+ arg.originalArgs,
723
+ )
724
+
725
+ result = await fetchPage(existingData, param, maxPages, previous)
726
+ } else {
727
+ // Otherwise, fetch the first page and then any remaining pages
728
+
729
+ const { initialPageParam = infiniteQueryOptions.initialPageParam } =
730
+ arg as InfiniteQueryThunkArg<any>
731
+
732
+ // If we're doing a refetch, we should start from
733
+ // the first page we have cached.
734
+ // Otherwise, we should start from the initialPageParam
735
+ const cachedPageParams = cachedData?.pageParams ?? []
736
+ const firstPageParam = cachedPageParams[0] ?? initialPageParam
737
+ const totalPages = cachedPageParams.length
738
+
739
+ // Fetch first page
740
+ result = await fetchPage(existingData, firstPageParam, maxPages)
741
+
742
+ if (forceQueryFn) {
743
+ // HACK `upsertQueryData` expects the user to pass in the `{pages, pageParams}` structure,
744
+ // but `fetchPage` treats that as `pages[0]`. We have to manually un-nest it.
745
+ result = {
746
+ data: (result.data as InfiniteData<unknown, unknown>).pages[0],
747
+ } as QueryReturnValue
748
+ }
749
+
750
+ if (refetchCachedPages) {
751
+ // Fetch remaining pages
752
+ for (let i = 1; i < totalPages; i++) {
753
+ const param = getNextPageParam(
754
+ infiniteQueryOptions,
755
+ result.data as InfiniteData<unknown, unknown>,
756
+ arg.originalArgs,
757
+ )
758
+ result = await fetchPage(
759
+ result.data as InfiniteData<unknown, unknown>,
760
+ param,
761
+ maxPages,
762
+ )
763
+ }
764
+ }
765
+ }
766
+
767
+ finalQueryReturnValue = result
768
+ } else {
769
+ // Non-infinite endpoint. Just run the one request.
770
+ finalQueryReturnValue = await executeRequest(arg.originalArgs)
771
+ }
772
+
773
+ if (
774
+ metaSchema &&
775
+ !shouldSkip(skipSchemaValidation, 'meta') &&
776
+ finalQueryReturnValue.meta
777
+ ) {
778
+ finalQueryReturnValue.meta = await parseWithSchema(
779
+ metaSchema,
780
+ finalQueryReturnValue.meta,
781
+ 'metaSchema',
782
+ finalQueryReturnValue.meta,
783
+ )
784
+ }
785
+
786
+ // console.log('Final result: ', transformedData)
787
+ return fulfillWithValue(
788
+ finalQueryReturnValue.data,
789
+ addShouldAutoBatch({
790
+ fulfilledTimeStamp: Date.now(),
791
+ baseQueryMeta: finalQueryReturnValue.meta,
792
+ }),
793
+ )
794
+ } catch (error) {
795
+ let caughtError = error
796
+ if (caughtError instanceof HandledError) {
797
+ let transformErrorResponse = getTransformCallbackForEndpoint(
798
+ endpointDefinition,
799
+ 'transformErrorResponse',
800
+ )
801
+ const { rawErrorResponseSchema, errorResponseSchema } =
802
+ endpointDefinition
803
+
804
+ let { value, meta } = caughtError
805
+
806
+ try {
807
+ if (
808
+ rawErrorResponseSchema &&
809
+ !shouldSkip(skipSchemaValidation, 'rawErrorResponse')
810
+ ) {
811
+ value = await parseWithSchema(
812
+ rawErrorResponseSchema,
813
+ value,
814
+ 'rawErrorResponseSchema',
815
+ meta,
816
+ )
817
+ }
818
+
819
+ if (metaSchema && !shouldSkip(skipSchemaValidation, 'meta')) {
820
+ meta = await parseWithSchema(metaSchema, meta, 'metaSchema', meta)
821
+ }
822
+ let transformedErrorResponse = await transformErrorResponse(
823
+ value,
824
+ meta,
825
+ arg.originalArgs,
826
+ )
827
+ if (
828
+ errorResponseSchema &&
829
+ !shouldSkip(skipSchemaValidation, 'errorResponse')
830
+ ) {
831
+ transformedErrorResponse = await parseWithSchema(
832
+ errorResponseSchema,
833
+ transformedErrorResponse,
834
+ 'errorResponseSchema',
835
+ meta,
836
+ )
837
+ }
838
+
839
+ return rejectWithValue(
840
+ transformedErrorResponse,
841
+ addShouldAutoBatch({ baseQueryMeta: meta }),
842
+ )
843
+ } catch (e) {
844
+ caughtError = e
845
+ }
846
+ }
847
+ try {
848
+ if (caughtError instanceof NamedSchemaError) {
849
+ const info: SchemaFailureInfo = {
850
+ endpoint: arg.endpointName,
851
+ arg: arg.originalArgs,
852
+ type: arg.type,
853
+ queryCacheKey: isQuery ? arg.queryCacheKey : undefined,
854
+ }
855
+ endpointDefinition.onSchemaFailure?.(caughtError, info)
856
+ onSchemaFailure?.(caughtError, info)
857
+ const { catchSchemaFailure = globalCatchSchemaFailure } =
858
+ endpointDefinition
859
+ if (catchSchemaFailure) {
860
+ return rejectWithValue(
861
+ catchSchemaFailure(caughtError, info),
862
+ addShouldAutoBatch({ baseQueryMeta: caughtError._bqMeta }),
863
+ )
864
+ }
865
+ }
866
+ } catch (e) {
867
+ caughtError = e
868
+ }
869
+ if (
870
+ typeof process !== 'undefined' &&
871
+ process.env.NODE_ENV !== 'production'
872
+ ) {
873
+ console.error(
874
+ `An unhandled error occurred processing a request for the endpoint "${arg.endpointName}".
875
+ In the case of an unhandled error, no tags will be "provided" or "invalidated".`,
876
+ caughtError,
877
+ )
878
+ } else {
879
+ console.error(caughtError)
880
+ }
881
+ throw caughtError
882
+ }
883
+ }
884
+
885
+ function isForcedQuery(
886
+ arg: QueryThunkArg,
887
+ state: RootState<any, string, ReducerPath>,
888
+ ) {
889
+ const requestState = selectors.selectQueryEntry(state, arg.queryCacheKey)
890
+ const baseFetchOnMountOrArgChange =
891
+ selectors.selectConfig(state).refetchOnMountOrArgChange
892
+
893
+ const fulfilledVal = requestState?.fulfilledTimeStamp
894
+ const refetchVal =
895
+ arg.forceRefetch ?? (arg.subscribe && baseFetchOnMountOrArgChange)
896
+
897
+ if (refetchVal) {
898
+ // Return if it's true or compare the dates because it must be a number
899
+ return (
900
+ refetchVal === true ||
901
+ (Number(new Date()) - Number(fulfilledVal)) / 1000 >= refetchVal
902
+ )
903
+ }
904
+ return false
905
+ }
906
+
907
+ const createQueryThunk = <
908
+ ThunkArgType extends QueryThunkArg | InfiniteQueryThunkArg<any>,
909
+ >() => {
910
+ const generatedQueryThunk = createAsyncThunk<
911
+ ThunkResult,
912
+ ThunkArgType,
913
+ ThunkApiMetaConfig & { state: RootState<any, string, ReducerPath> }
914
+ >(`${reducerPath}/executeQuery`, executeEndpoint, {
915
+ getPendingMeta({ arg }) {
916
+ const endpointDefinition = endpointDefinitions[arg.endpointName]
917
+ return addShouldAutoBatch({
918
+ startedTimeStamp: Date.now(),
919
+ ...(isInfiniteQueryDefinition(endpointDefinition)
920
+ ? { direction: (arg as InfiniteQueryThunkArg<any>).direction }
921
+ : {}),
922
+ })
923
+ },
924
+ condition(queryThunkArg, { getState }) {
925
+ const state = getState()
926
+
927
+ const requestState = selectors.selectQueryEntry(
928
+ state,
929
+ queryThunkArg.queryCacheKey,
930
+ )
931
+ const fulfilledVal = requestState?.fulfilledTimeStamp
932
+ const currentArg = queryThunkArg.originalArgs
933
+ const previousArg = requestState?.originalArgs
934
+ const endpointDefinition =
935
+ endpointDefinitions[queryThunkArg.endpointName]
936
+ const direction = (queryThunkArg as InfiniteQueryThunkArg<any>)
937
+ .direction
938
+
939
+ // Order of these checks matters.
940
+ // In order for `upsertQueryData` to successfully run while an existing request is in flight,
941
+ /// we have to check for that first, otherwise `queryThunk` will bail out and not run at all.
942
+ if (isUpsertQuery(queryThunkArg)) {
943
+ return true
944
+ }
945
+
946
+ // Don't retry a request that's currently in-flight
947
+ if (requestState?.status === 'pending') {
948
+ return false
949
+ }
950
+
951
+ // if this is forced, continue
952
+ if (isForcedQuery(queryThunkArg, state)) {
953
+ return true
954
+ }
955
+
956
+ if (
957
+ isQueryDefinition(endpointDefinition) &&
958
+ endpointDefinition?.forceRefetch?.({
959
+ currentArg,
960
+ previousArg,
961
+ endpointState: requestState,
962
+ state,
963
+ })
964
+ ) {
965
+ return true
966
+ }
967
+
968
+ // Pull from the cache unless we explicitly force refetch or qualify based on time
969
+ if (fulfilledVal && !direction) {
970
+ // Value is cached and we didn't specify to refresh, skip it.
971
+ return false
972
+ }
973
+
974
+ return true
975
+ },
976
+ dispatchConditionRejection: true,
977
+ })
978
+ return generatedQueryThunk
979
+ }
980
+
981
+ const queryThunk = createQueryThunk<QueryThunkArg>()
982
+ const infiniteQueryThunk = createQueryThunk<InfiniteQueryThunkArg<any>>()
983
+
984
+ const mutationThunk = createAsyncThunk<
985
+ ThunkResult,
986
+ MutationThunkArg,
987
+ ThunkApiMetaConfig & { state: RootState<any, string, ReducerPath> }
988
+ >(`${reducerPath}/executeMutation`, executeEndpoint, {
989
+ getPendingMeta() {
990
+ return addShouldAutoBatch({ startedTimeStamp: Date.now() })
991
+ },
992
+ })
993
+
994
+ const hasTheForce = (options: any): options is { force: boolean } =>
995
+ 'force' in options
996
+ const hasMaxAge = (
997
+ options: any,
998
+ ): options is { ifOlderThan: false | number } => 'ifOlderThan' in options
999
+
1000
+ const prefetch =
1001
+ <EndpointName extends QueryKeys<Definitions>>(
1002
+ endpointName: EndpointName,
1003
+ arg: any,
1004
+ options: PrefetchOptions = {},
1005
+ ): ThunkAction<void, any, any, UnknownAction> =>
1006
+ (dispatch: ThunkDispatch<any, any, any>, getState: () => any) => {
1007
+ const force = hasTheForce(options) && options.force
1008
+ const maxAge = hasMaxAge(options) && options.ifOlderThan
1009
+
1010
+ const queryAction = (force: boolean = true) => {
1011
+ const options: StartQueryActionCreatorOptions = {
1012
+ forceRefetch: force,
1013
+ subscribe: false,
1014
+ }
1015
+ return (
1016
+ api.endpoints[endpointName] as ApiEndpointQuery<any, any>
1017
+ ).initiate(arg, options)
1018
+ }
1019
+ const latestStateValue = (
1020
+ api.endpoints[endpointName] as ApiEndpointQuery<any, any>
1021
+ ).select(arg)(getState())
1022
+
1023
+ if (force) {
1024
+ dispatch(queryAction())
1025
+ } else if (maxAge) {
1026
+ const lastFulfilledTs = latestStateValue?.fulfilledTimeStamp
1027
+ if (!lastFulfilledTs) {
1028
+ dispatch(queryAction())
1029
+ return
1030
+ }
1031
+ const shouldRetrigger =
1032
+ (Number(new Date()) - Number(new Date(lastFulfilledTs))) / 1000 >=
1033
+ maxAge
1034
+ if (shouldRetrigger) {
1035
+ dispatch(queryAction())
1036
+ }
1037
+ } else {
1038
+ // If prefetching with no options, just let it try
1039
+ dispatch(queryAction(false))
1040
+ }
1041
+ }
1042
+
1043
+ function matchesEndpoint(endpointName: string) {
1044
+ return (action: any): action is UnknownAction =>
1045
+ action?.meta?.arg?.endpointName === endpointName
1046
+ }
1047
+
1048
+ function buildMatchThunkActions<
1049
+ Thunk extends
1050
+ | AsyncThunk<any, QueryThunkArg, ThunkApiMetaConfig>
1051
+ | AsyncThunk<any, MutationThunkArg, ThunkApiMetaConfig>,
1052
+ >(thunk: Thunk, endpointName: string) {
1053
+ return {
1054
+ matchPending: isAllOf(isPending(thunk), matchesEndpoint(endpointName)),
1055
+ matchFulfilled: isAllOf(
1056
+ isFulfilled(thunk),
1057
+ matchesEndpoint(endpointName),
1058
+ ),
1059
+ matchRejected: isAllOf(isRejected(thunk), matchesEndpoint(endpointName)),
1060
+ } as Matchers<Thunk, any>
1061
+ }
1062
+
1063
+ return {
1064
+ queryThunk,
1065
+ mutationThunk,
1066
+ infiniteQueryThunk,
1067
+ prefetch,
1068
+ updateQueryData,
1069
+ upsertQueryData,
1070
+ patchQueryData,
1071
+ buildMatchThunkActions,
1072
+ }
1073
+ }
1074
+
1075
+ export function getNextPageParam(
1076
+ options: InfiniteQueryConfigOptions<unknown, unknown, unknown>,
1077
+ { pages, pageParams }: InfiniteData<unknown, unknown>,
1078
+ queryArg: unknown,
1079
+ ): unknown | undefined {
1080
+ const lastIndex = pages.length - 1
1081
+ return options.getNextPageParam(
1082
+ pages[lastIndex],
1083
+ pages,
1084
+ pageParams[lastIndex],
1085
+ pageParams,
1086
+ queryArg,
1087
+ )
1088
+ }
1089
+
1090
+ export function getPreviousPageParam(
1091
+ options: InfiniteQueryConfigOptions<unknown, unknown, unknown>,
1092
+ { pages, pageParams }: InfiniteData<unknown, unknown>,
1093
+ queryArg: unknown,
1094
+ ): unknown | undefined {
1095
+ return options.getPreviousPageParam?.(
1096
+ pages[0],
1097
+ pages,
1098
+ pageParams[0],
1099
+ pageParams,
1100
+ queryArg,
1101
+ )
1102
+ }
1103
+
1104
+ export function calculateProvidedByThunk(
1105
+ action: UnwrapPromise<
1106
+ | ReturnType<ReturnType<QueryThunk>>
1107
+ | ReturnType<ReturnType<MutationThunk>>
1108
+ | ReturnType<ReturnType<InfiniteQueryThunk<any>>>
1109
+ >,
1110
+ type: 'providesTags' | 'invalidatesTags',
1111
+ endpointDefinitions: EndpointDefinitions,
1112
+ assertTagType: AssertTagTypes,
1113
+ ) {
1114
+ return calculateProvidedBy(
1115
+ endpointDefinitions[action.meta.arg.endpointName][
1116
+ type
1117
+ ] as ResultDescription<any, any, any, any, any>,
1118
+ isFulfilled(action) ? action.payload : undefined,
1119
+ isRejectedWithValue(action) ? action.payload : undefined,
1120
+ action.meta.arg.originalArgs,
1121
+ 'baseQueryMeta' in action.meta ? action.meta.baseQueryMeta : undefined,
1122
+ assertTagType,
1123
+ )
1124
+ }