Skip to content

Commit e870202

Browse files
authored
Merge pull request #421 from OpenAPI-Qraft/feat/optional-parameters-for-the-query-fn
feat: allow query-fn options without parameters when all operation params are optional
2 parents 78e3403 + f43bc5c commit e870202

9 files changed

Lines changed: 76 additions & 36 deletions

File tree

.changeset/cold-pets-design.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@openapi-qraft/tanstack-query-react-plugin': minor
3+
'@openapi-qraft/tanstack-query-react-types': minor
4+
'@openapi-qraft/react': minor
5+
---
6+
7+
When an operation has only optional parameters, the imperative operation function now accepts `QueryFnOptions` (e.g. `signal`, `meta`) without requiring a `parameters` argument. This matches how optional request fields are already handled for hooks and improves typing for direct `qraft.<service>.<operation>(…)` calls.

packages/react-client/src/tests/qraftAPIClient.test.tsx

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2172,21 +2172,55 @@ describe('Qraft uses Operation Query Function', () => {
21722172
);
21732173
});
21742174

2175-
it('uses Operation Query without arguments', async () => {
2176-
const { qraft } = createClient();
2175+
describe('uses Operation Query without arguments', () => {
2176+
it('uses Operation Query without invoke options', async () => {
2177+
const { qraft } = createClient();
21772178

2178-
const { data, error } = await qraft.files.findAll();
2179+
const { data, error } = await qraft.files.findAll();
21792180

2180-
expect(
2181-
error satisfies
2182-
| Services['files']['findAll']['types']['error']
2183-
| Error
2184-
| undefined
2185-
).toBeUndefined();
2181+
expect(
2182+
error satisfies
2183+
| Services['files']['findAll']['types']['error']
2184+
| Error
2185+
| undefined
2186+
).toBeUndefined();
21862187

2187-
expect(
2188-
data satisfies Services['files']['findAll']['types']['data'] | undefined
2189-
).toEqual(filesFindAllResponsePayloadFixtures);
2188+
expect(
2189+
data satisfies Services['files']['findAll']['types']['data'] | undefined
2190+
).toEqual(filesFindAllResponsePayloadFixtures);
2191+
});
2192+
2193+
it('uses Operation Query with `signal` without `parameters`', async () => {
2194+
const { qraft } = createClient();
2195+
2196+
const requestFnSpy = vi.fn(requestFn) as typeof requestFn;
2197+
2198+
const controller = new AbortController();
2199+
const signal = controller.signal;
2200+
2201+
const { data, error } = await qraft.files.findAll(
2202+
{ signal },
2203+
requestFnSpy
2204+
);
2205+
2206+
expect(
2207+
error satisfies
2208+
| Services['files']['findAll']['types']['error']
2209+
| Error
2210+
| undefined
2211+
).toBeUndefined();
2212+
2213+
expect(
2214+
data satisfies Services['files']['findAll']['types']['data'] | undefined
2215+
).toEqual(filesFindAllResponsePayloadFixtures);
2216+
2217+
expect(requestFnSpy).toHaveBeenCalledWith(
2218+
qraft.files.findAll.schema,
2219+
expect.objectContaining({
2220+
signal,
2221+
})
2222+
);
2223+
});
21902224
});
21912225

21922226
it('uses Operation Query with `queryKey`', async () => {

packages/tanstack-query-react-plugin/src/__snapshots__/explicit-import-extensions/services/FilesService.ts.snapshot.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55

66
import type { paths } from "../../openapi.js";
7-
import type { DeepReadonly, InvalidateQueryFilters, MutationFiltersByMutationKey, MutationFiltersByParameters, MutationVariables, OperationError, OperationInfiniteData, PartialParameters, QueryFiltersByParameters, QueryFiltersByQueryKey, QueryFnOptionsByParameters, QueryFnOptionsByQueryKey, RequestFnResponse, ServiceOperationEnsureInfiniteQueryDataOptions, ServiceOperationEnsureQueryDataOptions, ServiceOperationFetchInfiniteQueryOptions, ServiceOperationFetchQueryOptions, ServiceOperationInfiniteQueryKey, ServiceOperationMutationFnOptions, ServiceOperationMutationKey, ServiceOperationQueryKey, ServiceOperationUseMutationOptions, UseQueryOptionsForUseQueries, UseQueryOptionsForUseSuspenseQuery, WithOptional, QraftServiceOperationsToken } from "@openapi-qraft/tanstack-query-react-types";
7+
import type { DeepReadonly, InvalidateQueryFilters, MutationFiltersByMutationKey, MutationFiltersByParameters, MutationVariables, OperationError, OperationInfiniteData, PartialParameters, QueryFiltersByParameters, QueryFiltersByQueryKey, QueryFnOptions, QueryFnOptionsByParameters, QueryFnOptionsByQueryKey, RequestFnResponse, ServiceOperationEnsureInfiniteQueryDataOptions, ServiceOperationEnsureQueryDataOptions, ServiceOperationFetchInfiniteQueryOptions, ServiceOperationFetchQueryOptions, ServiceOperationInfiniteQueryKey, ServiceOperationMutationFnOptions, ServiceOperationMutationKey, ServiceOperationQueryKey, ServiceOperationUseMutationOptions, UseQueryOptionsForUseQueries, UseQueryOptionsForUseSuspenseQuery, WithOptional, QraftServiceOperationsToken } from "@openapi-qraft/tanstack-query-react-types";
88
import type { CancelOptions, DefinedInitialDataInfiniteOptions, DefinedInitialDataOptions, DefinedUseInfiniteQueryResult, DefinedUseQueryResult, InfiniteQueryPageParamsOptions, InvalidateOptions, Mutation, MutationCache, MutationState, NoInfer, QueryState, RefetchOptions, ResetOptions, SetDataOptions, UndefinedInitialDataInfiniteOptions, UndefinedInitialDataOptions, Updater, UseInfiniteQueryResult, UseMutationResult, UseQueryResult, UseSuspenseInfiniteQueryOptions, UseSuspenseInfiniteQueryResult, UseSuspenseQueryOptions, UseSuspenseQueryResult } from "@tanstack/react-query";
99
export interface FilesService {
1010
/** @summary Get a files by ID */
@@ -803,7 +803,7 @@ export interface FilesService {
803803
* @deprecated
804804
* @summary Get a file list
805805
*/
806-
<TMeta extends Record<string, any>, TSignal extends AbortSignal = AbortSignal>(options: QueryFnOptionsByQueryKey<GetFileListSchema, GetFileListParameters, TMeta, TSignal> | (QueryFnOptionsByParameters<GetFileListParameters, TMeta, TSignal> | void), client?: (schema: GetFileListSchema, options: {
806+
<TMeta extends Record<string, any>, TSignal extends AbortSignal = AbortSignal>(options: QueryFnOptionsByQueryKey<GetFileListSchema, GetFileListParameters, TMeta, TSignal> | (QueryFnOptionsByParameters<GetFileListParameters, TMeta, TSignal> | QueryFnOptions<TMeta, TSignal> | void), client?: (schema: GetFileListSchema, options: {
807807
parameters: GetFileListParameters;
808808
signal?: TSignal;
809809
meta?: TMeta;

packages/tanstack-query-react-plugin/src/__snapshots__/operation-parameters-type-wrapper/services/FilesService.ts.snapshot.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55

66
import type { paths } from "../../openapi.d.ts";
7-
import type { DeepReadonly, InvalidateQueryFilters, MutationFiltersByMutationKey, MutationFiltersByParameters, MutationVariables, OperationError, OperationInfiniteData, PartialParameters, QueryFiltersByParameters, QueryFiltersByQueryKey, QueryFnOptionsByParameters, QueryFnOptionsByQueryKey, RequestFnResponse, ServiceOperationEnsureInfiniteQueryDataOptions, ServiceOperationEnsureQueryDataOptions, ServiceOperationFetchInfiniteQueryOptions, ServiceOperationFetchQueryOptions, ServiceOperationInfiniteQueryKey, ServiceOperationMutationFnOptions, ServiceOperationMutationKey, ServiceOperationQueryKey, ServiceOperationUseMutationOptions, UseQueryOptionsForUseQueries, UseQueryOptionsForUseSuspenseQuery, WithOptional, QraftServiceOperationsToken } from "@openapi-qraft/tanstack-query-react-types";
7+
import type { DeepReadonly, InvalidateQueryFilters, MutationFiltersByMutationKey, MutationFiltersByParameters, MutationVariables, OperationError, OperationInfiniteData, PartialParameters, QueryFiltersByParameters, QueryFiltersByQueryKey, QueryFnOptions, QueryFnOptionsByParameters, QueryFnOptionsByQueryKey, RequestFnResponse, ServiceOperationEnsureInfiniteQueryDataOptions, ServiceOperationEnsureQueryDataOptions, ServiceOperationFetchInfiniteQueryOptions, ServiceOperationFetchQueryOptions, ServiceOperationInfiniteQueryKey, ServiceOperationMutationFnOptions, ServiceOperationMutationKey, ServiceOperationQueryKey, ServiceOperationUseMutationOptions, UseQueryOptionsForUseQueries, UseQueryOptionsForUseSuspenseQuery, WithOptional, QraftServiceOperationsToken } from "@openapi-qraft/tanstack-query-react-types";
88
import type { CancelOptions, DefinedInitialDataInfiniteOptions, DefinedInitialDataOptions, DefinedUseInfiniteQueryResult, DefinedUseQueryResult, InfiniteQueryPageParamsOptions, InvalidateOptions, Mutation, MutationCache, MutationState, NoInfer, QueryState, RefetchOptions, ResetOptions, SetDataOptions, UndefinedInitialDataInfiniteOptions, UndefinedInitialDataOptions, Updater, UseInfiniteQueryResult, UseMutationResult, UseQueryResult, UseSuspenseInfiniteQueryOptions, UseSuspenseInfiniteQueryResult, UseSuspenseQueryOptions, UseSuspenseQueryResult } from "@tanstack/react-query";
99
import type { ParametersWrapper } from "../../type-overrides/parameters-wrapper.js";
1010
export interface FilesService {
@@ -804,7 +804,7 @@ export interface FilesService {
804804
* @deprecated
805805
* @summary Get a file list
806806
*/
807-
<TMeta extends Record<string, any>, TSignal extends AbortSignal = AbortSignal>(options: QueryFnOptionsByQueryKey<GetFileListSchema, GetFileListParameters, TMeta, TSignal> | (QueryFnOptionsByParameters<GetFileListParameters, TMeta, TSignal> | void), client?: (schema: GetFileListSchema, options: {
807+
<TMeta extends Record<string, any>, TSignal extends AbortSignal = AbortSignal>(options: QueryFnOptionsByQueryKey<GetFileListSchema, GetFileListParameters, TMeta, TSignal> | (QueryFnOptionsByParameters<GetFileListParameters, TMeta, TSignal> | QueryFnOptions<TMeta, TSignal> | void), client?: (schema: GetFileListSchema, options: {
808808
parameters: GetFileListParameters;
809809
signal?: TSignal;
810810
meta?: TMeta;

packages/tanstack-query-react-plugin/src/__snapshots__/queryable-write-operations/services/FilesService.ts.snapshot.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55

66
import type { paths } from "../../openapi.d.ts";
7-
import type { DeepReadonly, InvalidateQueryFilters, MutationFiltersByMutationKey, MutationFiltersByParameters, MutationVariables, OperationError, OperationInfiniteData, PartialParameters, QueryFiltersByParameters, QueryFiltersByQueryKey, QueryFnOptionsByParameters, QueryFnOptionsByQueryKey, RequestFnResponse, ServiceOperationEnsureInfiniteQueryDataOptions, ServiceOperationEnsureQueryDataOptions, ServiceOperationFetchInfiniteQueryOptions, ServiceOperationFetchQueryOptions, ServiceOperationInfiniteQueryKey, ServiceOperationMutationFnOptions, ServiceOperationMutationKey, ServiceOperationQueryKey, ServiceOperationUseMutationOptions, UseQueryOptionsForUseQueries, UseQueryOptionsForUseSuspenseQuery, WithOptional, QraftServiceOperationsToken } from "@openapi-qraft/tanstack-query-react-types";
7+
import type { DeepReadonly, InvalidateQueryFilters, MutationFiltersByMutationKey, MutationFiltersByParameters, MutationVariables, OperationError, OperationInfiniteData, PartialParameters, QueryFiltersByParameters, QueryFiltersByQueryKey, QueryFnOptions, QueryFnOptionsByParameters, QueryFnOptionsByQueryKey, RequestFnResponse, ServiceOperationEnsureInfiniteQueryDataOptions, ServiceOperationEnsureQueryDataOptions, ServiceOperationFetchInfiniteQueryOptions, ServiceOperationFetchQueryOptions, ServiceOperationInfiniteQueryKey, ServiceOperationMutationFnOptions, ServiceOperationMutationKey, ServiceOperationQueryKey, ServiceOperationUseMutationOptions, UseQueryOptionsForUseQueries, UseQueryOptionsForUseSuspenseQuery, WithOptional, QraftServiceOperationsToken } from "@openapi-qraft/tanstack-query-react-types";
88
import type { CancelOptions, DefinedInitialDataInfiniteOptions, DefinedInitialDataOptions, DefinedUseInfiniteQueryResult, DefinedUseQueryResult, InfiniteQueryPageParamsOptions, InvalidateOptions, Mutation, MutationCache, MutationState, NoInfer, QueryState, RefetchOptions, ResetOptions, SetDataOptions, UndefinedInitialDataInfiniteOptions, UndefinedInitialDataOptions, Updater, UseInfiniteQueryResult, UseMutationResult, UseQueryResult, UseSuspenseInfiniteQueryOptions, UseSuspenseInfiniteQueryResult, UseSuspenseQueryOptions, UseSuspenseQueryResult } from "@tanstack/react-query";
99
export interface FilesService {
1010
/** @summary Get a files by ID */
@@ -1664,7 +1664,7 @@ export interface FilesService {
16641664
* @deprecated
16651665
* @summary Get a file list
16661666
*/
1667-
<TMeta extends Record<string, any>, TSignal extends AbortSignal = AbortSignal>(options: QueryFnOptionsByQueryKey<GetFileListSchema, GetFileListParameters, TMeta, TSignal> | (QueryFnOptionsByParameters<GetFileListParameters, TMeta, TSignal> | void), client?: (schema: GetFileListSchema, options: {
1667+
<TMeta extends Record<string, any>, TSignal extends AbortSignal = AbortSignal>(options: QueryFnOptionsByQueryKey<GetFileListSchema, GetFileListParameters, TMeta, TSignal> | (QueryFnOptionsByParameters<GetFileListParameters, TMeta, TSignal> | QueryFnOptions<TMeta, TSignal> | void), client?: (schema: GetFileListSchema, options: {
16681668
parameters: GetFileListParameters;
16691669
signal?: TSignal;
16701670
meta?: TMeta;

packages/tanstack-query-react-plugin/src/__snapshots__/root-level-security-inheritance/services/AccountsService.ts.snapshot.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
*/
55

66
import type { paths } from "../../openapi.d.ts";
7-
import type { DeepReadonly, InvalidateQueryFilters, OperationError, OperationInfiniteData, PartialParameters, QueryFiltersByParameters, QueryFiltersByQueryKey, QueryFnOptionsByParameters, QueryFnOptionsByQueryKey, RequestFnResponse, ServiceOperationEnsureInfiniteQueryDataOptions, ServiceOperationEnsureQueryDataOptions, ServiceOperationFetchInfiniteQueryOptions, ServiceOperationFetchQueryOptions, ServiceOperationInfiniteQueryKey, ServiceOperationQueryKey, UseQueryOptionsForUseQueries, UseQueryOptionsForUseSuspenseQuery, WithOptional, QraftServiceOperationsToken } from "@openapi-qraft/tanstack-query-react-types";
7+
import type { DeepReadonly, InvalidateQueryFilters, OperationError, OperationInfiniteData, PartialParameters, QueryFiltersByParameters, QueryFiltersByQueryKey, QueryFnOptions, QueryFnOptionsByParameters, QueryFnOptionsByQueryKey, RequestFnResponse, ServiceOperationEnsureInfiniteQueryDataOptions, ServiceOperationEnsureQueryDataOptions, ServiceOperationFetchInfiniteQueryOptions, ServiceOperationFetchQueryOptions, ServiceOperationInfiniteQueryKey, ServiceOperationQueryKey, UseQueryOptionsForUseQueries, UseQueryOptionsForUseSuspenseQuery, WithOptional, QraftServiceOperationsToken } from "@openapi-qraft/tanstack-query-react-types";
88
import type { CancelOptions, DefinedInitialDataInfiniteOptions, DefinedInitialDataOptions, DefinedUseInfiniteQueryResult, DefinedUseQueryResult, InfiniteQueryPageParamsOptions, InvalidateOptions, NoInfer, QueryState, RefetchOptions, ResetOptions, SetDataOptions, UndefinedInitialDataInfiniteOptions, UndefinedInitialDataOptions, Updater, UseInfiniteQueryResult, UseQueryResult, UseSuspenseInfiniteQueryOptions, UseSuspenseInfiniteQueryResult, UseSuspenseQueryOptions, UseSuspenseQueryResult } from "@tanstack/react-query";
99
export interface AccountsService {
1010
getAccounts: {
1111
/**/
12-
<TMeta extends Record<string, any>, TSignal extends AbortSignal = AbortSignal>(options: QueryFnOptionsByQueryKey<GetAccountsSchema, GetAccountsParameters, TMeta, TSignal> | (QueryFnOptionsByParameters<GetAccountsParameters, TMeta, TSignal> | void), client?: (schema: GetAccountsSchema, options: {
12+
<TMeta extends Record<string, any>, TSignal extends AbortSignal = AbortSignal>(options: QueryFnOptionsByQueryKey<GetAccountsSchema, GetAccountsParameters, TMeta, TSignal> | (QueryFnOptionsByParameters<GetAccountsParameters, TMeta, TSignal> | QueryFnOptions<TMeta, TSignal> | void), client?: (schema: GetAccountsSchema, options: {
1313
parameters: GetAccountsParameters;
1414
signal?: TSignal;
1515
meta?: TMeta;
@@ -232,7 +232,7 @@ export interface AccountsService {
232232
};
233233
getAccountProfile: {
234234
/**/
235-
<TMeta extends Record<string, any>, TSignal extends AbortSignal = AbortSignal>(options: QueryFnOptionsByQueryKey<GetAccountProfileSchema, GetAccountProfileParameters, TMeta, TSignal> | (QueryFnOptionsByParameters<GetAccountProfileParameters, TMeta, TSignal> | void), client?: (schema: GetAccountProfileSchema, options: {
235+
<TMeta extends Record<string, any>, TSignal extends AbortSignal = AbortSignal>(options: QueryFnOptionsByQueryKey<GetAccountProfileSchema, GetAccountProfileParameters, TMeta, TSignal> | (QueryFnOptionsByParameters<GetAccountProfileParameters, TMeta, TSignal> | QueryFnOptions<TMeta, TSignal> | void), client?: (schema: GetAccountProfileSchema, options: {
236236
parameters: GetAccountProfileParameters;
237237
signal?: TSignal;
238238
meta?: TMeta;

packages/tanstack-query-react-types/src/service-operation/ServiceOperationQueryFn.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type {
22
AreAllOptional,
3+
QueryFnOptions,
34
QueryFnOptionsByParameters,
45
QueryFnOptionsByQueryKey,
56
RequestFnResponse,
@@ -18,7 +19,10 @@ export interface ServiceOperationQueryFn<
1819
options:
1920
| QueryFnOptionsByQueryKey<TSchema, TQueryParams, TMeta, TSignal>
2021
| (AreAllOptional<TQueryParams> extends true
21-
? QueryFnOptionsByParameters<TQueryParams, TMeta, TSignal> | void
22+
?
23+
| QueryFnOptionsByParameters<TQueryParams, TMeta, TSignal>
24+
| QueryFnOptions<TMeta, TSignal>
25+
| void
2226
: QueryFnOptionsByParameters<TQueryParams, TMeta, TSignal>),
2327
client?: (
2428
schema: TSchema,
Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
import type { ServiceOperationQueryKey } from '@openapi-qraft/tanstack-query-react-types';
22
import type { DeepReadonly } from './DeepReadonly.js';
33

4-
interface QueryFnOptionsBase<
4+
export interface QueryFnOptions<
55
TMeta extends Record<string, any>,
66
TSignal extends AbortSignal = AbortSignal,
77
> {
88
signal?: TSignal;
99
meta?: TMeta;
10+
/**
11+
* Base URL to use for the request
12+
* @example 'https://api.example.com'
13+
*/
14+
baseUrl?: string;
1015
}
1116

1217
export interface QueryFnOptionsByParameters<
1318
TParams,
1419
TMeta extends Record<string, any>,
1520
TSignal extends AbortSignal = AbortSignal,
16-
>
17-
extends QueryFnOptionsBase<TMeta, TSignal>, QueryFnBaseUrlOptions {
21+
> extends QueryFnOptions<TMeta, TSignal> {
1822
parameters: DeepReadonly<TParams>;
1923

2024
queryKey?: never;
@@ -25,17 +29,8 @@ export interface QueryFnOptionsByQueryKey<
2529
TParams,
2630
TMeta extends Record<string, any>,
2731
TSignal extends AbortSignal = AbortSignal,
28-
>
29-
extends QueryFnOptionsBase<TMeta, TSignal>, QueryFnBaseUrlOptions {
32+
> extends QueryFnOptions<TMeta, TSignal> {
3033
queryKey: ServiceOperationQueryKey<TSchema, TParams>;
3134

3235
parameters?: never;
3336
}
34-
35-
interface QueryFnBaseUrlOptions {
36-
/**
37-
* Base URL to use for the request
38-
* @example 'https://api.example.com'
39-
*/
40-
baseUrl?: string;
41-
}

turbo.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"test": {
1010
"cache": true,
1111
"dependsOn": ["write-package-version-file", "^build"],
12-
"outputs": ["coverage/**"]
12+
"outputs": []
1313
},
1414
"typecheck": {
1515
"cache": true,

0 commit comments

Comments
 (0)