@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,2 @@
1
+ export const UNINITIALIZED_VALUE = Symbol()
2
+ export type UninitializedValue = typeof UNINITIALIZED_VALUE
@@ -0,0 +1,45 @@
1
+ // This must remain here so that the `mangleErrors.cjs` build script
2
+ // does not have to import this into each source file it rewrites.
3
+ import { formatProdErrorMessage } from '@reduxjs/toolkit'
4
+
5
+ import { buildCreateApi, coreModule } from './rtkqImports'
6
+ import { reactHooksModule, reactHooksModuleName } from './module'
7
+
8
+ export * from '@reduxjs/toolkit/query'
9
+ export { ApiProvider } from './ApiProvider'
10
+
11
+ const createApi = /* @__PURE__ */ buildCreateApi(
12
+ coreModule(),
13
+ reactHooksModule(),
14
+ )
15
+
16
+ export type {
17
+ TypedUseMutationResult,
18
+ TypedUseQueryHookResult,
19
+ TypedUseQueryStateResult,
20
+ TypedUseQuerySubscriptionResult,
21
+ TypedLazyQueryTrigger,
22
+ TypedUseLazyQuery,
23
+ TypedUseMutation,
24
+ TypedMutationTrigger,
25
+ TypedQueryStateSelector,
26
+ TypedUseQueryState,
27
+ TypedUseQuery,
28
+ TypedUseQuerySubscription,
29
+ TypedUseLazyQuerySubscription,
30
+ TypedUseQueryStateOptions,
31
+ TypedUseLazyQueryStateResult,
32
+ TypedUseInfiniteQuery,
33
+ TypedUseInfiniteQueryHookResult,
34
+ TypedUseInfiniteQueryStateResult,
35
+ TypedUseInfiniteQuerySubscriptionResult,
36
+ TypedUseInfiniteQueryStateOptions,
37
+ TypedInfiniteQueryStateSelector,
38
+ TypedUseInfiniteQuerySubscription,
39
+ TypedUseInfiniteQueryState,
40
+ TypedLazyInfiniteQueryTrigger,
41
+ TypedUseQuerySubscriptionOptions,
42
+ TypedUseMutationStateOptions,
43
+ } from './buildHooks'
44
+ export { UNINITIALIZED_VALUE } from './constants'
45
+ export { createApi, reactHooksModule, reactHooksModuleName }
@@ -0,0 +1,275 @@
1
+ import type {
2
+ Api,
3
+ BaseQueryFn,
4
+ EndpointDefinitions,
5
+ InfiniteQueryDefinition,
6
+ Module,
7
+ MutationDefinition,
8
+ PrefetchOptions,
9
+ QueryArgFrom,
10
+ QueryDefinition,
11
+ QueryKeys,
12
+ } from '@reduxjs/toolkit/query'
13
+ import {
14
+ batch as rrBatch,
15
+ useDispatch as rrUseDispatch,
16
+ useSelector as rrUseSelector,
17
+ useStore as rrUseStore,
18
+ } from 'react-redux'
19
+ import type { CreateSelectorFunction } from 'reselect'
20
+ import { createSelector as _createSelector } from 'reselect'
21
+ import {
22
+ isInfiniteQueryDefinition,
23
+ isMutationDefinition,
24
+ isQueryDefinition,
25
+ } from '../endpointDefinitions'
26
+ import { safeAssign } from '../tsHelpers'
27
+ import { capitalize, countObjectKeys } from '../utils'
28
+ import type {
29
+ InfiniteQueryHooks,
30
+ MutationHooks,
31
+ QueryHooks,
32
+ } from './buildHooks'
33
+ import { buildHooks } from './buildHooks'
34
+ import type { HooksWithUniqueNames } from './namedHooks'
35
+
36
+ export const reactHooksModuleName = /* @__PURE__ */ Symbol()
37
+ export type ReactHooksModule = typeof reactHooksModuleName
38
+
39
+ declare module '@reduxjs/toolkit/query' {
40
+ export interface ApiModules<
41
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
42
+ BaseQuery extends BaseQueryFn,
43
+ Definitions extends EndpointDefinitions,
44
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
45
+ ReducerPath extends string,
46
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
47
+ TagTypes extends string,
48
+ > {
49
+ [reactHooksModuleName]: {
50
+ /**
51
+ * Endpoints based on the input endpoints provided to `createApi`, containing `select`, `hooks` and `action matchers`.
52
+ */
53
+ endpoints: {
54
+ [K in keyof Definitions]: Definitions[K] extends QueryDefinition<
55
+ any,
56
+ any,
57
+ any,
58
+ any,
59
+ any
60
+ >
61
+ ? QueryHooks<Definitions[K]>
62
+ : Definitions[K] extends MutationDefinition<any, any, any, any, any>
63
+ ? MutationHooks<Definitions[K]>
64
+ : Definitions[K] extends InfiniteQueryDefinition<
65
+ any,
66
+ any,
67
+ any,
68
+ any,
69
+ any
70
+ >
71
+ ? InfiniteQueryHooks<Definitions[K]>
72
+ : never
73
+ }
74
+ /**
75
+ * A hook that accepts a string endpoint name, and provides a callback that when called, pre-fetches the data for that endpoint.
76
+ */
77
+ usePrefetch<EndpointName extends QueryKeys<Definitions>>(
78
+ endpointName: EndpointName,
79
+ options?: PrefetchOptions,
80
+ ): (
81
+ arg: QueryArgFrom<Definitions[EndpointName]>,
82
+ options?: PrefetchOptions,
83
+ ) => void
84
+ } & HooksWithUniqueNames<Definitions>
85
+ }
86
+ }
87
+
88
+ type RR = typeof import('react-redux')
89
+
90
+ export interface ReactHooksModuleOptions {
91
+ /**
92
+ * The hooks from React Redux to be used
93
+ */
94
+ hooks?: {
95
+ /**
96
+ * The version of the `useDispatch` hook to be used
97
+ */
98
+ useDispatch: RR['useDispatch']
99
+ /**
100
+ * The version of the `useSelector` hook to be used
101
+ */
102
+ useSelector: RR['useSelector']
103
+ /**
104
+ * The version of the `useStore` hook to be used
105
+ */
106
+ useStore: RR['useStore']
107
+ }
108
+ /**
109
+ * The version of the `batchedUpdates` function to be used
110
+ */
111
+ batch?: RR['batch']
112
+ /**
113
+ * Enables performing asynchronous tasks immediately within a render.
114
+ *
115
+ * @example
116
+ *
117
+ * ```ts
118
+ * import {
119
+ * buildCreateApi,
120
+ * coreModule,
121
+ * reactHooksModule
122
+ * } from '@reduxjs/toolkit/query/react'
123
+ *
124
+ * const createApi = buildCreateApi(
125
+ * coreModule(),
126
+ * reactHooksModule({ unstable__sideEffectsInRender: true })
127
+ * )
128
+ * ```
129
+ */
130
+ unstable__sideEffectsInRender?: boolean
131
+ /**
132
+ * A selector creator (usually from `reselect`, or matching the same signature)
133
+ */
134
+ createSelector?: CreateSelectorFunction<any, any, any>
135
+ }
136
+
137
+ /**
138
+ * Creates a module that generates react hooks from endpoints, for use with `buildCreateApi`.
139
+ *
140
+ * @example
141
+ * ```ts
142
+ * const MyContext = React.createContext<ReactReduxContextValue | null>(null);
143
+ * const customCreateApi = buildCreateApi(
144
+ * coreModule(),
145
+ * reactHooksModule({
146
+ * hooks: {
147
+ * useDispatch: createDispatchHook(MyContext),
148
+ * useSelector: createSelectorHook(MyContext),
149
+ * useStore: createStoreHook(MyContext)
150
+ * }
151
+ * })
152
+ * );
153
+ * ```
154
+ *
155
+ * @returns A module for use with `buildCreateApi`
156
+ */
157
+ export const reactHooksModule = ({
158
+ batch = rrBatch,
159
+ hooks = {
160
+ useDispatch: rrUseDispatch,
161
+ useSelector: rrUseSelector,
162
+ useStore: rrUseStore,
163
+ },
164
+ createSelector = _createSelector,
165
+ unstable__sideEffectsInRender = false,
166
+ ...rest
167
+ }: ReactHooksModuleOptions = {}): Module<ReactHooksModule> => {
168
+ if (process.env.NODE_ENV !== 'production') {
169
+ const hookNames = ['useDispatch', 'useSelector', 'useStore'] as const
170
+ let warned = false
171
+ for (const hookName of hookNames) {
172
+ // warn for old hook options
173
+ if (countObjectKeys(rest) > 0) {
174
+ if ((rest as Partial<typeof hooks>)[hookName]) {
175
+ if (!warned) {
176
+ console.warn(
177
+ 'As of RTK 2.0, the hooks now need to be specified as one object, provided under a `hooks` key:' +
178
+ '\n`reactHooksModule({ hooks: { useDispatch, useSelector, useStore } })`',
179
+ )
180
+ warned = true
181
+ }
182
+ }
183
+ // migrate
184
+ // @ts-ignore
185
+ hooks[hookName] = rest[hookName]
186
+ }
187
+ // then make sure we have them all
188
+ if (typeof hooks[hookName] !== 'function') {
189
+ throw new Error(
190
+ `When using custom hooks for context, all ${
191
+ hookNames.length
192
+ } hooks need to be provided: ${hookNames.join(
193
+ ', ',
194
+ )}.\nHook ${hookName} was either not provided or not a function.`,
195
+ )
196
+ }
197
+ }
198
+ }
199
+
200
+ return {
201
+ name: reactHooksModuleName,
202
+ init(api, { serializeQueryArgs }, context) {
203
+ const anyApi = api as any as Api<
204
+ any,
205
+ Record<string, any>,
206
+ any,
207
+ any,
208
+ ReactHooksModule
209
+ >
210
+ const {
211
+ buildQueryHooks,
212
+ buildInfiniteQueryHooks,
213
+ buildMutationHook,
214
+ usePrefetch,
215
+ } = buildHooks({
216
+ api,
217
+ moduleOptions: {
218
+ batch,
219
+ hooks,
220
+ unstable__sideEffectsInRender,
221
+ createSelector,
222
+ },
223
+ serializeQueryArgs,
224
+ context,
225
+ })
226
+ safeAssign(anyApi, { usePrefetch })
227
+ safeAssign(context, { batch })
228
+
229
+ return {
230
+ injectEndpoint(endpointName, definition) {
231
+ if (isQueryDefinition(definition)) {
232
+ const {
233
+ useQuery,
234
+ useLazyQuery,
235
+ useLazyQuerySubscription,
236
+ useQueryState,
237
+ useQuerySubscription,
238
+ } = buildQueryHooks(endpointName)
239
+ safeAssign(anyApi.endpoints[endpointName], {
240
+ useQuery,
241
+ useLazyQuery,
242
+ useLazyQuerySubscription,
243
+ useQueryState,
244
+ useQuerySubscription,
245
+ })
246
+ ;(api as any)[`use${capitalize(endpointName)}Query`] = useQuery
247
+ ;(api as any)[`useLazy${capitalize(endpointName)}Query`] =
248
+ useLazyQuery
249
+ }
250
+ if (isMutationDefinition(definition)) {
251
+ const useMutation = buildMutationHook(endpointName)
252
+ safeAssign(anyApi.endpoints[endpointName], {
253
+ useMutation,
254
+ })
255
+ ;(api as any)[`use${capitalize(endpointName)}Mutation`] =
256
+ useMutation
257
+ } else if (isInfiniteQueryDefinition(definition)) {
258
+ const {
259
+ useInfiniteQuery,
260
+ useInfiniteQuerySubscription,
261
+ useInfiniteQueryState,
262
+ } = buildInfiniteQueryHooks(endpointName)
263
+ safeAssign(anyApi.endpoints[endpointName], {
264
+ useInfiniteQuery,
265
+ useInfiniteQuerySubscription,
266
+ useInfiniteQueryState,
267
+ })
268
+ ;(api as any)[`use${capitalize(endpointName)}InfiniteQuery`] =
269
+ useInfiniteQuery
270
+ }
271
+ },
272
+ }
273
+ },
274
+ }
275
+ }
@@ -0,0 +1,59 @@
1
+ import type {
2
+ DefinitionType,
3
+ EndpointDefinitions,
4
+ MutationDefinition,
5
+ QueryDefinition,
6
+ InfiniteQueryDefinition,
7
+ } from '@reduxjs/toolkit/query'
8
+ import type {
9
+ UseInfiniteQuery,
10
+ UseLazyQuery,
11
+ UseMutation,
12
+ UseQuery,
13
+ } from './buildHooks'
14
+
15
+ type QueryHookNames<Definitions extends EndpointDefinitions> = {
16
+ [K in keyof Definitions as Definitions[K] extends {
17
+ type: DefinitionType.query
18
+ }
19
+ ? `use${Capitalize<K & string>}Query`
20
+ : never]: UseQuery<
21
+ Extract<Definitions[K], QueryDefinition<any, any, any, any>>
22
+ >
23
+ }
24
+
25
+ type LazyQueryHookNames<Definitions extends EndpointDefinitions> = {
26
+ [K in keyof Definitions as Definitions[K] extends {
27
+ type: DefinitionType.query
28
+ }
29
+ ? `useLazy${Capitalize<K & string>}Query`
30
+ : never]: UseLazyQuery<
31
+ Extract<Definitions[K], QueryDefinition<any, any, any, any>>
32
+ >
33
+ }
34
+
35
+ type InfiniteQueryHookNames<Definitions extends EndpointDefinitions> = {
36
+ [K in keyof Definitions as Definitions[K] extends {
37
+ type: DefinitionType.infinitequery
38
+ }
39
+ ? `use${Capitalize<K & string>}InfiniteQuery`
40
+ : never]: UseInfiniteQuery<
41
+ Extract<Definitions[K], InfiniteQueryDefinition<any, any, any, any, any>>
42
+ >
43
+ }
44
+
45
+ type MutationHookNames<Definitions extends EndpointDefinitions> = {
46
+ [K in keyof Definitions as Definitions[K] extends {
47
+ type: DefinitionType.mutation
48
+ }
49
+ ? `use${Capitalize<K & string>}Mutation`
50
+ : never]: UseMutation<
51
+ Extract<Definitions[K], MutationDefinition<any, any, any, any>>
52
+ >
53
+ }
54
+
55
+ export type HooksWithUniqueNames<Definitions extends EndpointDefinitions> =
56
+ QueryHookNames<Definitions> &
57
+ LazyQueryHookNames<Definitions> &
58
+ InfiniteQueryHookNames<Definitions> &
59
+ MutationHookNames<Definitions>
@@ -0,0 +1,10 @@
1
+ export {
2
+ useEffect,
3
+ useRef,
4
+ useMemo,
5
+ useContext,
6
+ useCallback,
7
+ useDebugValue,
8
+ useLayoutEffect,
9
+ useState,
10
+ } from 'react'
@@ -0,0 +1 @@
1
+ export { shallowEqual, Provider, ReactReduxContext } from 'react-redux'
@@ -0,0 +1,8 @@
1
+ export {
2
+ buildCreateApi,
3
+ coreModule,
4
+ copyWithStructuralSharing,
5
+ setupListeners,
6
+ QueryStatus,
7
+ skipToken,
8
+ } from '@reduxjs/toolkit/query'
@@ -0,0 +1,17 @@
1
+ import { useEffect, useRef, useMemo } from './reactImports'
2
+ import { copyWithStructuralSharing } from './rtkqImports'
3
+
4
+ export function useStableQueryArgs<T>(queryArgs: T) {
5
+ const cache = useRef(queryArgs)
6
+ const copy = useMemo(
7
+ () => copyWithStructuralSharing(cache.current, queryArgs),
8
+ [queryArgs],
9
+ )
10
+ useEffect(() => {
11
+ if (cache.current !== copy) {
12
+ cache.current = copy
13
+ }
14
+ }, [copy])
15
+
16
+ return copy
17
+ }
@@ -0,0 +1,13 @@
1
+ import { useEffect, useRef } from './reactImports'
2
+ import { shallowEqual } from './reactReduxImports'
3
+
4
+ export function useShallowStableValue<T>(value: T) {
5
+ const cache = useRef(value)
6
+ useEffect(() => {
7
+ if (!shallowEqual(cache.current, value)) {
8
+ cache.current = value
9
+ }
10
+ }, [value])
11
+
12
+ return shallowEqual(cache.current, value) ? cache.current : value
13
+ }
@@ -0,0 +1,233 @@
1
+ import type {
2
+ BaseQueryApi,
3
+ BaseQueryArg,
4
+ BaseQueryEnhancer,
5
+ BaseQueryError,
6
+ BaseQueryExtraOptions,
7
+ BaseQueryFn,
8
+ BaseQueryMeta,
9
+ } from './baseQueryTypes'
10
+ import type { FetchBaseQueryError } from './fetchBaseQuery'
11
+ import { HandledError } from './HandledError'
12
+
13
+ /**
14
+ * Exponential backoff based on the attempt number.
15
+ *
16
+ * @remarks
17
+ * 1. 600ms * random(0.4, 1.4)
18
+ * 2. 1200ms * random(0.4, 1.4)
19
+ * 3. 2400ms * random(0.4, 1.4)
20
+ * 4. 4800ms * random(0.4, 1.4)
21
+ * 5. 9600ms * random(0.4, 1.4)
22
+ *
23
+ * @param attempt - Current attempt
24
+ * @param maxRetries - Maximum number of retries
25
+ */
26
+ async function defaultBackoff(
27
+ attempt: number = 0,
28
+ maxRetries: number = 5,
29
+ signal?: AbortSignal,
30
+ ) {
31
+ const attempts = Math.min(attempt, maxRetries)
32
+
33
+ const timeout = ~~((Math.random() + 0.4) * (300 << attempts)) // Force a positive int in the case we make this an option
34
+
35
+ await new Promise<void>((resolve, reject) => {
36
+ const timeoutId = setTimeout(() => resolve(), timeout)
37
+
38
+ // If signal is provided and gets aborted, clear timeout and reject
39
+ if (signal) {
40
+ const abortHandler = () => {
41
+ clearTimeout(timeoutId)
42
+ reject(new Error('Aborted'))
43
+ }
44
+
45
+ // Check if already aborted
46
+ if (signal.aborted) {
47
+ clearTimeout(timeoutId)
48
+ reject(new Error('Aborted'))
49
+ } else {
50
+ signal.addEventListener('abort', abortHandler, { once: true })
51
+ }
52
+ }
53
+ })
54
+ }
55
+
56
+ type RetryConditionFunction = (
57
+ error: BaseQueryError<BaseQueryFn>,
58
+ args: BaseQueryArg<BaseQueryFn>,
59
+ extraArgs: {
60
+ attempt: number
61
+ baseQueryApi: BaseQueryApi
62
+ extraOptions: BaseQueryExtraOptions<BaseQueryFn> & RetryOptions
63
+ },
64
+ ) => boolean
65
+
66
+ export type RetryOptions = {
67
+ /**
68
+ * Function used to determine delay between retries
69
+ */
70
+ backoff?: (
71
+ attempt: number,
72
+ maxRetries: number,
73
+ signal?: AbortSignal,
74
+ ) => Promise<void>
75
+ } & (
76
+ | {
77
+ /**
78
+ * How many times the query will be retried (default: 5)
79
+ */
80
+ maxRetries?: number
81
+ retryCondition?: undefined
82
+ }
83
+ | {
84
+ /**
85
+ * Callback to determine if a retry should be attempted.
86
+ * Return `true` for another retry and `false` to quit trying prematurely.
87
+ */
88
+ retryCondition?: RetryConditionFunction
89
+ maxRetries?: undefined
90
+ }
91
+ )
92
+
93
+ function fail<BaseQuery extends BaseQueryFn = BaseQueryFn>(
94
+ error: BaseQueryError<BaseQuery>,
95
+ meta?: BaseQueryMeta<BaseQuery>,
96
+ ): never {
97
+ throw Object.assign(new HandledError({ error, meta }), {
98
+ throwImmediately: true,
99
+ })
100
+ }
101
+
102
+ /**
103
+ * Checks if the abort signal is aborted and fails immediately if so.
104
+ * Used to exit retry loops cleanly when a request is aborted.
105
+ */
106
+ function failIfAborted(signal: AbortSignal): void {
107
+ if (signal.aborted) {
108
+ fail({ status: 'CUSTOM_ERROR', error: 'Aborted' })
109
+ }
110
+ }
111
+
112
+ const EMPTY_OPTIONS = {}
113
+
114
+ const retryWithBackoff: BaseQueryEnhancer<
115
+ unknown,
116
+ RetryOptions,
117
+ RetryOptions | void
118
+ > = (baseQuery, defaultOptions) => async (args, api, extraOptions) => {
119
+ // We need to figure out `maxRetries` before we define `defaultRetryCondition.
120
+ // This is probably goofy, but ought to work.
121
+ // Put our defaults in one array, filter out undefineds, grab the last value.
122
+ const possibleMaxRetries: number[] = [
123
+ 5,
124
+ ((defaultOptions as any) || EMPTY_OPTIONS).maxRetries,
125
+ ((extraOptions as any) || EMPTY_OPTIONS).maxRetries,
126
+ ].filter((x) => x !== undefined)
127
+ const [maxRetries] = possibleMaxRetries.slice(-1)
128
+
129
+ const defaultRetryCondition: RetryConditionFunction = (_, __, { attempt }) =>
130
+ attempt <= maxRetries
131
+
132
+ const options: {
133
+ maxRetries: number
134
+ backoff: typeof defaultBackoff
135
+ retryCondition: typeof defaultRetryCondition
136
+ } = {
137
+ maxRetries,
138
+ backoff: defaultBackoff,
139
+ retryCondition: defaultRetryCondition,
140
+ ...defaultOptions,
141
+ ...extraOptions,
142
+ }
143
+ let retry = 0
144
+
145
+ while (true) {
146
+ // Check if aborted before each attempt
147
+ failIfAborted(api.signal)
148
+
149
+ try {
150
+ const result = await baseQuery(args, api, extraOptions)
151
+ // baseQueries _should_ return an error property, so we should check for that and throw it to continue retrying
152
+ if (result.error) {
153
+ throw new HandledError(result)
154
+ }
155
+ return result
156
+ } catch (e: any) {
157
+ retry++
158
+
159
+ if (e.throwImmediately) {
160
+ if (e instanceof HandledError) {
161
+ return e.value
162
+ }
163
+
164
+ // We don't know what this is, so we have to rethrow it
165
+ throw e
166
+ }
167
+
168
+ if (e instanceof HandledError) {
169
+ if (
170
+ !options.retryCondition(e.value.error as FetchBaseQueryError, args, {
171
+ attempt: retry,
172
+ baseQueryApi: api,
173
+ extraOptions,
174
+ })
175
+ ) {
176
+ return e.value // Max retries for expected error
177
+ }
178
+ } else {
179
+ // For unexpected errors, respect maxRetries
180
+ if (retry > options.maxRetries) {
181
+ // Return the error as a proper error response instead of throwing
182
+ return { error: e }
183
+ }
184
+ }
185
+
186
+ // Check if aborted before backoff
187
+ failIfAborted(api.signal)
188
+
189
+ try {
190
+ await options.backoff(retry, options.maxRetries, api.signal)
191
+ } catch (backoffError) {
192
+ // If backoff was aborted, exit the retry loop
193
+ failIfAborted(api.signal)
194
+ // Otherwise, rethrow the backoff error
195
+ throw backoffError
196
+ }
197
+ }
198
+ }
199
+ }
200
+
201
+ /**
202
+ * A utility that can wrap `baseQuery` in the API definition to provide retries with a basic exponential backoff.
203
+ *
204
+ * @example
205
+ *
206
+ * ```ts
207
+ * // codeblock-meta title="Retry every request 5 times by default"
208
+ * import { createApi, fetchBaseQuery, retry } from '@reduxjs/toolkit/query/react'
209
+ * interface Post {
210
+ * id: number
211
+ * name: string
212
+ * }
213
+ * type PostsResponse = Post[]
214
+ *
215
+ * // maxRetries: 5 is the default, and can be omitted. Shown for documentation purposes.
216
+ * const staggeredBaseQuery = retry(fetchBaseQuery({ baseUrl: '/' }), { maxRetries: 5 });
217
+ * export const api = createApi({
218
+ * baseQuery: staggeredBaseQuery,
219
+ * endpoints: (build) => ({
220
+ * getPosts: build.query<PostsResponse, void>({
221
+ * query: () => ({ url: 'posts' }),
222
+ * }),
223
+ * getPost: build.query<PostsResponse, string>({
224
+ * query: (id) => ({ url: `post/${id}` }),
225
+ * extraOptions: { maxRetries: 8 }, // You can override the retry behavior on each endpoint
226
+ * }),
227
+ * }),
228
+ * });
229
+ *
230
+ * export const { useGetPostsQuery, useGetPostQuery } = api;
231
+ * ```
232
+ */
233
+ export const retry = /* @__PURE__ */ Object.assign(retryWithBackoff, { fail })