@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,173 @@
1
+ import type {
2
+ Action,
3
+ AsyncThunkAction,
4
+ Dispatch,
5
+ Middleware,
6
+ MiddlewareAPI,
7
+ ThunkAction,
8
+ ThunkDispatch,
9
+ UnknownAction,
10
+ } from '@reduxjs/toolkit'
11
+ import type { Api, ApiContext } from '../../apiTypes'
12
+ import type {
13
+ AssertTagTypes,
14
+ EndpointDefinitions,
15
+ } from '../../endpointDefinitions'
16
+ import type {
17
+ QueryStatus,
18
+ QuerySubState,
19
+ RootState,
20
+ SubscriptionInternalState,
21
+ SubscriptionState,
22
+ } from '../apiState'
23
+ import type {
24
+ InfiniteQueryThunk,
25
+ MutationThunk,
26
+ QueryThunk,
27
+ QueryThunkArg,
28
+ ThunkResult,
29
+ } from '../buildThunks'
30
+ import type {
31
+ InfiniteQueryActionCreatorResult,
32
+ MutationActionCreatorResult,
33
+ QueryActionCreatorResult,
34
+ } from '../buildInitiate'
35
+ import type { AllSelectors } from '../buildSelectors'
36
+
37
+ export type QueryStateMeta<T> = Record<string, undefined | T>
38
+ export type TimeoutId = ReturnType<typeof setTimeout>
39
+
40
+ type QueryPollState = {
41
+ nextPollTimestamp: number
42
+ timeout?: TimeoutId
43
+ pollingInterval: number
44
+ }
45
+
46
+ export interface InternalMiddlewareState {
47
+ currentSubscriptions: SubscriptionInternalState
48
+ currentPolls: Map<string, QueryPollState>
49
+ runningQueries: Map<
50
+ string,
51
+ | QueryActionCreatorResult<any>
52
+ | InfiniteQueryActionCreatorResult<any>
53
+ | undefined
54
+ >
55
+ runningMutations: Map<string, MutationActionCreatorResult<any> | undefined>
56
+ }
57
+
58
+ export interface SubscriptionSelectors {
59
+ getSubscriptions: () => SubscriptionInternalState
60
+ getSubscriptionCount: (queryCacheKey: string) => number
61
+ isRequestSubscribed: (queryCacheKey: string, requestId: string) => boolean
62
+ }
63
+
64
+ export interface BuildMiddlewareInput<
65
+ Definitions extends EndpointDefinitions,
66
+ ReducerPath extends string,
67
+ TagTypes extends string,
68
+ > {
69
+ reducerPath: ReducerPath
70
+ context: ApiContext<Definitions>
71
+ queryThunk: QueryThunk
72
+ mutationThunk: MutationThunk
73
+ infiniteQueryThunk: InfiniteQueryThunk<any>
74
+ api: Api<any, Definitions, ReducerPath, TagTypes>
75
+ assertTagType: AssertTagTypes
76
+ selectors: AllSelectors
77
+ getRunningQueryThunk: (
78
+ endpointName: string,
79
+ queryArgs: any,
80
+ ) => (dispatch: Dispatch) => QueryActionCreatorResult<any> | undefined
81
+ getInternalState: (dispatch: Dispatch) => InternalMiddlewareState
82
+ }
83
+
84
+ export type SubMiddlewareApi = MiddlewareAPI<
85
+ ThunkDispatch<any, any, UnknownAction>,
86
+ RootState<EndpointDefinitions, string, string>
87
+ >
88
+
89
+ export interface BuildSubMiddlewareInput
90
+ extends BuildMiddlewareInput<EndpointDefinitions, string, string> {
91
+ internalState: InternalMiddlewareState
92
+ refetchQuery(
93
+ querySubState: Exclude<
94
+ QuerySubState<any>,
95
+ { status: QueryStatus.uninitialized }
96
+ >,
97
+ ): ThunkAction<QueryActionCreatorResult<any>, any, any, UnknownAction>
98
+ isThisApiSliceAction: (action: Action) => boolean
99
+ selectors: AllSelectors
100
+ mwApi: MiddlewareAPI<
101
+ ThunkDispatch<any, any, UnknownAction>,
102
+ RootState<EndpointDefinitions, string, string>
103
+ >
104
+ }
105
+
106
+ export type SubMiddlewareBuilder = (
107
+ input: BuildSubMiddlewareInput,
108
+ ) => Middleware<
109
+ {},
110
+ RootState<EndpointDefinitions, string, string>,
111
+ ThunkDispatch<any, any, UnknownAction>
112
+ >
113
+
114
+ type MwNext = Parameters<ReturnType<Middleware>>[0]
115
+
116
+ export type ApiMiddlewareInternalHandler<Return = void> = (
117
+ action: Action,
118
+ mwApi: SubMiddlewareApi & { next: MwNext },
119
+ prevState: RootState<EndpointDefinitions, string, string>,
120
+ ) => Return
121
+
122
+ export type InternalHandlerBuilder<ReturnType = void> = (
123
+ input: BuildSubMiddlewareInput,
124
+ ) => ApiMiddlewareInternalHandler<ReturnType>
125
+
126
+ export interface PromiseConstructorWithKnownReason {
127
+ /**
128
+ * Creates a new Promise with a known rejection reason.
129
+ * @param executor A callback used to initialize the promise. This callback is passed two arguments:
130
+ * a resolve callback used to resolve the promise with a value or the result of another promise,
131
+ * and a reject callback used to reject the promise with a provided reason or error.
132
+ */
133
+ new <T, R>(
134
+ executor: (
135
+ resolve: (value: T | PromiseLike<T>) => void,
136
+ reject: (reason?: R) => void,
137
+ ) => void,
138
+ ): PromiseWithKnownReason<T, R>
139
+ }
140
+
141
+ export type PromiseWithKnownReason<T, R> = Omit<
142
+ Promise<T>,
143
+ 'then' | 'catch'
144
+ > & {
145
+ /**
146
+ * Attaches callbacks for the resolution and/or rejection of the Promise.
147
+ * @param onfulfilled The callback to execute when the Promise is resolved.
148
+ * @param onrejected The callback to execute when the Promise is rejected.
149
+ * @returns A Promise for the completion of which ever callback is executed.
150
+ */
151
+ then<TResult1 = T, TResult2 = never>(
152
+ onfulfilled?:
153
+ | ((value: T) => TResult1 | PromiseLike<TResult1>)
154
+ | undefined
155
+ | null,
156
+ onrejected?:
157
+ | ((reason: R) => TResult2 | PromiseLike<TResult2>)
158
+ | undefined
159
+ | null,
160
+ ): Promise<TResult1 | TResult2>
161
+
162
+ /**
163
+ * Attaches a callback for only the rejection of the Promise.
164
+ * @param onrejected The callback to execute when the Promise is rejected.
165
+ * @returns A Promise for the completion of the callback.
166
+ */
167
+ catch<TResult = never>(
168
+ onrejected?:
169
+ | ((reason: R) => TResult | PromiseLike<TResult>)
170
+ | undefined
171
+ | null,
172
+ ): Promise<T | TResult>
173
+ }
@@ -0,0 +1,64 @@
1
+ import { QueryStatus, STATUS_UNINITIALIZED } from '../apiState'
2
+ import type { QueryCacheKey } from '../apiState'
3
+ import { onFocus, onOnline } from '../setupListeners'
4
+ import type {
5
+ ApiMiddlewareInternalHandler,
6
+ InternalHandlerBuilder,
7
+ SubMiddlewareApi,
8
+ } from './types'
9
+
10
+ export const buildWindowEventHandler: InternalHandlerBuilder = ({
11
+ reducerPath,
12
+ context,
13
+ api,
14
+ refetchQuery,
15
+ internalState,
16
+ }) => {
17
+ const { removeQueryResult } = api.internalActions
18
+
19
+ const handler: ApiMiddlewareInternalHandler = (action, mwApi) => {
20
+ if (onFocus.match(action)) {
21
+ refetchValidQueries(mwApi, 'refetchOnFocus')
22
+ }
23
+ if (onOnline.match(action)) {
24
+ refetchValidQueries(mwApi, 'refetchOnReconnect')
25
+ }
26
+ }
27
+
28
+ function refetchValidQueries(
29
+ api: SubMiddlewareApi,
30
+ type: 'refetchOnFocus' | 'refetchOnReconnect',
31
+ ) {
32
+ const state = api.getState()[reducerPath]
33
+ const queries = state.queries
34
+ const subscriptions = internalState.currentSubscriptions
35
+
36
+ context.batch(() => {
37
+ for (const queryCacheKey of subscriptions.keys()) {
38
+ const querySubState = queries[queryCacheKey]
39
+ const subscriptionSubState = subscriptions.get(queryCacheKey)
40
+
41
+ if (!subscriptionSubState || !querySubState) continue
42
+
43
+ const values = [...subscriptionSubState.values()]
44
+ const shouldRefetch =
45
+ values.some((sub) => sub[type] === true) ||
46
+ (values.every((sub) => sub[type] === undefined) && state.config[type])
47
+
48
+ if (shouldRefetch) {
49
+ if (subscriptionSubState.size === 0) {
50
+ api.dispatch(
51
+ removeQueryResult({
52
+ queryCacheKey: queryCacheKey as QueryCacheKey,
53
+ }),
54
+ )
55
+ } else if (querySubState.status !== STATUS_UNINITIALIZED) {
56
+ api.dispatch(refetchQuery(querySubState))
57
+ }
58
+ }
59
+ }
60
+ })
61
+ }
62
+
63
+ return handler
64
+ }
@@ -0,0 +1,413 @@
1
+ import type { InternalSerializeQueryArgs } from '../defaultSerializeQueryArgs'
2
+ import type {
3
+ EndpointDefinition,
4
+ EndpointDefinitions,
5
+ InfiniteQueryArgFrom,
6
+ InfiniteQueryDefinition,
7
+ MutationDefinition,
8
+ QueryArgFrom,
9
+ QueryArgFromAnyQuery,
10
+ QueryDefinition,
11
+ ReducerPathFrom,
12
+ TagDescription,
13
+ TagTypesFrom,
14
+ } from '../endpointDefinitions'
15
+ import { expandTagDescription } from '../endpointDefinitions'
16
+ import { filterMap, isNotNullish } from '../utils'
17
+ import type {
18
+ InfiniteData,
19
+ InfiniteQueryConfigOptions,
20
+ InfiniteQuerySubState,
21
+ MutationSubState,
22
+ QueryCacheKey,
23
+ QueryState,
24
+ QuerySubState,
25
+ RequestStatusFlags,
26
+ RootState as _RootState,
27
+ QueryStatus,
28
+ } from './apiState'
29
+ import { STATUS_UNINITIALIZED, getRequestStatusFlags } from './apiState'
30
+ import { getMutationCacheKey } from './buildSlice'
31
+ import type { createSelector as _createSelector } from './rtkImports'
32
+ import { createNextState } from './rtkImports'
33
+ import {
34
+ type AllQueryKeys,
35
+ getNextPageParam,
36
+ getPreviousPageParam,
37
+ } from './buildThunks'
38
+
39
+ export type SkipToken = typeof skipToken
40
+ /**
41
+ * Can be passed into `useQuery`, `useQueryState` or `useQuerySubscription`
42
+ * instead of the query argument to get the same effect as if setting
43
+ * `skip: true` in the query options.
44
+ *
45
+ * Useful for scenarios where a query should be skipped when `arg` is `undefined`
46
+ * and TypeScript complains about it because `arg` is not allowed to be passed
47
+ * in as `undefined`, such as
48
+ *
49
+ * ```ts
50
+ * // codeblock-meta title="will error if the query argument is not allowed to be undefined" no-transpile
51
+ * useSomeQuery(arg, { skip: !!arg })
52
+ * ```
53
+ *
54
+ * ```ts
55
+ * // codeblock-meta title="using skipToken instead" no-transpile
56
+ * useSomeQuery(arg ?? skipToken)
57
+ * ```
58
+ *
59
+ * If passed directly into a query or mutation selector, that selector will always
60
+ * return an uninitialized state.
61
+ */
62
+ export const skipToken = /* @__PURE__ */ Symbol.for('RTKQ/skipToken')
63
+
64
+ export type BuildSelectorsApiEndpointQuery<
65
+ Definition extends QueryDefinition<any, any, any, any, any>,
66
+ Definitions extends EndpointDefinitions,
67
+ > = {
68
+ select: QueryResultSelectorFactory<
69
+ Definition,
70
+ _RootState<
71
+ Definitions,
72
+ TagTypesFrom<Definition>,
73
+ ReducerPathFrom<Definition>
74
+ >
75
+ >
76
+ }
77
+
78
+ export type BuildSelectorsApiEndpointInfiniteQuery<
79
+ Definition extends InfiniteQueryDefinition<any, any, any, any, any>,
80
+ Definitions extends EndpointDefinitions,
81
+ > = {
82
+ select: InfiniteQueryResultSelectorFactory<
83
+ Definition,
84
+ _RootState<
85
+ Definitions,
86
+ TagTypesFrom<Definition>,
87
+ ReducerPathFrom<Definition>
88
+ >
89
+ >
90
+ }
91
+
92
+ export type BuildSelectorsApiEndpointMutation<
93
+ Definition extends MutationDefinition<any, any, any, any, any>,
94
+ Definitions extends EndpointDefinitions,
95
+ > = {
96
+ select: MutationResultSelectorFactory<
97
+ Definition,
98
+ _RootState<
99
+ Definitions,
100
+ TagTypesFrom<Definition>,
101
+ ReducerPathFrom<Definition>
102
+ >
103
+ >
104
+ }
105
+
106
+ type QueryResultSelectorFactory<
107
+ Definition extends QueryDefinition<any, any, any, any>,
108
+ RootState,
109
+ > = (
110
+ queryArg: QueryArgFrom<Definition> | SkipToken,
111
+ ) => (state: RootState) => QueryResultSelectorResult<Definition>
112
+
113
+ export type QueryResultSelectorResult<
114
+ Definition extends QueryDefinition<any, any, any, any>,
115
+ > = QuerySubState<Definition> & RequestStatusFlags
116
+
117
+ type InfiniteQueryResultSelectorFactory<
118
+ Definition extends InfiniteQueryDefinition<any, any, any, any, any>,
119
+ RootState,
120
+ > = (
121
+ queryArg: InfiniteQueryArgFrom<Definition> | SkipToken,
122
+ ) => (state: RootState) => InfiniteQueryResultSelectorResult<Definition>
123
+
124
+ export type InfiniteQueryResultFlags = {
125
+ hasNextPage: boolean
126
+ hasPreviousPage: boolean
127
+ isFetchingNextPage: boolean
128
+ isFetchingPreviousPage: boolean
129
+ isFetchNextPageError: boolean
130
+ isFetchPreviousPageError: boolean
131
+ }
132
+
133
+ export type InfiniteQueryResultSelectorResult<
134
+ Definition extends InfiniteQueryDefinition<any, any, any, any, any>,
135
+ > = InfiniteQuerySubState<Definition> &
136
+ RequestStatusFlags &
137
+ InfiniteQueryResultFlags
138
+
139
+ type MutationResultSelectorFactory<
140
+ Definition extends MutationDefinition<any, any, any, any>,
141
+ RootState,
142
+ > = (
143
+ requestId:
144
+ | string
145
+ | { requestId: string | undefined; fixedCacheKey: string | undefined }
146
+ | SkipToken,
147
+ ) => (state: RootState) => MutationResultSelectorResult<Definition>
148
+
149
+ export type MutationResultSelectorResult<
150
+ Definition extends MutationDefinition<any, any, any, any>,
151
+ > = MutationSubState<Definition> & RequestStatusFlags
152
+
153
+ const initialSubState: QuerySubState<any> = {
154
+ status: STATUS_UNINITIALIZED,
155
+ }
156
+
157
+ // abuse immer to freeze default states
158
+ const defaultQuerySubState = /* @__PURE__ */ createNextState(
159
+ initialSubState,
160
+ () => {},
161
+ )
162
+ const defaultMutationSubState = /* @__PURE__ */ createNextState(
163
+ initialSubState as MutationSubState<any>,
164
+ () => {},
165
+ )
166
+
167
+ export type AllSelectors = ReturnType<typeof buildSelectors>
168
+
169
+ export function buildSelectors<
170
+ Definitions extends EndpointDefinitions,
171
+ ReducerPath extends string,
172
+ >({
173
+ serializeQueryArgs,
174
+ reducerPath,
175
+ createSelector,
176
+ }: {
177
+ serializeQueryArgs: InternalSerializeQueryArgs
178
+ reducerPath: ReducerPath
179
+ createSelector: typeof _createSelector
180
+ }) {
181
+ type RootState = _RootState<Definitions, string, string>
182
+
183
+ const selectSkippedQuery = (state: RootState) => defaultQuerySubState
184
+ const selectSkippedMutation = (state: RootState) => defaultMutationSubState
185
+
186
+ return {
187
+ buildQuerySelector,
188
+ buildInfiniteQuerySelector,
189
+ buildMutationSelector,
190
+ selectInvalidatedBy,
191
+ selectCachedArgsForQuery,
192
+ selectApiState,
193
+ selectQueries,
194
+ selectMutations,
195
+ selectQueryEntry,
196
+ selectConfig,
197
+ }
198
+
199
+ function withRequestFlags<T extends { status: QueryStatus }>(
200
+ substate: T,
201
+ ): T & RequestStatusFlags {
202
+ return { ...substate, ...getRequestStatusFlags(substate.status) }
203
+ }
204
+
205
+ function selectApiState(rootState: RootState) {
206
+ const state = rootState[reducerPath]
207
+ if (process.env.NODE_ENV !== 'production') {
208
+ if (!state) {
209
+ if ((selectApiState as any).triggered) return state
210
+ ;(selectApiState as any).triggered = true
211
+ console.error(
212
+ `Error: No data found at \`state.${reducerPath}\`. Did you forget to add the reducer to the store?`,
213
+ )
214
+ }
215
+ }
216
+ return state
217
+ }
218
+
219
+ function selectQueries(rootState: RootState) {
220
+ return selectApiState(rootState)?.queries
221
+ }
222
+
223
+ function selectQueryEntry(rootState: RootState, cacheKey: QueryCacheKey) {
224
+ return selectQueries(rootState)?.[cacheKey]
225
+ }
226
+
227
+ function selectMutations(rootState: RootState) {
228
+ return selectApiState(rootState)?.mutations
229
+ }
230
+
231
+ function selectConfig(rootState: RootState) {
232
+ return selectApiState(rootState)?.config
233
+ }
234
+
235
+ function buildAnyQuerySelector(
236
+ endpointName: string,
237
+ endpointDefinition: EndpointDefinition<any, any, any, any>,
238
+ combiner: <T extends { status: QueryStatus }>(
239
+ substate: T,
240
+ ) => T & RequestStatusFlags,
241
+ ) {
242
+ return (queryArgs: any) => {
243
+ // Avoid calling serializeQueryArgs if the arg is skipToken
244
+ if (queryArgs === skipToken) {
245
+ return createSelector(selectSkippedQuery, combiner)
246
+ }
247
+
248
+ const serializedArgs = serializeQueryArgs({
249
+ queryArgs,
250
+ endpointDefinition,
251
+ endpointName,
252
+ })
253
+ const selectQuerySubstate = (state: RootState) =>
254
+ selectQueryEntry(state, serializedArgs) ?? defaultQuerySubState
255
+
256
+ return createSelector(selectQuerySubstate, combiner)
257
+ }
258
+ }
259
+
260
+ function buildQuerySelector(
261
+ endpointName: string,
262
+ endpointDefinition: QueryDefinition<any, any, any, any>,
263
+ ) {
264
+ return buildAnyQuerySelector(
265
+ endpointName,
266
+ endpointDefinition,
267
+ withRequestFlags,
268
+ ) as QueryResultSelectorFactory<any, RootState>
269
+ }
270
+
271
+ function buildInfiniteQuerySelector(
272
+ endpointName: string,
273
+ endpointDefinition: InfiniteQueryDefinition<any, any, any, any, any>,
274
+ ) {
275
+ const { infiniteQueryOptions } = endpointDefinition
276
+
277
+ function withInfiniteQueryResultFlags<T extends { status: QueryStatus }>(
278
+ substate: T,
279
+ ): T & RequestStatusFlags & InfiniteQueryResultFlags {
280
+ const stateWithRequestFlags = {
281
+ ...(substate as InfiniteQuerySubState<any>),
282
+ ...getRequestStatusFlags(substate.status),
283
+ }
284
+
285
+ const { isLoading, isError, direction } = stateWithRequestFlags
286
+ const isForward = direction === 'forward'
287
+ const isBackward = direction === 'backward'
288
+
289
+ return {
290
+ ...stateWithRequestFlags,
291
+ hasNextPage: getHasNextPage(
292
+ infiniteQueryOptions,
293
+ stateWithRequestFlags.data,
294
+ stateWithRequestFlags.originalArgs,
295
+ ),
296
+ hasPreviousPage: getHasPreviousPage(
297
+ infiniteQueryOptions,
298
+ stateWithRequestFlags.data,
299
+ stateWithRequestFlags.originalArgs,
300
+ ),
301
+ isFetchingNextPage: isLoading && isForward,
302
+ isFetchingPreviousPage: isLoading && isBackward,
303
+ isFetchNextPageError: isError && isForward,
304
+ isFetchPreviousPageError: isError && isBackward,
305
+ }
306
+ }
307
+
308
+ return buildAnyQuerySelector(
309
+ endpointName,
310
+ endpointDefinition,
311
+ withInfiniteQueryResultFlags,
312
+ ) as unknown as InfiniteQueryResultSelectorFactory<any, RootState>
313
+ }
314
+
315
+ function buildMutationSelector() {
316
+ return ((id) => {
317
+ let mutationId: string | typeof skipToken
318
+ if (typeof id === 'object') {
319
+ mutationId = getMutationCacheKey(id) ?? skipToken
320
+ } else {
321
+ mutationId = id
322
+ }
323
+ const selectMutationSubstate = (state: RootState) =>
324
+ selectApiState(state)?.mutations?.[mutationId as string] ??
325
+ defaultMutationSubState
326
+ const finalSelectMutationSubstate =
327
+ mutationId === skipToken
328
+ ? selectSkippedMutation
329
+ : selectMutationSubstate
330
+
331
+ return createSelector(finalSelectMutationSubstate, withRequestFlags)
332
+ }) as MutationResultSelectorFactory<any, RootState>
333
+ }
334
+
335
+ function selectInvalidatedBy(
336
+ state: RootState,
337
+ tags: ReadonlyArray<TagDescription<string> | null | undefined>,
338
+ ): Array<{
339
+ endpointName: string
340
+ originalArgs: any
341
+ queryCacheKey: QueryCacheKey
342
+ }> {
343
+ const apiState = state[reducerPath]
344
+ const toInvalidate = new Set<QueryCacheKey>()
345
+ const finalTags = filterMap(tags, isNotNullish, expandTagDescription)
346
+ for (const tag of finalTags) {
347
+ const provided = apiState.provided.tags[tag.type]
348
+ if (!provided) {
349
+ continue
350
+ }
351
+
352
+ let invalidateSubscriptions =
353
+ (tag.id !== undefined
354
+ ? // id given: invalidate all queries that provide this type & id
355
+ provided[tag.id]
356
+ : // no id: invalidate all queries that provide this type
357
+ Object.values(provided).flat()) ?? []
358
+
359
+ for (const invalidate of invalidateSubscriptions) {
360
+ toInvalidate.add(invalidate)
361
+ }
362
+ }
363
+
364
+ return Array.from(toInvalidate.values()).flatMap((queryCacheKey) => {
365
+ const querySubState = apiState.queries[queryCacheKey]
366
+ return querySubState
367
+ ? {
368
+ queryCacheKey,
369
+ endpointName: querySubState.endpointName!,
370
+ originalArgs: querySubState.originalArgs,
371
+ }
372
+ : []
373
+ })
374
+ }
375
+
376
+ function selectCachedArgsForQuery<
377
+ QueryName extends AllQueryKeys<Definitions>,
378
+ >(
379
+ state: RootState,
380
+ queryName: QueryName,
381
+ ): Array<QueryArgFromAnyQuery<Definitions[QueryName]>> {
382
+ return filterMap(
383
+ Object.values(selectQueries(state) as QueryState<any>),
384
+ (
385
+ entry,
386
+ ): entry is Exclude<
387
+ QuerySubState<Definitions[QueryName]>,
388
+ { status: QueryStatus.uninitialized }
389
+ > =>
390
+ entry?.endpointName === queryName &&
391
+ entry.status !== STATUS_UNINITIALIZED,
392
+ (entry) => entry.originalArgs,
393
+ )
394
+ }
395
+
396
+ function getHasNextPage(
397
+ options: InfiniteQueryConfigOptions<any, any, any>,
398
+ data?: InfiniteData<unknown, unknown>,
399
+ queryArg?: unknown,
400
+ ): boolean {
401
+ if (!data) return false
402
+ return getNextPageParam(options, data, queryArg) != null
403
+ }
404
+
405
+ function getHasPreviousPage(
406
+ options: InfiniteQueryConfigOptions<any, any, any>,
407
+ data?: InfiniteData<unknown, unknown>,
408
+ queryArg?: unknown,
409
+ ): boolean {
410
+ if (!data || !options.getPreviousPageParam) return false
411
+ return getPreviousPageParam(options, data, queryArg) != null
412
+ }
413
+ }