@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.
- package/LICENSE +21 -0
- package/README.md +33 -0
- package/changes.json +18 -0
- package/dist/cjs/index.js +6 -0
- package/dist/cjs/redux-toolkit.development.cjs +2406 -0
- package/dist/cjs/redux-toolkit.development.cjs.map +1 -0
- package/dist/cjs/redux-toolkit.production.min.cjs +3 -0
- package/dist/cjs/redux-toolkit.production.min.cjs.map +1 -0
- package/dist/index.d.mts +2665 -0
- package/dist/index.d.ts +2665 -0
- package/dist/query/cjs/index.js +6 -0
- package/dist/query/cjs/rtk-query.development.cjs +3092 -0
- package/dist/query/cjs/rtk-query.development.cjs.map +1 -0
- package/dist/query/cjs/rtk-query.production.min.cjs +2 -0
- package/dist/query/cjs/rtk-query.production.min.cjs.map +1 -0
- package/dist/query/index.d.mts +3066 -0
- package/dist/query/index.d.ts +3066 -0
- package/dist/query/react/cjs/index.js +6 -0
- package/dist/query/react/cjs/rtk-query-react.development.cjs +748 -0
- package/dist/query/react/cjs/rtk-query-react.development.cjs.map +1 -0
- package/dist/query/react/cjs/rtk-query-react.production.min.cjs +2 -0
- package/dist/query/react/cjs/rtk-query-react.production.min.cjs.map +1 -0
- package/dist/query/react/index.d.mts +1009 -0
- package/dist/query/react/index.d.ts +1009 -0
- package/dist/query/react/rtk-query-react.browser.mjs +2 -0
- package/dist/query/react/rtk-query-react.browser.mjs.map +1 -0
- package/dist/query/react/rtk-query-react.legacy-esm.js +740 -0
- package/dist/query/react/rtk-query-react.legacy-esm.js.map +1 -0
- package/dist/query/react/rtk-query-react.modern.mjs +705 -0
- package/dist/query/react/rtk-query-react.modern.mjs.map +1 -0
- package/dist/query/rtk-query.browser.mjs +2 -0
- package/dist/query/rtk-query.browser.mjs.map +1 -0
- package/dist/query/rtk-query.legacy-esm.js +3117 -0
- package/dist/query/rtk-query.legacy-esm.js.map +1 -0
- package/dist/query/rtk-query.modern.mjs +3052 -0
- package/dist/query/rtk-query.modern.mjs.map +1 -0
- package/dist/react/cjs/index.js +6 -0
- package/dist/react/cjs/redux-toolkit-react.development.cjs +55 -0
- package/dist/react/cjs/redux-toolkit-react.development.cjs.map +1 -0
- package/dist/react/cjs/redux-toolkit-react.production.min.cjs +2 -0
- package/dist/react/cjs/redux-toolkit-react.production.min.cjs.map +1 -0
- package/dist/react/index.d.mts +22 -0
- package/dist/react/index.d.ts +22 -0
- package/dist/react/redux-toolkit-react.browser.mjs +2 -0
- package/dist/react/redux-toolkit-react.browser.mjs.map +1 -0
- package/dist/react/redux-toolkit-react.legacy-esm.js +47 -0
- package/dist/react/redux-toolkit-react.legacy-esm.js.map +1 -0
- package/dist/react/redux-toolkit-react.modern.mjs +28 -0
- package/dist/react/redux-toolkit-react.modern.mjs.map +1 -0
- package/dist/redux-toolkit.browser.mjs +3 -0
- package/dist/redux-toolkit.browser.mjs.map +1 -0
- package/dist/redux-toolkit.legacy-esm.js +2351 -0
- package/dist/redux-toolkit.legacy-esm.js.map +1 -0
- package/dist/redux-toolkit.modern.mjs +2330 -0
- package/dist/redux-toolkit.modern.mjs.map +1 -0
- package/dist/uncheckedindexed.ts +16 -0
- package/package.json +310 -0
- package/query/package.json +13 -0
- package/query/react/package.json +13 -0
- package/react/package.json +13 -0
- package/skills/build-modern-redux-apps/modern-redux/SKILL.md +304 -0
- package/skills/build-modern-redux-apps/modern-redux/references/store-lifetime.md +53 -0
- package/skills/build-modern-redux-apps/redux-dataflow/SKILL.md +264 -0
- package/skills/evolve-and-diagnose-redux-apps/debug-redux-toolkit-apps/SKILL.md +269 -0
- package/skills/evolve-and-diagnose-redux-apps/migrate-to-modern-redux/SKILL.md +226 -0
- package/skills/manage-server-data/adopt-rtk-query/SKILL.md +385 -0
- package/skills/manage-server-data/adopt-rtk-query/references/endpoint-lifecycle.md +36 -0
- package/skills/model-redux-state/build-slices-and-selectors/SKILL.md +364 -0
- package/skills/model-redux-state/build-slices-and-selectors/references/slice-patterns.md +59 -0
- package/skills/model-redux-state/design-state-ownership/SKILL.md +322 -0
- package/skills/model-redux-state/design-state-ownership/references/state-ownership.md +28 -0
- package/skills/orchestrate-side-effects/handle-side-effects/SKILL.md +271 -0
- package/skills/orchestrate-side-effects/handle-side-effects/references/listener-workflows.md +34 -0
- package/src/actionCreatorInvariantMiddleware.ts +34 -0
- package/src/autoBatchEnhancer.ts +146 -0
- package/src/combineSlices.ts +487 -0
- package/src/configureStore.ts +248 -0
- package/src/createAction.ts +324 -0
- package/src/createAsyncThunk.ts +791 -0
- package/src/createDraftSafeSelector.ts +30 -0
- package/src/createReducer.ts +217 -0
- package/src/createSlice.ts +1079 -0
- package/src/devtoolsExtension.ts +241 -0
- package/src/dynamicMiddleware/index.ts +93 -0
- package/src/dynamicMiddleware/react/index.ts +101 -0
- package/src/dynamicMiddleware/types.ts +82 -0
- package/src/entities/create_adapter.ts +47 -0
- package/src/entities/entity_state.ts +38 -0
- package/src/entities/index.ts +8 -0
- package/src/entities/models.ts +198 -0
- package/src/entities/sorted_state_adapter.ts +266 -0
- package/src/entities/state_adapter.ts +58 -0
- package/src/entities/state_selectors.ts +73 -0
- package/src/entities/unsorted_state_adapter.ts +204 -0
- package/src/entities/utils.ts +68 -0
- package/src/formatProdErrorMessage.ts +13 -0
- package/src/getDefaultEnhancers.ts +31 -0
- package/src/getDefaultMiddleware.ts +113 -0
- package/src/immerImports.ts +7 -0
- package/src/immutableStateInvariantMiddleware.ts +274 -0
- package/src/index.ts +213 -0
- package/src/listenerMiddleware/exceptions.ts +20 -0
- package/src/listenerMiddleware/index.ts +562 -0
- package/src/listenerMiddleware/task.ts +100 -0
- package/src/listenerMiddleware/types.ts +886 -0
- package/src/listenerMiddleware/utils.ts +30 -0
- package/src/mapBuilders.ts +298 -0
- package/src/matchers.ts +365 -0
- package/src/nanoid.ts +20 -0
- package/src/query/HandledError.ts +6 -0
- package/src/query/apiTypes.ts +120 -0
- package/src/query/baseQueryTypes.ts +101 -0
- package/src/query/core/apiState.ts +377 -0
- package/src/query/core/buildInitiate.ts +596 -0
- package/src/query/core/buildMiddleware/batchActions.ts +207 -0
- package/src/query/core/buildMiddleware/cacheCollection.ts +204 -0
- package/src/query/core/buildMiddleware/cacheLifecycle.ts +379 -0
- package/src/query/core/buildMiddleware/devMiddleware.ts +34 -0
- package/src/query/core/buildMiddleware/index.ts +162 -0
- package/src/query/core/buildMiddleware/invalidationByTags.ts +139 -0
- package/src/query/core/buildMiddleware/polling.ts +187 -0
- package/src/query/core/buildMiddleware/queryLifecycle.ts +508 -0
- package/src/query/core/buildMiddleware/types.ts +173 -0
- package/src/query/core/buildMiddleware/windowEventHandling.ts +64 -0
- package/src/query/core/buildSelectors.ts +413 -0
- package/src/query/core/buildSlice.ts +735 -0
- package/src/query/core/buildThunks.ts +1124 -0
- package/src/query/core/index.ts +58 -0
- package/src/query/core/module.ts +727 -0
- package/src/query/core/rtkImports.ts +24 -0
- package/src/query/core/setupListeners.ts +118 -0
- package/src/query/createApi.ts +506 -0
- package/src/query/defaultSerializeQueryArgs.ts +52 -0
- package/src/query/endpointDefinitions.ts +1717 -0
- package/src/query/fakeBaseQuery.ts +21 -0
- package/src/query/fetchBaseQuery.ts +385 -0
- package/src/query/index.ts +105 -0
- package/src/query/react/ApiProvider.tsx +69 -0
- package/src/query/react/buildHooks.ts +2297 -0
- package/src/query/react/constants.ts +2 -0
- package/src/query/react/index.ts +45 -0
- package/src/query/react/module.ts +275 -0
- package/src/query/react/namedHooks.ts +59 -0
- package/src/query/react/reactImports.ts +10 -0
- package/src/query/react/reactReduxImports.ts +1 -0
- package/src/query/react/rtkqImports.ts +8 -0
- package/src/query/react/useSerializedStableValue.ts +17 -0
- package/src/query/react/useShallowStableValue.ts +13 -0
- package/src/query/retry.ts +233 -0
- package/src/query/standardSchema.ts +35 -0
- package/src/query/tsHelpers.ts +48 -0
- package/src/query/utils/capitalize.ts +3 -0
- package/src/query/utils/copyWithStructuralSharing.ts +27 -0
- package/src/query/utils/countObjectKeys.ts +14 -0
- package/src/query/utils/filterMap.ts +27 -0
- package/src/query/utils/getCurrent.ts +6 -0
- package/src/query/utils/getOrInsert.ts +41 -0
- package/src/query/utils/immerImports.ts +9 -0
- package/src/query/utils/index.ts +11 -0
- package/src/query/utils/isAbsoluteUrl.ts +9 -0
- package/src/query/utils/isDocumentVisible.ts +12 -0
- package/src/query/utils/isNotNullish.ts +7 -0
- package/src/query/utils/isOnline.ts +12 -0
- package/src/query/utils/isValidUrl.ts +9 -0
- package/src/query/utils/joinUrls.ts +26 -0
- package/src/query/utils/signals.ts +33 -0
- package/src/react/index.ts +7 -0
- package/src/reduxImports.ts +8 -0
- package/src/reselectImports.ts +1 -0
- package/src/serializableStateInvariantMiddleware.ts +285 -0
- package/src/tsHelpers.ts +214 -0
- package/src/uncheckedindexed.ts +16 -0
- package/src/utils.ts +125 -0
|
@@ -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 @@
|
|
|
1
|
+
export { shallowEqual, Provider, ReactReduxContext } from 'react-redux'
|
|
@@ -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 })
|