88 isRejectedWithValue ,
99 createNextState ,
1010 prepareAutoBatched ,
11+ SHOULD_AUTOBATCH ,
12+ nanoid ,
1113} from './rtkImports'
1214import type {
1315 QuerySubstateIdentifier ,
@@ -21,15 +23,24 @@ import type {
2123 QueryCacheKey ,
2224 SubscriptionState ,
2325 ConfigState ,
26+ QueryKeys ,
2427} from './apiState'
2528import { QueryStatus } from './apiState'
26- import type { MutationThunk , QueryThunk , RejectedAction } from './buildThunks'
29+ import type {
30+ MutationThunk ,
31+ QueryThunk ,
32+ QueryThunkArg ,
33+ RejectedAction ,
34+ } from './buildThunks'
2735import { calculateProvidedByThunk } from './buildThunks'
2836import type {
2937 AssertTagTypes ,
38+ DefinitionType ,
3039 EndpointDefinitions ,
3140 FullTagDescription ,
41+ QueryArgFrom ,
3242 QueryDefinition ,
43+ ResultTypeFrom ,
3344} from '../endpointDefinitions'
3445import type { Patch } from 'immer'
3546import { isDraft } from 'immer'
@@ -42,6 +53,44 @@ import {
4253} from '../utils'
4354import type { ApiContext } from '../apiTypes'
4455import { isUpsertQuery } from './buildInitiate'
56+ import type { InternalSerializeQueryArgs } from '../defaultSerializeQueryArgs'
57+
58+ /**
59+ * A typesafe single entry to be upserted into the cache
60+ */
61+ export type NormalizedQueryUpsertEntry <
62+ Definitions extends EndpointDefinitions ,
63+ EndpointName extends QueryKeys < Definitions > ,
64+ > = {
65+ endpointName : EndpointName
66+ args : QueryArgFrom < Definitions [ EndpointName ] >
67+ value : ResultTypeFrom < Definitions [ EndpointName ] >
68+ }
69+
70+ /**
71+ * The internal version that is not typesafe since we can't carry the generics through `createSlice`
72+ */
73+ type NormalizedQueryUpsertEntryPayload = {
74+ endpointName : string
75+ args : any
76+ value : any
77+ }
78+
79+ /**
80+ * A typesafe representation of a util action creator that accepts cache entry descriptions to upsert
81+ */
82+ export type UpsertEntries < Definitions extends EndpointDefinitions > = <
83+ EndpointNames extends Array < QueryKeys < Definitions > > ,
84+ > (
85+ entries : [
86+ ...{
87+ [ I in keyof EndpointNames ] : NormalizedQueryUpsertEntry <
88+ Definitions ,
89+ EndpointNames [ I ]
90+ >
91+ } ,
92+ ] ,
93+ ) => PayloadAction < NormalizedQueryUpsertEntryPayload >
4594
4695function updateQuerySubstateIfExists (
4796 state : QueryState < any > ,
@@ -92,6 +141,7 @@ export function buildSlice({
92141 reducerPath,
93142 queryThunk,
94143 mutationThunk,
144+ serializeQueryArgs,
95145 context : {
96146 endpointDefinitions : definitions ,
97147 apiUid,
@@ -104,6 +154,7 @@ export function buildSlice({
104154 reducerPath : string
105155 queryThunk : QueryThunk
106156 mutationThunk : MutationThunk
157+ serializeQueryArgs : InternalSerializeQueryArgs
107158 context : ApiContext < EndpointDefinitions >
108159 assertTagType : AssertTagTypes
109160 config : Omit <
@@ -221,6 +272,63 @@ export function buildSlice({
221272 } ,
222273 prepare : prepareAutoBatched < QuerySubstateIdentifier > ( ) ,
223274 } ,
275+ cacheEntriesUpserted : {
276+ reducer (
277+ draft ,
278+ action : PayloadAction <
279+ NormalizedQueryUpsertEntryPayload [ ] ,
280+ string ,
281+ {
282+ RTK_autoBatch : boolean
283+ requestId : string
284+ timestamp : number
285+ }
286+ > ,
287+ ) {
288+ for ( const entry of action . payload ) {
289+ const { endpointName, args, value } = entry
290+ const endpointDefinition = definitions [ endpointName ]
291+
292+ const arg : QueryThunkArg = {
293+ type : 'query' ,
294+ endpointName : endpointName ,
295+ originalArgs : entry . args ,
296+ queryCacheKey : serializeQueryArgs ( {
297+ queryArgs : args ,
298+ endpointDefinition,
299+ endpointName,
300+ } ) ,
301+ }
302+ writePendingCacheEntry ( draft , arg , true , {
303+ arg,
304+ requestId : action . meta . requestId ,
305+ startedTimeStamp : action . meta . timestamp ,
306+ } )
307+
308+ writeFulfilledCacheEntry (
309+ draft ,
310+ {
311+ arg,
312+ requestId : action . meta . requestId ,
313+ fulfilledTimeStamp : action . meta . timestamp ,
314+ baseQueryMeta : { } ,
315+ } ,
316+ entry . value ,
317+ )
318+ }
319+ } ,
320+ prepare : ( payload : NormalizedQueryUpsertEntryPayload [ ] ) => {
321+ const result = {
322+ payload,
323+ meta : {
324+ [ SHOULD_AUTOBATCH ] : true ,
325+ requestId : nanoid ( ) ,
326+ timestamp : Date . now ( ) ,
327+ } ,
328+ }
329+ return result
330+ } ,
331+ } ,
224332 queryResultPatched : {
225333 reducer (
226334 draft ,
0 commit comments