From 3e77381cfd89c6ee352aba72614babd0d617bf27 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Thu, 21 Mar 2024 23:25:40 +0100 Subject: [PATCH 1/5] fetchBaseQuery: expose extraOptions to prepareHeaders --- packages/toolkit/src/query/fetchBaseQuery.ts | 13 ++--- .../src/query/tests/fetchBaseQuery.test.tsx | 47 +++++++++++++++++++ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/packages/toolkit/src/query/fetchBaseQuery.ts b/packages/toolkit/src/query/fetchBaseQuery.ts index 89f9c68ad6..37f1fdd37f 100644 --- a/packages/toolkit/src/query/fetchBaseQuery.ts +++ b/packages/toolkit/src/query/fetchBaseQuery.ts @@ -105,14 +105,14 @@ function stripUndefined(obj: any) { return copy } -export type FetchBaseQueryArgs = { +export type FetchBaseQueryArgs = { baseUrl?: string prepareHeaders?: ( headers: Headers, api: Pick< BaseQueryApi, 'getState' | 'extra' | 'endpoint' | 'type' | 'forced' - > & { arg: string | FetchArgs }, + > & { arg: string | FetchArgs; extraOptions: ExtraOptions }, ) => MaybePromise fetchFn?: ( input: RequestInfo, @@ -188,7 +188,7 @@ export type FetchBaseQueryMeta = { request: Request; response?: Response } * @param {number} timeout * A number in milliseconds that represents the maximum time a request can take before timing out. */ -export function fetchBaseQuery({ +export function fetchBaseQuery({ baseUrl, prepareHeaders = (x) => x, fetchFn = defaultFetchFn, @@ -200,11 +200,11 @@ export function fetchBaseQuery({ responseHandler: globalResponseHandler, validateStatus: globalValidateStatus, ...baseFetchOptions -}: FetchBaseQueryArgs = {}): BaseQueryFn< +}: FetchBaseQueryArgs = {}): BaseQueryFn< string | FetchArgs, unknown, FetchBaseQueryError, - {}, + ExtraOptions, FetchBaseQueryMeta > { if (typeof fetch === 'undefined' && fetchFn === defaultFetchFn) { @@ -212,7 +212,7 @@ export function fetchBaseQuery({ 'Warning: `fetch` is not available. Please supply a custom `fetchFn` property to use `fetchBaseQuery` on SSR environments.', ) } - return async (arg, api) => { + return async (arg, api, extraOptions) => { const { getState, extra, endpoint, forced, type } = api let meta: FetchBaseQueryMeta | undefined let { @@ -248,6 +248,7 @@ export function fetchBaseQuery({ endpoint, forced, type, + extraOptions, })) || headers // Only set the content-type to json if appropriate. Will not be true for FormData, ArrayBuffer, Blob, etc. diff --git a/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx b/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx index e2446d50c2..90b5787c6b 100644 --- a/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx +++ b/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx @@ -2,6 +2,7 @@ import { createSlice } from '@reduxjs/toolkit' import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' import { headersToObject } from 'headers-polyfill' import { HttpResponse, delay, http } from 'msw' +// @ts-ignore import nodeFetch from 'node-fetch' import queryString from 'query-string' import { vi } from 'vitest' @@ -852,6 +853,52 @@ describe('fetchBaseQuery', () => { expect(_forced).toBe(true) expect(_extra).toBe(fakeAuth0Client) }) + + test('can be instantiated with a `ExtraOptions` generic and `extraOptions` will be available in `prepareHeaders', async () => { + const prepare = vitest.fn() + const baseQuery = fetchBaseQuery<{ foo?: string; bar?: number }>({ + prepareHeaders(headers, api) { + expectTypeOf(api.extraOptions).toEqualTypeOf<{ foo?: string; bar?: number }>() + prepare.call(undefined, arguments) + }, + }) + baseQuery('', commonBaseQueryApi, { foo: 'baz', bar: 5 }) + expect(prepare).toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ extraOptions: { foo: 'baz', bar: 5 } }) + ) + + // ensure types + createApi({ + baseQuery, + endpoints(build) { + return { + testQuery: build.query({ + query: () => ({ url: '/echo', headers: {} }), + extraOptions: { + foo: 'asd', + bar: 1, + // @ts-expect-error + baz: 5, + }, + }), + testMutation: build.mutation({ + query: () => ({ + url: '/echo', + method: 'POST', + credentials: 'omit', + }), + extraOptions: { + foo: 'qwe', + bar: 15, + // @ts-expect-error + baz: 5, + }, + }), + } + }, + }) + }) }) test('can pass `headers` into `fetchBaseQuery`', async () => { From 6ef362f4e74647870cd59f22a8afaf00059729aa Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Thu, 21 Mar 2024 23:47:38 +0100 Subject: [PATCH 2/5] fixup test --- packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx b/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx index 90b5787c6b..210695e2fa 100644 --- a/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx +++ b/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx @@ -859,10 +859,10 @@ describe('fetchBaseQuery', () => { const baseQuery = fetchBaseQuery<{ foo?: string; bar?: number }>({ prepareHeaders(headers, api) { expectTypeOf(api.extraOptions).toEqualTypeOf<{ foo?: string; bar?: number }>() - prepare.call(undefined, arguments) + prepare.apply(undefined, arguments) }, }) - baseQuery('', commonBaseQueryApi, { foo: 'baz', bar: 5 }) + baseQuery('http://example.com', commonBaseQueryApi, { foo: 'baz', bar: 5 }) expect(prepare).toHaveBeenCalledWith( expect.anything(), expect.objectContaining({ extraOptions: { foo: 'baz', bar: 5 } }) From 1918f13ae4a806d2c775d3c06531cabb8ff3eb5a Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Fri, 22 Mar 2024 00:07:21 +0100 Subject: [PATCH 3/5] fix bad inference with an overload? --- packages/toolkit/src/query/fetchBaseQuery.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/toolkit/src/query/fetchBaseQuery.ts b/packages/toolkit/src/query/fetchBaseQuery.ts index 37f1fdd37f..e701301506 100644 --- a/packages/toolkit/src/query/fetchBaseQuery.ts +++ b/packages/toolkit/src/query/fetchBaseQuery.ts @@ -188,6 +188,20 @@ export type FetchBaseQueryMeta = { request: Request; response?: Response } * @param {number} timeout * A number in milliseconds that represents the maximum time a request can take before timing out. */ +export function fetchBaseQuery(options?: FetchBaseQueryArgs<{}>): BaseQueryFn< +string | FetchArgs, +unknown, +FetchBaseQueryError, +{}, +FetchBaseQueryMeta +> +export function fetchBaseQuery(options?: FetchBaseQueryArgs): BaseQueryFn< +string | FetchArgs, +unknown, +FetchBaseQueryError, +ExtraOptions, +FetchBaseQueryMeta +> export function fetchBaseQuery({ baseUrl, prepareHeaders = (x) => x, From 41487fd8d436b1d05708a373308c6009675876a8 Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Mon, 14 Oct 2024 16:12:07 -0400 Subject: [PATCH 4/5] Fix arguments type --- .../src/query/tests/fetchBaseQuery.test.tsx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx b/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx index 210695e2fa..81aa17db31 100644 --- a/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx +++ b/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx @@ -858,14 +858,20 @@ describe('fetchBaseQuery', () => { const prepare = vitest.fn() const baseQuery = fetchBaseQuery<{ foo?: string; bar?: number }>({ prepareHeaders(headers, api) { - expectTypeOf(api.extraOptions).toEqualTypeOf<{ foo?: string; bar?: number }>() - prepare.apply(undefined, arguments) + expectTypeOf(api.extraOptions).toEqualTypeOf<{ + foo?: string + bar?: number + }>() + prepare.apply(undefined, arguments as unknown as any[]) }, }) - baseQuery('http://example.com', commonBaseQueryApi, { foo: 'baz', bar: 5 }) + baseQuery('http://example.com', commonBaseQueryApi, { + foo: 'baz', + bar: 5, + }) expect(prepare).toHaveBeenCalledWith( expect.anything(), - expect.objectContaining({ extraOptions: { foo: 'baz', bar: 5 } }) + expect.objectContaining({ extraOptions: { foo: 'baz', bar: 5 } }), ) // ensure types From 896e4dfa020115cd2b03f5fb360578f7d11c43b3 Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Mon, 14 Oct 2024 16:37:16 -0400 Subject: [PATCH 5/5] Drop generic and make extraOptions unknown --- packages/toolkit/src/query/fetchBaseQuery.ts | 25 +++++-------------- .../src/query/tests/fetchBaseQuery.test.tsx | 11 ++------ 2 files changed, 8 insertions(+), 28 deletions(-) diff --git a/packages/toolkit/src/query/fetchBaseQuery.ts b/packages/toolkit/src/query/fetchBaseQuery.ts index e701301506..19c679e339 100644 --- a/packages/toolkit/src/query/fetchBaseQuery.ts +++ b/packages/toolkit/src/query/fetchBaseQuery.ts @@ -105,14 +105,14 @@ function stripUndefined(obj: any) { return copy } -export type FetchBaseQueryArgs = { +export type FetchBaseQueryArgs = { baseUrl?: string prepareHeaders?: ( headers: Headers, api: Pick< BaseQueryApi, 'getState' | 'extra' | 'endpoint' | 'type' | 'forced' - > & { arg: string | FetchArgs; extraOptions: ExtraOptions }, + > & { arg: string | FetchArgs; extraOptions: unknown }, ) => MaybePromise fetchFn?: ( input: RequestInfo, @@ -188,21 +188,8 @@ export type FetchBaseQueryMeta = { request: Request; response?: Response } * @param {number} timeout * A number in milliseconds that represents the maximum time a request can take before timing out. */ -export function fetchBaseQuery(options?: FetchBaseQueryArgs<{}>): BaseQueryFn< -string | FetchArgs, -unknown, -FetchBaseQueryError, -{}, -FetchBaseQueryMeta -> -export function fetchBaseQuery(options?: FetchBaseQueryArgs): BaseQueryFn< -string | FetchArgs, -unknown, -FetchBaseQueryError, -ExtraOptions, -FetchBaseQueryMeta -> -export function fetchBaseQuery({ + +export function fetchBaseQuery({ baseUrl, prepareHeaders = (x) => x, fetchFn = defaultFetchFn, @@ -214,11 +201,11 @@ export function fetchBaseQuery({ responseHandler: globalResponseHandler, validateStatus: globalValidateStatus, ...baseFetchOptions -}: FetchBaseQueryArgs = {}): BaseQueryFn< +}: FetchBaseQueryArgs = {}): BaseQueryFn< string | FetchArgs, unknown, FetchBaseQueryError, - ExtraOptions, + {}, FetchBaseQueryMeta > { if (typeof fetch === 'undefined' && fetchFn === defaultFetchFn) { diff --git a/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx b/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx index 81aa17db31..3b70753318 100644 --- a/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx +++ b/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx @@ -856,12 +856,9 @@ describe('fetchBaseQuery', () => { test('can be instantiated with a `ExtraOptions` generic and `extraOptions` will be available in `prepareHeaders', async () => { const prepare = vitest.fn() - const baseQuery = fetchBaseQuery<{ foo?: string; bar?: number }>({ + const baseQuery = fetchBaseQuery({ prepareHeaders(headers, api) { - expectTypeOf(api.extraOptions).toEqualTypeOf<{ - foo?: string - bar?: number - }>() + expectTypeOf(api.extraOptions).toEqualTypeOf() prepare.apply(undefined, arguments as unknown as any[]) }, }) @@ -884,8 +881,6 @@ describe('fetchBaseQuery', () => { extraOptions: { foo: 'asd', bar: 1, - // @ts-expect-error - baz: 5, }, }), testMutation: build.mutation({ @@ -897,8 +892,6 @@ describe('fetchBaseQuery', () => { extraOptions: { foo: 'qwe', bar: 15, - // @ts-expect-error - baz: 5, }, }), }