source: node_modules/@reduxjs/toolkit/src/query/endpointDefinitions.ts@ a762898

Last change on this file since a762898 was a762898, checked in by istevanoska <ilinastevanoska@…>, 5 months ago

Added visualizations

  • Property mode set to 100644
File size: 46.6 KB
Line 
1import type { Api } from '@reduxjs/toolkit/query'
2import type { StandardSchemaV1 } from '@standard-schema/spec'
3import type {
4 BaseQueryApi,
5 BaseQueryArg,
6 BaseQueryError,
7 BaseQueryExtraOptions,
8 BaseQueryFn,
9 BaseQueryMeta,
10 BaseQueryResult,
11 QueryReturnValue,
12} from './baseQueryTypes'
13import type { CacheCollectionQueryExtraOptions } from './core/buildMiddleware/cacheCollection'
14import type {
15 CacheLifecycleInfiniteQueryExtraOptions,
16 CacheLifecycleMutationExtraOptions,
17 CacheLifecycleQueryExtraOptions,
18} from './core/buildMiddleware/cacheLifecycle'
19import type {
20 QueryLifecycleInfiniteQueryExtraOptions,
21 QueryLifecycleMutationExtraOptions,
22 QueryLifecycleQueryExtraOptions,
23} from './core/buildMiddleware/queryLifecycle'
24import type {
25 InfiniteData,
26 InfiniteQueryConfigOptions,
27 QuerySubState,
28 RootState,
29} from './core/index'
30import type { SerializeQueryArgs } from './defaultSerializeQueryArgs'
31import type { NEVER } from './fakeBaseQuery'
32import type {
33 CastAny,
34 HasRequiredProps,
35 MaybePromise,
36 NonUndefined,
37 OmitFromUnion,
38 UnwrapPromise,
39} from './tsHelpers'
40import { isNotNullish } from './utils'
41import type { NamedSchemaError } from './standardSchema'
42import { filterMap } from './utils/filterMap'
43
44const rawResultType = /* @__PURE__ */ Symbol()
45const resultType = /* @__PURE__ */ Symbol()
46const baseQuery = /* @__PURE__ */ Symbol()
47
48export interface SchemaFailureInfo {
49 endpoint: string
50 arg: any
51 type: 'query' | 'mutation'
52 queryCacheKey?: string
53}
54
55export type SchemaFailureHandler = (
56 error: NamedSchemaError,
57 info: SchemaFailureInfo,
58) => void
59
60export type SchemaFailureConverter<BaseQuery extends BaseQueryFn> = (
61 error: NamedSchemaError,
62 info: SchemaFailureInfo,
63) => BaseQueryError<BaseQuery>
64
65export type EndpointDefinitionWithQuery<
66 QueryArg,
67 BaseQuery extends BaseQueryFn,
68 ResultType,
69 RawResultType extends BaseQueryResult<BaseQuery>,
70> = {
71 /**
72 * `query` can be a function that returns either a `string` or an `object` which is passed to your `baseQuery`. If you are using [fetchBaseQuery](./fetchBaseQuery), this can return either a `string` or an `object` of properties in `FetchArgs`. If you use your own custom [`baseQuery`](../../rtk-query/usage/customizing-queries), you can customize this behavior to your liking.
73 *
74 * @example
75 *
76 * ```ts
77 * // codeblock-meta title="query example"
78 *
79 * import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
80 * interface Post {
81 * id: number
82 * name: string
83 * }
84 * type PostsResponse = Post[]
85 *
86 * const api = createApi({
87 * baseQuery: fetchBaseQuery({ baseUrl: '/' }),
88 * tagTypes: ['Post'],
89 * endpoints: (build) => ({
90 * getPosts: build.query<PostsResponse, void>({
91 * // highlight-start
92 * query: () => 'posts',
93 * // highlight-end
94 * }),
95 * addPost: build.mutation<Post, Partial<Post>>({
96 * // highlight-start
97 * query: (body) => ({
98 * url: `posts`,
99 * method: 'POST',
100 * body,
101 * }),
102 * // highlight-end
103 * invalidatesTags: [{ type: 'Post', id: 'LIST' }],
104 * }),
105 * })
106 * })
107 * ```
108 */
109 query(arg: QueryArg): BaseQueryArg<BaseQuery>
110 queryFn?: never
111 /**
112 * A function to manipulate the data returned by a query or mutation.
113 */
114 transformResponse?(
115 baseQueryReturnValue: RawResultType,
116 meta: BaseQueryMeta<BaseQuery>,
117 arg: QueryArg,
118 ): ResultType | Promise<ResultType>
119 /**
120 * A function to manipulate the data returned by a failed query or mutation.
121 */
122 transformErrorResponse?(
123 baseQueryReturnValue: BaseQueryError<BaseQuery>,
124 meta: BaseQueryMeta<BaseQuery>,
125 arg: QueryArg,
126 ): unknown
127
128 /**
129 * A schema for the result *before* it's passed to `transformResponse`.
130 *
131 * @example
132 * ```ts
133 * // codeblock-meta no-transpile
134 * import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
135 * import * as v from "valibot"
136 *
137 * const postSchema = v.object({ id: v.number(), name: v.string() })
138 * type Post = v.InferOutput<typeof postSchema>
139 *
140 * const api = createApi({
141 * baseQuery: fetchBaseQuery({ baseUrl: '/' }),
142 * endpoints: (build) => ({
143 * getPostName: build.query<Post, { id: number }>({
144 * query: ({ id }) => `/post/${id}`,
145 * rawResponseSchema: postSchema,
146 * transformResponse: (post) => post.name,
147 * }),
148 * })
149 * })
150 * ```
151 */
152 rawResponseSchema?: StandardSchemaV1<RawResultType>
153
154 /**
155 * A schema for the error object returned by the `query` or `queryFn`, *before* it's passed to `transformErrorResponse`.
156 *
157 * @example
158 * ```ts
159 * // codeblock-meta no-transpile
160 * import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
161 * import * as v from "valibot"
162 * import {customBaseQuery, baseQueryErrorSchema} from "./customBaseQuery"
163 *
164 * const api = createApi({
165 * baseQuery: customBaseQuery,
166 * endpoints: (build) => ({
167 * getPost: build.query<Post, { id: number }>({
168 * query: ({ id }) => `/post/${id}`,
169 * rawErrorResponseSchema: baseQueryErrorSchema,
170 * transformErrorResponse: (error) => error.data,
171 * }),
172 * })
173 * })
174 * ```
175 */
176 rawErrorResponseSchema?: StandardSchemaV1<BaseQueryError<BaseQuery>>
177}
178
179export type EndpointDefinitionWithQueryFn<
180 QueryArg,
181 BaseQuery extends BaseQueryFn,
182 ResultType,
183> = {
184 /**
185 * Can be used in place of `query` as an inline function that bypasses `baseQuery` completely for the endpoint.
186 *
187 * @example
188 * ```ts
189 * // codeblock-meta title="Basic queryFn example"
190 *
191 * import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
192 * interface Post {
193 * id: number
194 * name: string
195 * }
196 * type PostsResponse = Post[]
197 *
198 * const api = createApi({
199 * baseQuery: fetchBaseQuery({ baseUrl: '/' }),
200 * endpoints: (build) => ({
201 * getPosts: build.query<PostsResponse, void>({
202 * query: () => 'posts',
203 * }),
204 * flipCoin: build.query<'heads' | 'tails', void>({
205 * // highlight-start
206 * queryFn(arg, queryApi, extraOptions, baseQuery) {
207 * const randomVal = Math.random()
208 * if (randomVal < 0.45) {
209 * return { data: 'heads' }
210 * }
211 * if (randomVal < 0.9) {
212 * return { data: 'tails' }
213 * }
214 * return { error: { status: 500, statusText: 'Internal Server Error', data: "Coin landed on its edge!" } }
215 * }
216 * // highlight-end
217 * })
218 * })
219 * })
220 * ```
221 */
222 queryFn(
223 arg: QueryArg,
224 api: BaseQueryApi,
225 extraOptions: BaseQueryExtraOptions<BaseQuery>,
226 baseQuery: (arg: Parameters<BaseQuery>[0]) => ReturnType<BaseQuery>,
227 ): MaybePromise<
228 QueryReturnValue<
229 ResultType,
230 BaseQueryError<BaseQuery>,
231 BaseQueryMeta<BaseQuery>
232 >
233 >
234 query?: never
235 transformResponse?: never
236 transformErrorResponse?: never
237 rawResponseSchema?: never
238 rawErrorResponseSchema?: never
239}
240
241type BaseEndpointTypes<
242 QueryArg,
243 BaseQuery extends BaseQueryFn,
244 ResultType,
245 RawResultType,
246> = {
247 QueryArg: QueryArg
248 BaseQuery: BaseQuery
249 ResultType: ResultType
250 RawResultType: RawResultType
251}
252
253export type SchemaType =
254 | 'arg'
255 | 'rawResponse'
256 | 'response'
257 | 'rawErrorResponse'
258 | 'errorResponse'
259 | 'meta'
260
261interface CommonEndpointDefinition<
262 QueryArg,
263 BaseQuery extends BaseQueryFn,
264 ResultType,
265> {
266 /**
267 * A schema for the arguments to be passed to the `query` or `queryFn`.
268 *
269 * @example
270 * ```ts
271 * // codeblock-meta no-transpile
272 * import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
273 * import * as v from "valibot"
274 *
275 * const api = createApi({
276 * baseQuery: fetchBaseQuery({ baseUrl: '/' }),
277 * endpoints: (build) => ({
278 * getPost: build.query<Post, { id: number }>({
279 * query: ({ id }) => `/post/${id}`,
280 * argSchema: v.object({ id: v.number() }),
281 * }),
282 * })
283 * })
284 * ```
285 */
286 argSchema?: StandardSchemaV1<QueryArg>
287
288 /**
289 * A schema for the result (including `transformResponse` if provided).
290 *
291 * @example
292 * ```ts
293 * // codeblock-meta no-transpile
294 * import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
295 * import * as v from "valibot"
296 *
297 * const postSchema = v.object({ id: v.number(), name: v.string() })
298 * type Post = v.InferOutput<typeof postSchema>
299 *
300 * const api = createApi({
301 * baseQuery: fetchBaseQuery({ baseUrl: '/' }),
302 * endpoints: (build) => ({
303 * getPost: build.query<Post, { id: number }>({
304 * query: ({ id }) => `/post/${id}`,
305 * responseSchema: postSchema,
306 * }),
307 * })
308 * })
309 * ```
310 */
311 responseSchema?: StandardSchemaV1<ResultType>
312
313 /**
314 * A schema for the error object returned by the `query` or `queryFn` (including `transformErrorResponse` if provided).
315 *
316 * @example
317 * ```ts
318 * // codeblock-meta no-transpile
319 * import { createApi } from '@reduxjs/toolkit/query/react'
320 * import * as v from "valibot"
321 * import { customBaseQuery, baseQueryErrorSchema } from "./customBaseQuery"
322 *
323 * const api = createApi({
324 * baseQuery: customBaseQuery,
325 * endpoints: (build) => ({
326 * getPost: build.query<Post, { id: number }>({
327 * query: ({ id }) => `/post/${id}`,
328 * errorResponseSchema: baseQueryErrorSchema,
329 * }),
330 * })
331 * })
332 * ```
333 */
334 errorResponseSchema?: StandardSchemaV1<BaseQueryError<BaseQuery>>
335
336 /**
337 * A schema for the `meta` property returned by the `query` or `queryFn`.
338 *
339 * @example
340 * ```ts
341 * // codeblock-meta no-transpile
342 * import { createApi } from '@reduxjs/toolkit/query/react'
343 * import * as v from "valibot"
344 * import { customBaseQuery, baseQueryMetaSchema } from "./customBaseQuery"
345 *
346 * const api = createApi({
347 * baseQuery: customBaseQuery,
348 * endpoints: (build) => ({
349 * getPost: build.query<Post, { id: number }>({
350 * query: ({ id }) => `/post/${id}`,
351 * metaSchema: baseQueryMetaSchema,
352 * }),
353 * })
354 * })
355 * ```
356 */
357 metaSchema?: StandardSchemaV1<BaseQueryMeta<BaseQuery>>
358
359 /**
360 * Defaults to `true`.
361 *
362 * Most apps should leave this setting on. The only time it can be a performance issue
363 * is if an API returns extremely large amounts of data (e.g. 10,000 rows per request) and
364 * you're unable to paginate it.
365 *
366 * For details of how this works, please see the below. When it is set to `false`,
367 * every request will cause subscribed components to rerender, even when the data has not changed.
368 *
369 * @see https://redux-toolkit.js.org/api/other-exports#copywithstructuralsharing
370 */
371 structuralSharing?: boolean
372
373 /**
374 * A function that is called when a schema validation fails.
375 *
376 * Gets called with a `NamedSchemaError` and an object containing the endpoint name, the type of the endpoint, the argument passed to the endpoint, and the query cache key (if applicable).
377 *
378 * `NamedSchemaError` has the following properties:
379 * - `issues`: an array of issues that caused the validation to fail
380 * - `value`: the value that was passed to the schema
381 * - `schemaName`: the name of the schema that was used to validate the value (e.g. `argSchema`)
382 *
383 * @example
384 * ```ts
385 * // codeblock-meta no-transpile
386 * import { createApi } from '@reduxjs/toolkit/query/react'
387 * import * as v from "valibot"
388 *
389 * const api = createApi({
390 * baseQuery: fetchBaseQuery({ baseUrl: '/' }),
391 * endpoints: (build) => ({
392 * getPost: build.query<Post, { id: number }>({
393 * query: ({ id }) => `/post/${id}`,
394 * onSchemaFailure: (error, info) => {
395 * console.error(error, info)
396 * },
397 * }),
398 * })
399 * })
400 * ```
401 */
402 onSchemaFailure?: SchemaFailureHandler
403
404 /**
405 * Convert a schema validation failure into an error shape matching base query errors.
406 *
407 * When not provided, schema failures are treated as fatal, and normal error handling such as tag invalidation will not be executed.
408 *
409 * @example
410 * ```ts
411 * // codeblock-meta no-transpile
412 * import { createApi } from '@reduxjs/toolkit/query/react'
413 * import * as v from "valibot"
414 *
415 * const api = createApi({
416 * baseQuery: fetchBaseQuery({ baseUrl: '/' }),
417 * endpoints: (build) => ({
418 * getPost: build.query<Post, { id: number }>({
419 * query: ({ id }) => `/post/${id}`,
420 * responseSchema: v.object({ id: v.number(), name: v.string() }),
421 * catchSchemaFailure: (error, info) => ({
422 * status: "CUSTOM_ERROR",
423 * error: error.schemaName + " failed validation",
424 * data: error.issues,
425 * }),
426 * }),
427 * }),
428 * })
429 * ```
430 */
431 catchSchemaFailure?: SchemaFailureConverter<BaseQuery>
432
433 /**
434 * Defaults to `false`.
435 *
436 * If set to `true`, will skip schema validation for this endpoint.
437 * Overrides the global setting.
438 *
439 * Can be overridden for specific schemas by passing an array of schema types to skip.
440 *
441 * @example
442 * ```ts
443 * // codeblock-meta no-transpile
444 * import { createApi } from '@reduxjs/toolkit/query/react'
445 * import * as v from "valibot"
446 *
447 * const api = createApi({
448 * baseQuery: fetchBaseQuery({ baseUrl: '/' }),
449 * endpoints: (build) => ({
450 * getPost: build.query<Post, { id: number }>({
451 * query: ({ id }) => `/post/${id}`,
452 * responseSchema: v.object({ id: v.number(), name: v.string() }),
453 * skipSchemaValidation: process.env.NODE_ENV === "test" ? ["response"] : false, // skip schema validation for response in tests, since we'll be mocking the response
454 * }),
455 * })
456 * })
457 * ```
458 */
459 skipSchemaValidation?: boolean | SchemaType[]
460}
461
462export type BaseEndpointDefinition<
463 QueryArg,
464 BaseQuery extends BaseQueryFn,
465 ResultType,
466 RawResultType extends BaseQueryResult<BaseQuery> = BaseQueryResult<BaseQuery>,
467> = (
468 | ([CastAny<BaseQueryResult<BaseQuery>, {}>] extends [NEVER]
469 ? never
470 : EndpointDefinitionWithQuery<
471 QueryArg,
472 BaseQuery,
473 ResultType,
474 RawResultType
475 >)
476 | EndpointDefinitionWithQueryFn<QueryArg, BaseQuery, ResultType>
477) &
478 CommonEndpointDefinition<QueryArg, BaseQuery, ResultType> & {
479 /* phantom type */
480 [rawResultType]?: RawResultType
481 /* phantom type */
482 [resultType]?: ResultType
483 /* phantom type */
484 [baseQuery]?: BaseQuery
485 } & HasRequiredProps<
486 BaseQueryExtraOptions<BaseQuery>,
487 { extraOptions: BaseQueryExtraOptions<BaseQuery> },
488 { extraOptions?: BaseQueryExtraOptions<BaseQuery> }
489 >
490
491// NOTE As with QueryStatus in `apiState.ts`, don't use this for real comparisons
492// at runtime, use the string constants defined below.
493export enum DefinitionType {
494 query = 'query',
495 mutation = 'mutation',
496 infinitequery = 'infinitequery',
497}
498
499export const ENDPOINT_QUERY = DefinitionType.query
500export const ENDPOINT_MUTATION = DefinitionType.mutation
501export const ENDPOINT_INFINITEQUERY = DefinitionType.infinitequery
502
503type TagDescriptionArray<TagTypes extends string> = ReadonlyArray<
504 TagDescription<TagTypes> | undefined | null
505>
506
507export type GetResultDescriptionFn<
508 TagTypes extends string,
509 ResultType,
510 QueryArg,
511 ErrorType,
512 MetaType,
513> = (
514 result: ResultType | undefined,
515 error: ErrorType | undefined,
516 arg: QueryArg,
517 meta: MetaType,
518) => TagDescriptionArray<TagTypes>
519
520export type FullTagDescription<TagType> = {
521 type: TagType
522 id?: number | string
523}
524export type TagDescription<TagType> = TagType | FullTagDescription<TagType>
525
526/**
527 * @public
528 */
529export type ResultDescription<
530 TagTypes extends string,
531 ResultType,
532 QueryArg,
533 ErrorType,
534 MetaType,
535> =
536 | TagDescriptionArray<TagTypes>
537 | GetResultDescriptionFn<TagTypes, ResultType, QueryArg, ErrorType, MetaType>
538
539type QueryTypes<
540 QueryArg,
541 BaseQuery extends BaseQueryFn,
542 TagTypes extends string,
543 ResultType,
544 ReducerPath extends string = string,
545 RawResultType extends BaseQueryResult<BaseQuery> = BaseQueryResult<BaseQuery>,
546> = BaseEndpointTypes<QueryArg, BaseQuery, ResultType, RawResultType> & {
547 /**
548 * The endpoint definition type. To be used with some internal generic types.
549 * @example
550 * ```ts
551 * const useMyWrappedHook: UseQuery<typeof api.endpoints.query.Types.QueryDefinition> = ...
552 * ```
553 */
554 QueryDefinition: QueryDefinition<
555 QueryArg,
556 BaseQuery,
557 TagTypes,
558 ResultType,
559 ReducerPath
560 >
561 TagTypes: TagTypes
562 ReducerPath: ReducerPath
563}
564
565/**
566 * @public
567 */
568export interface QueryExtraOptions<
569 TagTypes extends string,
570 ResultType,
571 QueryArg,
572 BaseQuery extends BaseQueryFn,
573 ReducerPath extends string = string,
574 RawResultType extends BaseQueryResult<BaseQuery> = BaseQueryResult<BaseQuery>,
575> extends CacheLifecycleQueryExtraOptions<
576 ResultType,
577 QueryArg,
578 BaseQuery,
579 ReducerPath
580 >,
581 QueryLifecycleQueryExtraOptions<
582 ResultType,
583 QueryArg,
584 BaseQuery,
585 ReducerPath
586 >,
587 CacheCollectionQueryExtraOptions {
588 type: DefinitionType.query
589
590 /**
591 * Used by `query` endpoints. Determines which 'tag' is attached to the cached data returned by the query.
592 * Expects an array of tag type strings, an array of objects of tag types with ids, or a function that returns such an array.
593 * 1. `['Post']` - equivalent to `2`
594 * 2. `[{ type: 'Post' }]` - equivalent to `1`
595 * 3. `[{ type: 'Post', id: 1 }]`
596 * 4. `(result, error, arg) => ['Post']` - equivalent to `5`
597 * 5. `(result, error, arg) => [{ type: 'Post' }]` - equivalent to `4`
598 * 6. `(result, error, arg) => [{ type: 'Post', id: 1 }]`
599 *
600 * @example
601 *
602 * ```ts
603 * // codeblock-meta title="providesTags example"
604 *
605 * import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
606 * interface Post {
607 * id: number
608 * name: string
609 * }
610 * type PostsResponse = Post[]
611 *
612 * const api = createApi({
613 * baseQuery: fetchBaseQuery({ baseUrl: '/' }),
614 * tagTypes: ['Posts'],
615 * endpoints: (build) => ({
616 * getPosts: build.query<PostsResponse, void>({
617 * query: () => 'posts',
618 * // highlight-start
619 * providesTags: (result) =>
620 * result
621 * ? [
622 * ...result.map(({ id }) => ({ type: 'Posts' as const, id })),
623 * { type: 'Posts', id: 'LIST' },
624 * ]
625 * : [{ type: 'Posts', id: 'LIST' }],
626 * // highlight-end
627 * })
628 * })
629 * })
630 * ```
631 */
632 providesTags?: ResultDescription<
633 TagTypes,
634 ResultType,
635 QueryArg,
636 BaseQueryError<BaseQuery>,
637 BaseQueryMeta<BaseQuery>
638 >
639 /**
640 * Not to be used. A query should not invalidate tags in the cache.
641 */
642 invalidatesTags?: never
643
644 /**
645 * Can be provided to return a custom cache key value based on the query arguments.
646 *
647 * This is primarily intended for cases where a non-serializable value is passed as part of the query arg object and should be excluded from the cache key. It may also be used for cases where an endpoint should only have a single cache entry, such as an infinite loading / pagination implementation.
648 *
649 * Unlike the `createApi` version which can _only_ return a string, this per-endpoint option can also return an an object, number, or boolean. If it returns a string, that value will be used as the cache key directly. If it returns an object / number / boolean, that value will be passed to the built-in `defaultSerializeQueryArgs`. This simplifies the use case of stripping out args you don't want included in the cache key.
650 *
651 *
652 * @example
653 *
654 * ```ts
655 * // codeblock-meta title="serializeQueryArgs : exclude value"
656 *
657 * import { createApi, fetchBaseQuery, defaultSerializeQueryArgs } from '@reduxjs/toolkit/query/react'
658 * interface Post {
659 * id: number
660 * name: string
661 * }
662 *
663 * interface MyApiClient {
664 * fetchPost: (id: string) => Promise<Post>
665 * }
666 *
667 * createApi({
668 * baseQuery: fetchBaseQuery({ baseUrl: '/' }),
669 * endpoints: (build) => ({
670 * // Example: an endpoint with an API client passed in as an argument,
671 * // but only the item ID should be used as the cache key
672 * getPost: build.query<Post, { id: string; client: MyApiClient }>({
673 * queryFn: async ({ id, client }) => {
674 * const post = await client.fetchPost(id)
675 * return { data: post }
676 * },
677 * // highlight-start
678 * serializeQueryArgs: ({ queryArgs, endpointDefinition, endpointName }) => {
679 * const { id } = queryArgs
680 * // This can return a string, an object, a number, or a boolean.
681 * // If it returns an object, number or boolean, that value
682 * // will be serialized automatically via `defaultSerializeQueryArgs`
683 * return { id } // omit `client` from the cache key
684 *
685 * // Alternately, you can use `defaultSerializeQueryArgs` yourself:
686 * // return defaultSerializeQueryArgs({
687 * // endpointName,
688 * // queryArgs: { id },
689 * // endpointDefinition
690 * // })
691 * // Or create and return a string yourself:
692 * // return `getPost(${id})`
693 * },
694 * // highlight-end
695 * }),
696 * }),
697 *})
698 * ```
699 */
700 serializeQueryArgs?: SerializeQueryArgs<
701 QueryArg,
702 string | number | boolean | Record<any, any>
703 >
704
705 /**
706 * Can be provided to merge an incoming response value into the current cache data.
707 * If supplied, no automatic structural sharing will be applied - it's up to
708 * you to update the cache appropriately.
709 *
710 * Since RTKQ normally replaces cache entries with the new response, you will usually
711 * need to use this with the `serializeQueryArgs` or `forceRefetch` options to keep
712 * an existing cache entry so that it can be updated.
713 *
714 * Since this is wrapped with Immer, you may either mutate the `currentCacheValue` directly,
715 * or return a new value, but _not_ both at once.
716 *
717 * Will only be called if the existing `currentCacheData` is _not_ `undefined` - on first response,
718 * the cache entry will just save the response data directly.
719 *
720 * Useful if you don't want a new request to completely override the current cache value,
721 * maybe because you have manually updated it from another source and don't want those
722 * updates to get lost.
723 *
724 *
725 * @example
726 *
727 * ```ts
728 * // codeblock-meta title="merge: pagination"
729 *
730 * import { createApi, fetchBaseQuery, defaultSerializeQueryArgs } from '@reduxjs/toolkit/query/react'
731 * interface Post {
732 * id: number
733 * name: string
734 * }
735 *
736 * createApi({
737 * baseQuery: fetchBaseQuery({ baseUrl: '/' }),
738 * endpoints: (build) => ({
739 * listItems: build.query<string[], number>({
740 * query: (pageNumber) => `/listItems?page=${pageNumber}`,
741 * // Only have one cache entry because the arg always maps to one string
742 * serializeQueryArgs: ({ endpointName }) => {
743 * return endpointName
744 * },
745 * // Always merge incoming data to the cache entry
746 * merge: (currentCache, newItems) => {
747 * currentCache.push(...newItems)
748 * },
749 * // Refetch when the page arg changes
750 * forceRefetch({ currentArg, previousArg }) {
751 * return currentArg !== previousArg
752 * },
753 * }),
754 * }),
755 *})
756 * ```
757 */
758 merge?(
759 currentCacheData: ResultType,
760 responseData: ResultType,
761 otherArgs: {
762 arg: QueryArg
763 baseQueryMeta: BaseQueryMeta<BaseQuery>
764 requestId: string
765 fulfilledTimeStamp: number
766 },
767 ): ResultType | void
768
769 /**
770 * Check to see if the endpoint should force a refetch in cases where it normally wouldn't.
771 * This is primarily useful for "infinite scroll" / pagination use cases where
772 * RTKQ is keeping a single cache entry that is added to over time, in combination
773 * with `serializeQueryArgs` returning a fixed cache key and a `merge` callback
774 * set to add incoming data to the cache entry each time.
775 *
776 * @example
777 *
778 * ```ts
779 * // codeblock-meta title="forceRefresh: pagination"
780 *
781 * import { createApi, fetchBaseQuery, defaultSerializeQueryArgs } from '@reduxjs/toolkit/query/react'
782 * interface Post {
783 * id: number
784 * name: string
785 * }
786 *
787 * createApi({
788 * baseQuery: fetchBaseQuery({ baseUrl: '/' }),
789 * endpoints: (build) => ({
790 * listItems: build.query<string[], number>({
791 * query: (pageNumber) => `/listItems?page=${pageNumber}`,
792 * // Only have one cache entry because the arg always maps to one string
793 * serializeQueryArgs: ({ endpointName }) => {
794 * return endpointName
795 * },
796 * // Always merge incoming data to the cache entry
797 * merge: (currentCache, newItems) => {
798 * currentCache.push(...newItems)
799 * },
800 * // Refetch when the page arg changes
801 * forceRefetch({ currentArg, previousArg }) {
802 * return currentArg !== previousArg
803 * },
804 * }),
805 * }),
806 *})
807 * ```
808 */
809 forceRefetch?(params: {
810 currentArg: QueryArg | undefined
811 previousArg: QueryArg | undefined
812 state: RootState<any, any, string>
813 endpointState?: QuerySubState<any>
814 }): boolean
815
816 /**
817 * All of these are `undefined` at runtime, purely to be used in TypeScript declarations!
818 */
819 Types?: QueryTypes<
820 QueryArg,
821 BaseQuery,
822 TagTypes,
823 ResultType,
824 ReducerPath,
825 RawResultType
826 >
827}
828
829export type QueryDefinition<
830 QueryArg,
831 BaseQuery extends BaseQueryFn,
832 TagTypes extends string,
833 ResultType,
834 ReducerPath extends string = string,
835 RawResultType extends BaseQueryResult<BaseQuery> = BaseQueryResult<BaseQuery>,
836> = BaseEndpointDefinition<QueryArg, BaseQuery, ResultType, RawResultType> &
837 QueryExtraOptions<
838 TagTypes,
839 ResultType,
840 QueryArg,
841 BaseQuery,
842 ReducerPath,
843 RawResultType
844 >
845
846export type InfiniteQueryTypes<
847 QueryArg,
848 PageParam,
849 BaseQuery extends BaseQueryFn,
850 TagTypes extends string,
851 ResultType,
852 ReducerPath extends string = string,
853 RawResultType extends BaseQueryResult<BaseQuery> = BaseQueryResult<BaseQuery>,
854> = BaseEndpointTypes<QueryArg, BaseQuery, ResultType, RawResultType> & {
855 /**
856 * The endpoint definition type. To be used with some internal generic types.
857 * @example
858 * ```ts
859 * const useMyWrappedHook: UseQuery<typeof api.endpoints.query.Types.QueryDefinition> = ...
860 * ```
861 */
862 InfiniteQueryDefinition: InfiniteQueryDefinition<
863 QueryArg,
864 PageParam,
865 BaseQuery,
866 TagTypes,
867 ResultType,
868 ReducerPath
869 >
870 TagTypes: TagTypes
871 ReducerPath: ReducerPath
872}
873
874export interface InfiniteQueryExtraOptions<
875 TagTypes extends string,
876 ResultType,
877 QueryArg,
878 PageParam,
879 BaseQuery extends BaseQueryFn,
880 ReducerPath extends string = string,
881 RawResultType extends BaseQueryResult<BaseQuery> = BaseQueryResult<BaseQuery>,
882> extends CacheLifecycleInfiniteQueryExtraOptions<
883 InfiniteData<ResultType, PageParam>,
884 QueryArg,
885 BaseQuery,
886 ReducerPath
887 >,
888 QueryLifecycleInfiniteQueryExtraOptions<
889 InfiniteData<ResultType, PageParam>,
890 QueryArg,
891 BaseQuery,
892 ReducerPath
893 >,
894 CacheCollectionQueryExtraOptions {
895 type: DefinitionType.infinitequery
896
897 providesTags?: ResultDescription<
898 TagTypes,
899 InfiniteData<ResultType, PageParam>,
900 QueryArg,
901 BaseQueryError<BaseQuery>,
902 BaseQueryMeta<BaseQuery>
903 >
904 /**
905 * Not to be used. A query should not invalidate tags in the cache.
906 */
907 invalidatesTags?: never
908
909 /**
910 * Required options to configure the infinite query behavior.
911 * `initialPageParam` and `getNextPageParam` are required, to
912 * ensure the infinite query can properly fetch the next page of data.
913 * `initialPageParam` may be specified when using the
914 * endpoint, to override the default value.
915 * `maxPages` and `getPreviousPageParam` are both optional.
916 *
917 * @example
918 *
919 * ```ts
920 * // codeblock-meta title="infiniteQueryOptions example"
921 * import { createApi, fetchBaseQuery, defaultSerializeQueryArgs } from '@reduxjs/toolkit/query/react'
922 *
923 * type Pokemon = {
924 * id: string
925 * name: string
926 * }
927 *
928 * const pokemonApi = createApi({
929 * baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }),
930 * endpoints: (build) => ({
931 * getInfinitePokemonWithMax: build.infiniteQuery<Pokemon[], string, number>({
932 * infiniteQueryOptions: {
933 * initialPageParam: 0,
934 * maxPages: 3,
935 * getNextPageParam: (lastPage, allPages, lastPageParam, allPageParams) =>
936 * lastPageParam + 1,
937 * getPreviousPageParam: (
938 * firstPage,
939 * allPages,
940 * firstPageParam,
941 * allPageParams,
942 * ) => {
943 * return firstPageParam > 0 ? firstPageParam - 1 : undefined
944 * },
945 * },
946 * query({pageParam}) {
947 * return `https://example.com/listItems?page=${pageParam}`
948 * },
949 * }),
950 * }),
951 * })
952
953 * ```
954 */
955 infiniteQueryOptions: InfiniteQueryConfigOptions<
956 ResultType,
957 PageParam,
958 QueryArg
959 >
960
961 /**
962 * Can be provided to return a custom cache key value based on the query arguments.
963 *
964 * This is primarily intended for cases where a non-serializable value is passed as part of the query arg object and should be excluded from the cache key. It may also be used for cases where an endpoint should only have a single cache entry, such as an infinite loading / pagination implementation.
965 *
966 * Unlike the `createApi` version which can _only_ return a string, this per-endpoint option can also return an an object, number, or boolean. If it returns a string, that value will be used as the cache key directly. If it returns an object / number / boolean, that value will be passed to the built-in `defaultSerializeQueryArgs`. This simplifies the use case of stripping out args you don't want included in the cache key.
967 *
968 *
969 * @example
970 *
971 * ```ts
972 * // codeblock-meta title="serializeQueryArgs : exclude value"
973 *
974 * import { createApi, fetchBaseQuery, defaultSerializeQueryArgs } from '@reduxjs/toolkit/query/react'
975 * interface Post {
976 * id: number
977 * name: string
978 * }
979 *
980 * interface MyApiClient {
981 * fetchPost: (id: string) => Promise<Post>
982 * }
983 *
984 * createApi({
985 * baseQuery: fetchBaseQuery({ baseUrl: '/' }),
986 * endpoints: (build) => ({
987 * // Example: an endpoint with an API client passed in as an argument,
988 * // but only the item ID should be used as the cache key
989 * getPost: build.query<Post, { id: string; client: MyApiClient }>({
990 * queryFn: async ({ id, client }) => {
991 * const post = await client.fetchPost(id)
992 * return { data: post }
993 * },
994 * // highlight-start
995 * serializeQueryArgs: ({ queryArgs, endpointDefinition, endpointName }) => {
996 * const { id } = queryArgs
997 * // This can return a string, an object, a number, or a boolean.
998 * // If it returns an object, number or boolean, that value
999 * // will be serialized automatically via `defaultSerializeQueryArgs`
1000 * return { id } // omit `client` from the cache key
1001 *
1002 * // Alternately, you can use `defaultSerializeQueryArgs` yourself:
1003 * // return defaultSerializeQueryArgs({
1004 * // endpointName,
1005 * // queryArgs: { id },
1006 * // endpointDefinition
1007 * // })
1008 * // Or create and return a string yourself:
1009 * // return `getPost(${id})`
1010 * },
1011 * // highlight-end
1012 * }),
1013 * }),
1014 *})
1015 * ```
1016 */
1017 serializeQueryArgs?: SerializeQueryArgs<
1018 QueryArg,
1019 string | number | boolean | Record<any, any>
1020 >
1021
1022 /**
1023 * All of these are `undefined` at runtime, purely to be used in TypeScript declarations!
1024 */
1025 Types?: InfiniteQueryTypes<
1026 QueryArg,
1027 PageParam,
1028 BaseQuery,
1029 TagTypes,
1030 ResultType,
1031 ReducerPath,
1032 RawResultType
1033 >
1034}
1035
1036export type InfiniteQueryDefinition<
1037 QueryArg,
1038 PageParam,
1039 BaseQuery extends BaseQueryFn,
1040 TagTypes extends string,
1041 ResultType,
1042 ReducerPath extends string = string,
1043 RawResultType extends BaseQueryResult<BaseQuery> = BaseQueryResult<BaseQuery>,
1044> =
1045 // Infinite query endpoints receive `{queryArg, pageParam}`
1046 BaseEndpointDefinition<
1047 InfiniteQueryCombinedArg<QueryArg, PageParam>,
1048 BaseQuery,
1049 ResultType,
1050 RawResultType
1051 > &
1052 InfiniteQueryExtraOptions<
1053 TagTypes,
1054 ResultType,
1055 QueryArg,
1056 PageParam,
1057 BaseQuery,
1058 ReducerPath,
1059 RawResultType
1060 >
1061
1062type MutationTypes<
1063 QueryArg,
1064 BaseQuery extends BaseQueryFn,
1065 TagTypes extends string,
1066 ResultType,
1067 ReducerPath extends string = string,
1068 RawResultType extends BaseQueryResult<BaseQuery> = BaseQueryResult<BaseQuery>,
1069> = BaseEndpointTypes<QueryArg, BaseQuery, ResultType, RawResultType> & {
1070 /**
1071 * The endpoint definition type. To be used with some internal generic types.
1072 * @example
1073 * ```ts
1074 * const useMyWrappedHook: UseMutation<typeof api.endpoints.query.Types.MutationDefinition> = ...
1075 * ```
1076 */
1077 MutationDefinition: MutationDefinition<
1078 QueryArg,
1079 BaseQuery,
1080 TagTypes,
1081 ResultType,
1082 ReducerPath
1083 >
1084 TagTypes: TagTypes
1085 ReducerPath: ReducerPath
1086}
1087
1088/**
1089 * @public
1090 */
1091export interface MutationExtraOptions<
1092 TagTypes extends string,
1093 ResultType,
1094 QueryArg,
1095 BaseQuery extends BaseQueryFn,
1096 ReducerPath extends string = string,
1097 RawResultType extends BaseQueryResult<BaseQuery> = BaseQueryResult<BaseQuery>,
1098> extends CacheLifecycleMutationExtraOptions<
1099 ResultType,
1100 QueryArg,
1101 BaseQuery,
1102 ReducerPath
1103 >,
1104 QueryLifecycleMutationExtraOptions<
1105 ResultType,
1106 QueryArg,
1107 BaseQuery,
1108 ReducerPath
1109 > {
1110 type: DefinitionType.mutation
1111
1112 /**
1113 * Used by `mutation` endpoints. Determines which cached data should be either re-fetched or removed from the cache.
1114 * Expects the same shapes as `providesTags`.
1115 *
1116 * @example
1117 *
1118 * ```ts
1119 * // codeblock-meta title="invalidatesTags example"
1120 * import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
1121 * interface Post {
1122 * id: number
1123 * name: string
1124 * }
1125 * type PostsResponse = Post[]
1126 *
1127 * const api = createApi({
1128 * baseQuery: fetchBaseQuery({ baseUrl: '/' }),
1129 * tagTypes: ['Posts'],
1130 * endpoints: (build) => ({
1131 * getPosts: build.query<PostsResponse, void>({
1132 * query: () => 'posts',
1133 * providesTags: (result) =>
1134 * result
1135 * ? [
1136 * ...result.map(({ id }) => ({ type: 'Posts' as const, id })),
1137 * { type: 'Posts', id: 'LIST' },
1138 * ]
1139 * : [{ type: 'Posts', id: 'LIST' }],
1140 * }),
1141 * addPost: build.mutation<Post, Partial<Post>>({
1142 * query(body) {
1143 * return {
1144 * url: `posts`,
1145 * method: 'POST',
1146 * body,
1147 * }
1148 * },
1149 * // highlight-start
1150 * invalidatesTags: [{ type: 'Posts', id: 'LIST' }],
1151 * // highlight-end
1152 * }),
1153 * })
1154 * })
1155 * ```
1156 */
1157 invalidatesTags?: ResultDescription<
1158 TagTypes,
1159 ResultType,
1160 QueryArg,
1161 BaseQueryError<BaseQuery>,
1162 BaseQueryMeta<BaseQuery>
1163 >
1164 /**
1165 * Not to be used. A mutation should not provide tags to the cache.
1166 */
1167 providesTags?: never
1168
1169 /**
1170 * All of these are `undefined` at runtime, purely to be used in TypeScript declarations!
1171 */
1172 Types?: MutationTypes<
1173 QueryArg,
1174 BaseQuery,
1175 TagTypes,
1176 ResultType,
1177 ReducerPath,
1178 RawResultType
1179 >
1180}
1181
1182export type MutationDefinition<
1183 QueryArg,
1184 BaseQuery extends BaseQueryFn,
1185 TagTypes extends string,
1186 ResultType,
1187 ReducerPath extends string = string,
1188 RawResultType extends BaseQueryResult<BaseQuery> = BaseQueryResult<BaseQuery>,
1189> = BaseEndpointDefinition<QueryArg, BaseQuery, ResultType, RawResultType> &
1190 MutationExtraOptions<
1191 TagTypes,
1192 ResultType,
1193 QueryArg,
1194 BaseQuery,
1195 ReducerPath,
1196 RawResultType
1197 >
1198
1199export type EndpointDefinition<
1200 QueryArg,
1201 BaseQuery extends BaseQueryFn,
1202 TagTypes extends string,
1203 ResultType,
1204 ReducerPath extends string = string,
1205 PageParam = any,
1206 RawResultType extends BaseQueryResult<BaseQuery> = BaseQueryResult<BaseQuery>,
1207> =
1208 | QueryDefinition<
1209 QueryArg,
1210 BaseQuery,
1211 TagTypes,
1212 ResultType,
1213 ReducerPath,
1214 RawResultType
1215 >
1216 | MutationDefinition<
1217 QueryArg,
1218 BaseQuery,
1219 TagTypes,
1220 ResultType,
1221 ReducerPath,
1222 RawResultType
1223 >
1224 | InfiniteQueryDefinition<
1225 QueryArg,
1226 PageParam,
1227 BaseQuery,
1228 TagTypes,
1229 ResultType,
1230 ReducerPath,
1231 RawResultType
1232 >
1233
1234export type EndpointDefinitions = Record<
1235 string,
1236 EndpointDefinition<any, any, any, any, any, any, any>
1237>
1238
1239export function isQueryDefinition(
1240 e: EndpointDefinition<any, any, any, any, any, any, any>,
1241): e is QueryDefinition<any, any, any, any, any, any> {
1242 return e.type === ENDPOINT_QUERY
1243}
1244
1245export function isMutationDefinition(
1246 e: EndpointDefinition<any, any, any, any, any, any, any>,
1247): e is MutationDefinition<any, any, any, any, any, any> {
1248 return e.type === ENDPOINT_MUTATION
1249}
1250
1251export function isInfiniteQueryDefinition(
1252 e: EndpointDefinition<any, any, any, any, any, any, any>,
1253): e is InfiniteQueryDefinition<any, any, any, any, any, any, any> {
1254 return e.type === ENDPOINT_INFINITEQUERY
1255}
1256
1257export function isAnyQueryDefinition(
1258 e: EndpointDefinition<any, any, any, any>,
1259): e is
1260 | QueryDefinition<any, any, any, any>
1261 | InfiniteQueryDefinition<any, any, any, any, any> {
1262 return isQueryDefinition(e) || isInfiniteQueryDefinition(e)
1263}
1264
1265export type EndpointBuilder<
1266 BaseQuery extends BaseQueryFn,
1267 TagTypes extends string,
1268 ReducerPath extends string,
1269> = {
1270 /**
1271 * An endpoint definition that retrieves data, and may provide tags to the cache.
1272 *
1273 * @example
1274 * ```js
1275 * // codeblock-meta title="Example of all query endpoint options"
1276 * const api = createApi({
1277 * baseQuery,
1278 * endpoints: (build) => ({
1279 * getPost: build.query({
1280 * query: (id) => ({ url: `post/${id}` }),
1281 * // Pick out data and prevent nested properties in a hook or selector
1282 * transformResponse: (response) => response.data,
1283 * // Pick out error and prevent nested properties in a hook or selector
1284 * transformErrorResponse: (response) => response.error,
1285 * // `result` is the server response
1286 * providesTags: (result, error, id) => [{ type: 'Post', id }],
1287 * // trigger side effects or optimistic updates
1288 * onQueryStarted(id, { dispatch, getState, extra, requestId, queryFulfilled, getCacheEntry, updateCachedData }) {},
1289 * // handle subscriptions etc
1290 * onCacheEntryAdded(id, { dispatch, getState, extra, requestId, cacheEntryRemoved, cacheDataLoaded, getCacheEntry, updateCachedData }) {},
1291 * }),
1292 * }),
1293 *});
1294 *```
1295 */
1296 query<
1297 ResultType,
1298 QueryArg,
1299 RawResultType extends
1300 BaseQueryResult<BaseQuery> = BaseQueryResult<BaseQuery>,
1301 >(
1302 definition: OmitFromUnion<
1303 QueryDefinition<
1304 QueryArg,
1305 BaseQuery,
1306 TagTypes,
1307 ResultType,
1308 ReducerPath,
1309 RawResultType
1310 >,
1311 'type'
1312 >,
1313 ): QueryDefinition<
1314 QueryArg,
1315 BaseQuery,
1316 TagTypes,
1317 ResultType,
1318 ReducerPath,
1319 RawResultType
1320 >
1321
1322 /**
1323 * An endpoint definition that alters data on the server or will possibly invalidate the cache.
1324 *
1325 * @example
1326 * ```js
1327 * // codeblock-meta title="Example of all mutation endpoint options"
1328 * const api = createApi({
1329 * baseQuery,
1330 * endpoints: (build) => ({
1331 * updatePost: build.mutation({
1332 * query: ({ id, ...patch }) => ({ url: `post/${id}`, method: 'PATCH', body: patch }),
1333 * // Pick out data and prevent nested properties in a hook or selector
1334 * transformResponse: (response) => response.data,
1335 * // Pick out error and prevent nested properties in a hook or selector
1336 * transformErrorResponse: (response) => response.error,
1337 * // `result` is the server response
1338 * invalidatesTags: (result, error, id) => [{ type: 'Post', id }],
1339 * // trigger side effects or optimistic updates
1340 * onQueryStarted(id, { dispatch, getState, extra, requestId, queryFulfilled, getCacheEntry }) {},
1341 * // handle subscriptions etc
1342 * onCacheEntryAdded(id, { dispatch, getState, extra, requestId, cacheEntryRemoved, cacheDataLoaded, getCacheEntry }) {},
1343 * }),
1344 * }),
1345 * });
1346 * ```
1347 */
1348 mutation<
1349 ResultType,
1350 QueryArg,
1351 RawResultType extends
1352 BaseQueryResult<BaseQuery> = BaseQueryResult<BaseQuery>,
1353 >(
1354 definition: OmitFromUnion<
1355 MutationDefinition<
1356 QueryArg,
1357 BaseQuery,
1358 TagTypes,
1359 ResultType,
1360 ReducerPath,
1361 RawResultType
1362 >,
1363 'type'
1364 >,
1365 ): MutationDefinition<
1366 QueryArg,
1367 BaseQuery,
1368 TagTypes,
1369 ResultType,
1370 ReducerPath,
1371 RawResultType
1372 >
1373
1374 infiniteQuery<
1375 ResultType,
1376 QueryArg,
1377 PageParam,
1378 RawResultType extends
1379 BaseQueryResult<BaseQuery> = BaseQueryResult<BaseQuery>,
1380 >(
1381 definition: OmitFromUnion<
1382 InfiniteQueryDefinition<
1383 QueryArg,
1384 PageParam,
1385 BaseQuery,
1386 TagTypes,
1387 ResultType,
1388 ReducerPath,
1389 RawResultType
1390 >,
1391 'type'
1392 >,
1393 ): InfiniteQueryDefinition<
1394 QueryArg,
1395 PageParam,
1396 BaseQuery,
1397 TagTypes,
1398 ResultType,
1399 ReducerPath,
1400 RawResultType
1401 >
1402}
1403
1404export type AssertTagTypes = <T extends FullTagDescription<string>>(t: T) => T
1405
1406export function calculateProvidedBy<ResultType, QueryArg, ErrorType, MetaType>(
1407 description:
1408 | ResultDescription<string, ResultType, QueryArg, ErrorType, MetaType>
1409 | undefined,
1410 result: ResultType | undefined,
1411 error: ErrorType | undefined,
1412 queryArg: QueryArg,
1413 meta: MetaType | undefined,
1414 assertTagTypes: AssertTagTypes,
1415): readonly FullTagDescription<string>[] {
1416 const finalDescription = isFunction(description)
1417 ? description(
1418 result as ResultType,
1419 error as undefined,
1420 queryArg,
1421 meta as MetaType,
1422 )
1423 : description
1424
1425 if (finalDescription) {
1426 return filterMap(finalDescription, isNotNullish, (tag) =>
1427 assertTagTypes(expandTagDescription(tag)),
1428 )
1429 }
1430
1431 return []
1432}
1433
1434function isFunction<T>(t: T): t is Extract<T, Function> {
1435 return typeof t === 'function'
1436}
1437
1438export function expandTagDescription(
1439 description: TagDescription<string>,
1440): FullTagDescription<string> {
1441 return typeof description === 'string' ? { type: description } : description
1442}
1443
1444export type QueryArgFrom<D extends BaseEndpointDefinition<any, any, any, any>> =
1445 D extends BaseEndpointDefinition<infer QA, any, any, any> ? QA : never
1446
1447// Just extracting `QueryArg` from `BaseEndpointDefinition`
1448// doesn't sufficiently match here.
1449// We need to explicitly match against `InfiniteQueryDefinition`
1450export type InfiniteQueryArgFrom<
1451 D extends BaseEndpointDefinition<any, any, any, any>,
1452> =
1453 D extends InfiniteQueryDefinition<infer QA, any, any, any, any, any, any>
1454 ? QA
1455 : never
1456
1457export type QueryArgFromAnyQuery<
1458 D extends BaseEndpointDefinition<any, any, any, any>,
1459> =
1460 D extends InfiniteQueryDefinition<any, any, any, any, any, any, any>
1461 ? InfiniteQueryArgFrom<D>
1462 : D extends QueryDefinition<any, any, any, any, any, any>
1463 ? QueryArgFrom<D>
1464 : never
1465
1466export type ResultTypeFrom<
1467 D extends BaseEndpointDefinition<any, any, any, any>,
1468> = D extends BaseEndpointDefinition<any, any, infer RT, any> ? RT : unknown
1469
1470export type ReducerPathFrom<
1471 D extends EndpointDefinition<any, any, any, any, any, any, any>,
1472> =
1473 D extends EndpointDefinition<any, any, any, any, infer RP, any, any>
1474 ? RP
1475 : unknown
1476
1477export type TagTypesFrom<
1478 D extends EndpointDefinition<any, any, any, any, any, any, any>,
1479> =
1480 D extends EndpointDefinition<any, any, infer TT, any, any, any, any>
1481 ? TT
1482 : unknown
1483
1484export type PageParamFrom<
1485 D extends InfiniteQueryDefinition<any, any, any, any, any, any, any>,
1486> =
1487 D extends InfiniteQueryDefinition<any, infer PP, any, any, any, any, any>
1488 ? PP
1489 : unknown
1490
1491export type InfiniteQueryCombinedArg<QueryArg, PageParam> = {
1492 queryArg: QueryArg
1493 pageParam: PageParam
1494}
1495
1496export type TagTypesFromApi<T> =
1497 T extends Api<any, any, any, infer TagTypes> ? TagTypes : never
1498
1499export type DefinitionsFromApi<T> =
1500 T extends Api<any, infer Definitions, any, any> ? Definitions : never
1501
1502export type TransformedResponse<
1503 NewDefinitions extends EndpointDefinitions,
1504 K,
1505 ResultType,
1506> = K extends keyof NewDefinitions
1507 ? NewDefinitions[K]['transformResponse'] extends undefined
1508 ? ResultType
1509 : UnwrapPromise<
1510 ReturnType<NonUndefined<NewDefinitions[K]['transformResponse']>>
1511 >
1512 : ResultType
1513
1514export type OverrideResultType<Definition, NewResultType> =
1515 Definition extends QueryDefinition<
1516 infer QueryArg,
1517 infer BaseQuery,
1518 infer TagTypes,
1519 any,
1520 infer ReducerPath
1521 >
1522 ? QueryDefinition<QueryArg, BaseQuery, TagTypes, NewResultType, ReducerPath>
1523 : Definition extends MutationDefinition<
1524 infer QueryArg,
1525 infer BaseQuery,
1526 infer TagTypes,
1527 any,
1528 infer ReducerPath
1529 >
1530 ? MutationDefinition<
1531 QueryArg,
1532 BaseQuery,
1533 TagTypes,
1534 NewResultType,
1535 ReducerPath
1536 >
1537 : Definition extends InfiniteQueryDefinition<
1538 infer QueryArg,
1539 infer PageParam,
1540 infer BaseQuery,
1541 infer TagTypes,
1542 any,
1543 infer ReducerPath
1544 >
1545 ? InfiniteQueryDefinition<
1546 QueryArg,
1547 PageParam,
1548 BaseQuery,
1549 TagTypes,
1550 NewResultType,
1551 ReducerPath
1552 >
1553 : never
1554
1555export type UpdateDefinitions<
1556 Definitions extends EndpointDefinitions,
1557 NewTagTypes extends string,
1558 NewDefinitions extends EndpointDefinitions,
1559> = {
1560 [K in keyof Definitions]: Definitions[K] extends QueryDefinition<
1561 infer QueryArg,
1562 infer BaseQuery,
1563 any,
1564 infer ResultType,
1565 infer ReducerPath
1566 >
1567 ? QueryDefinition<
1568 QueryArg,
1569 BaseQuery,
1570 NewTagTypes,
1571 TransformedResponse<NewDefinitions, K, ResultType>,
1572 ReducerPath
1573 >
1574 : Definitions[K] extends MutationDefinition<
1575 infer QueryArg,
1576 infer BaseQuery,
1577 any,
1578 infer ResultType,
1579 infer ReducerPath
1580 >
1581 ? MutationDefinition<
1582 QueryArg,
1583 BaseQuery,
1584 NewTagTypes,
1585 TransformedResponse<NewDefinitions, K, ResultType>,
1586 ReducerPath
1587 >
1588 : Definitions[K] extends InfiniteQueryDefinition<
1589 infer QueryArg,
1590 infer PageParam,
1591 infer BaseQuery,
1592 any,
1593 infer ResultType,
1594 infer ReducerPath
1595 >
1596 ? InfiniteQueryDefinition<
1597 QueryArg,
1598 PageParam,
1599 BaseQuery,
1600 NewTagTypes,
1601 TransformedResponse<NewDefinitions, K, ResultType>,
1602 ReducerPath
1603 >
1604 : never
1605}
Note: See TracBrowser for help on using the repository browser.