@qualisero/openapi-endpoint 0.13.2 → 0.14.0

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.
package/dist/types.d.ts CHANGED
@@ -1,52 +1,51 @@
1
1
  import { type AxiosInstance, type AxiosError, type AxiosRequestConfig, type AxiosResponse } from 'axios';
2
2
  import type { MutationObserverOptions, QueryKey, QueryObserverOptions } from '@tanstack/query-core';
3
3
  import type { ComputedRef, Ref } from 'vue';
4
- import type { EndpointQueryReturn } from './openapi-query';
5
- import type { EndpointMutationReturn } from './openapi-mutation';
6
4
  /**
7
5
  * Extended Axios request configuration that allows custom properties.
8
6
  */
9
7
  export type AxiosRequestConfigExtended = AxiosRequestConfig & Record<string, unknown>;
8
+ export declare enum HttpMethod {
9
+ GET = "GET",
10
+ POST = "POST",
11
+ PUT = "PUT",
12
+ PATCH = "PATCH",
13
+ DELETE = "DELETE",
14
+ HEAD = "HEAD",
15
+ OPTIONS = "OPTIONS",
16
+ TRACE = "TRACE"
17
+ }
18
+ export declare const QUERY_METHODS: readonly [HttpMethod.GET, HttpMethod.HEAD, HttpMethod.OPTIONS];
19
+ export declare const MUTATION_METHODS: readonly [HttpMethod.POST, HttpMethod.PUT, HttpMethod.PATCH, HttpMethod.DELETE];
20
+ export declare function isQueryMethod(method: HttpMethod): boolean;
21
+ export declare function isMutationMethod(method: HttpMethod): boolean;
10
22
  /**
11
- * Error type shown when an operation requires path parameters but they weren't provided.
12
- *
13
- * @internal
23
+ * A value that can be reactive (ref, computed, getter function) or direct.
14
24
  */
15
- export type RequiresPathParameters<Op extends string> = {
16
- readonly __error: `Operation '${Op}' requires path parameters as the second argument`;
17
- readonly __fix: 'Provide path parameters as the second argument';
18
- readonly __see: 'Check the operation path definition (e.g., /pets/{petId}) or JSDoc';
19
- };
25
+ export type ReactiveOr<T> = T | Ref<T> | ComputedRef<T> | (() => T);
20
26
  /**
21
- * Validates that path parameters have no excess properties.
27
+ * Constrains a getter function `F` so that its return type has no excess
28
+ * properties beyond the expected type `T`.
22
29
  *
23
- * @internal
24
- */
25
- export type HasExcessPathParams<Provided extends Record<string, unknown>, Expected extends Record<string, unknown>> = Exclude<keyof Provided, keyof Expected> extends never ? true : false;
26
- /**
27
- * Type representing an operation that does NOT require path parameters.
28
- * Used in function signatures to restrict which operations can be called without path params.
30
+ * Evaluates to `F` when the return type is valid, or `never` when the
31
+ * function returns unexpected extra properties — causing a type error at the
32
+ * call site.
29
33
  *
30
- * @internal
31
- */
32
- export type NoPathParams<Ops extends Operations<Ops>, Op extends keyof Ops> = Op & (ApiPathParams<Ops, Op> extends Record<string, never> ? Op : RequiresPathParameters<Op & string>);
33
- /**
34
- * Type representing an operation that DOES require path parameters.
35
- * Used in function signatures to restrict which operations must be called with path params.
34
+ * @example
35
+ * ```ts
36
+ * type PP = { petId: string | undefined }
37
+ * type F1 = () => { petId: string } // NoExcessReturn<PP, F1> → F1 ✅
38
+ * type F2 = () => { petId: string; bad: 'x' } // NoExcessReturn<PP, F2> → never ❌
39
+ * ```
36
40
  *
37
- * @internal
41
+ * @internal Used in generated `api-client.ts` to enforce strict path params on getter fns.
38
42
  */
39
- export type WithPathParams<Ops extends Operations<Ops>, Op extends keyof Ops> = Op & (ApiPathParams<Ops, Op> extends Record<string, never> ? RequiresPathParameters<Op & string> : Op);
40
- /** @internal */
41
- export type { EndpointQueryReturn, EndpointMutationReturn };
43
+ export type NoExcessReturn<T extends Record<string, unknown>, F extends () => T> = Exclude<keyof ReturnType<F>, keyof T> extends never ? F : never;
42
44
  /**
43
- * Interface defining the minimal QueryClient methods required by this library.
44
- *
45
- * This interface ensures compatibility with different versions of @tanstack/vue-query
46
- * by only requiring the specific methods that are actually used internally.
47
- *
48
- * @group Types
45
+ * Reactive value that excludes function getters.
46
+ * @internal Used for internal type inference.
49
47
  */
48
+ export type ReactiveValue<T> = T | Ref<T> | ComputedRef<T>;
50
49
  export interface QueryClientLike {
51
50
  cancelQueries(filters: {
52
51
  queryKey: unknown[];
@@ -61,197 +60,219 @@ export interface QueryClientLike {
61
60
  }) => boolean;
62
61
  }): Promise<void>;
63
62
  }
64
- /** @internal */
65
- export type Operations<Ops> = object & {
66
- [K in keyof Ops]: OperationInfo;
67
- };
68
63
  /**
69
- * Configuration object for initializing the OpenAPI client.
70
- *
71
- * @template Ops - The operations type, typically generated from your OpenAPI specification
72
- *
73
- * @example
74
- * ```typescript
75
- * import { useOpenApi } from '@qualisero/openapi-endpoint'
76
- * import { openApiOperations, type OpenApiOperations } from './generated/api-operations'
77
- * import axios from 'axios'
64
+ * Runtime configuration for a single endpoint. Passed directly to
65
+ * `useEndpointQuery` / `useEndpointMutation` by generated code.
78
66
  *
79
- * const config: OpenApiConfig<OpenApiOperations> = {
80
- * operations: openApiOperations,
81
- * axios: axios.create({ baseURL: 'https://api.example.com' }),
82
- * queryClient: customQueryClient // optional
83
- * }
84
- * ```
67
+ * Created by the generated `createApiClient` factory and embedded per-operation
68
+ * in the generated `api-client.ts`.
85
69
  */
86
- export interface OpenApiConfig<Ops extends Operations<Ops>> {
87
- operations: Ops;
70
+ export interface EndpointConfig {
88
71
  axios: AxiosInstance;
89
- queryClient?: QueryClientLike;
90
- }
91
- /** @internal */
92
- export declare enum HttpMethod {
93
- GET = "GET",
94
- POST = "POST",
95
- PUT = "PUT",
96
- PATCH = "PATCH",
97
- DELETE = "DELETE",
98
- HEAD = "HEAD",
99
- OPTIONS = "OPTIONS",
100
- TRACE = "TRACE"
72
+ queryClient: QueryClientLike;
73
+ /** The OpenAPI path template, e.g. `/pets/{petId}` */
74
+ path: string;
75
+ method: HttpMethod;
76
+ /**
77
+ * Pre-computed list path for cache invalidation after mutations.
78
+ * e.g. for `updatePet` at `/pets/{petId}`, this would be `/pets`.
79
+ * `null` means no list invalidation.
80
+ * Generated at code-gen time by the CLI.
81
+ */
82
+ listPath?: string | null;
83
+ /**
84
+ * Registry of all operations' paths, used to resolve `invalidateOperations`
85
+ * option at mutation time. Generated and embedded by the CLI.
86
+ */
87
+ operationsRegistry?: Readonly<Record<string, {
88
+ path: string;
89
+ }>>;
101
90
  }
102
91
  /**
103
- * HTTP methods that are considered read-only query operations.
104
- * These can be used with useQuery() and support caching.
92
+ * Minimal interface satisfied by `QueryReturn`. Used for `refetchEndpoints`
93
+ * in cache invalidation options.
105
94
  */
106
- export declare const QUERY_METHODS: readonly [HttpMethod.GET, HttpMethod.HEAD, HttpMethod.OPTIONS];
95
+ export interface Refetchable {
96
+ refetch: () => Promise<void>;
97
+ }
107
98
  /**
108
- * HTTP methods that modify data and should use mutations.
99
+ * Options for controlling automatic cache invalidation after mutations.
109
100
  */
110
- export declare const MUTATION_METHODS: readonly [HttpMethod.POST, HttpMethod.PUT, HttpMethod.PATCH, HttpMethod.DELETE];
111
- /** @internal */
112
- export declare function isQueryMethod(method: HttpMethod): boolean;
113
- /** @internal */
114
- export declare function isMutationMethod(method: HttpMethod): boolean;
115
- /** @internal */
116
- export interface OperationInfo {
117
- path: string;
118
- method: HttpMethod;
101
+ export interface CacheInvalidationOptions {
102
+ /** Skip automatic cache invalidation. @default false */
103
+ dontInvalidate?: boolean;
104
+ /** Skip automatic cache update for PUT/PATCH responses. @default false */
105
+ dontUpdateCache?: boolean;
106
+ /**
107
+ * Additional operation IDs to invalidate after mutation succeeds.
108
+ * Array of operation name strings, or map of operation name → path params.
109
+ * @example ['listPets']
110
+ * @example { getPet: { petId: '123' } }
111
+ */
112
+ invalidateOperations?: string[] | Record<string, Record<string, string | undefined>>;
113
+ /** Specific query endpoints to refetch after mutation succeeds. */
114
+ refetchEndpoints?: Refetchable[];
119
115
  }
120
- /** @internal */
121
- export type GetOperation<Ops extends Operations<Ops>, Op extends keyof Ops> = Ops[Op];
122
- type RequireAll<T> = {
123
- [K in keyof T]-?: T[K];
124
- };
125
- type RequireReadonly<T> = {
126
- [K in keyof T as IsReadonly<T, K> extends true ? K : never]-?: T[K];
127
- } & {
128
- [K in keyof T as IsReadonly<T, K> extends false ? K : never]: T[K];
116
+ type MaybeRefLeaf<T> = T | Ref<T> | ComputedRef<T>;
117
+ type MaybeRefDeep<T> = T extends (...args: never[]) => unknown ? T : T extends object ? {
118
+ [K in keyof T]: MaybeRefDeep<T[K]>;
119
+ } : MaybeRefLeaf<T>;
120
+ type BaseQueryOptions<TResponse, _TQueryParams extends Record<string, unknown>> = MaybeRefDeep<QueryObserverOptions<TResponse, Error, TResponse, TResponse, QueryKey>> & {
121
+ shallow?: boolean;
129
122
  };
130
- type IfEquals<X, Y, A = X, B = never> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? A : B;
131
- type IsReadonly<T, K extends keyof T> = IfEquals<Pick<T, K>, {
132
- -readonly [Q in K]: T[K];
133
- }, false, true>;
134
123
  /**
135
- * Extract the raw response data type from an operation without modifications.
136
- * @internal
124
+ * Options for `useQuery` composable. Accepts all TanStack Query options plus:
125
+ * - `enabled`: reactive boolean
126
+ * - `queryParams`: reactive query string parameters
127
+ * - `onLoad`: callback when data loads for the first time
128
+ * - `errorHandler`: custom error handler
129
+ * - `axiosOptions`: additional axios config
130
+ *
131
+ * @template TResponse The response data type for this operation
132
+ * @template TQueryParams The query parameters type for this operation
137
133
  */
138
- type ExtractResponseData<Ops extends Operations<Ops>, Op extends keyof Ops> = GetOperation<Ops, Op> extends {
139
- responses: {
140
- 200: {
141
- content: {
142
- 'application/json': infer Data;
143
- };
144
- };
145
- };
146
- } ? Data : unknown;
134
+ export type QueryOptions<TResponse, TQueryParams extends Record<string, unknown> = Record<string, never>> = Omit<BaseQueryOptions<TResponse, TQueryParams>, 'queryKey' | 'queryFn' | 'enabled'> & {
135
+ enabled?: ReactiveOr<boolean>;
136
+ onLoad?: (data: TResponse) => void;
137
+ axiosOptions?: AxiosRequestConfigExtended;
138
+ errorHandler?: (error: AxiosError) => TResponse | void | Promise<TResponse | void>;
139
+ queryParams?: ReactiveOr<TQueryParams>;
140
+ };
141
+ type MutationVarsBase<TPathParams extends Record<string, unknown>, TQueryParams extends Record<string, unknown>> = CacheInvalidationOptions & {
142
+ pathParams?: Partial<TPathParams>;
143
+ axiosOptions?: AxiosRequestConfigExtended;
144
+ queryParams?: TQueryParams;
145
+ };
147
146
  /**
148
- * Extract response data type from an operation (all fields required).
147
+ * Variables passed to `mutation.mutate()` or `mutation.mutateAsync()`.
149
148
  *
150
- * All fields are REQUIRED regardless of their `required` status in the OpenAPI schema.
151
- * This assumes the server always returns complete objects.
149
+ * When `TRequest` is `never` (operation has no request body), `data` is excluded.
152
150
  *
153
- * @example
154
- * ```typescript
155
- * type PetResponse = ApiResponse<OpenApiOperations, 'getPet'>
156
- * // { readonly id: string, name: string, ... } - all required
157
- * ```
151
+ * @template TPathParams Path parameters type
152
+ * @template TRequest Request body type (`never` if none)
153
+ * @template TQueryParams Query parameters type
158
154
  */
159
- export type ApiResponse<Ops extends Operations<Ops>, Op extends keyof Ops> = RequireAll<ExtractResponseData<Ops, Op>>;
155
+ export type MutationVars<TPathParams extends Record<string, unknown>, TRequest, TQueryParams extends Record<string, unknown> = Record<string, never>> = [TRequest] extends [never] ? MutationVarsBase<TPathParams, TQueryParams> : MutationVarsBase<TPathParams, TQueryParams> & {
156
+ data?: TRequest;
157
+ };
158
+ type BaseMutationOptions<TResponse, TPathParams extends Record<string, unknown>, TRequest, TQueryParams extends Record<string, unknown>> = MaybeRefDeep<MutationObserverOptions<AxiosResponse<TResponse>, Error, MutationVars<TPathParams, TRequest, TQueryParams>, unknown>> & {
159
+ shallow?: boolean;
160
+ };
160
161
  /**
161
- * Extract response data type with safe typing for unreliable backends.
162
- *
163
- * Only readonly properties are REQUIRED. Other properties preserve their optional status.
162
+ * Options for `useMutation` composable.
164
163
  *
165
- * @example
166
- * ```typescript
167
- * type PetResponse = ApiResponseSafe<OpenApiOperations, 'getPet'>
168
- * // { readonly id: string, name?: string, ... } - only readonly required
169
- * ```
164
+ * @template TResponse Response data type
165
+ * @template TPathParams Path parameters type
166
+ * @template TRequest Request body type
167
+ * @template TQueryParams Query parameters type
170
168
  */
171
- export type ApiResponseSafe<Ops extends Operations<Ops>, Op extends keyof Ops> = RequireReadonly<ExtractResponseData<Ops, Op>>;
169
+ export type MutationOptions<TResponse, TPathParams extends Record<string, unknown>, TRequest, TQueryParams extends Record<string, unknown> = Record<string, never>> = Omit<BaseMutationOptions<TResponse, TPathParams, TRequest, TQueryParams>, 'mutationFn' | 'mutationKey'> & CacheInvalidationOptions & {
170
+ axiosOptions?: AxiosRequestConfigExtended;
171
+ queryParams?: ReactiveOr<TQueryParams>;
172
+ };
172
173
  /**
173
- * A value that can be reactive (ref, computed) or direct.
174
- * Standardized pattern for all reactive values across the library.
175
- *
176
- * @internal
174
+ * Return type of `mutation.mutateAsync()`.
177
175
  */
178
- export type ReactiveOr<T> = T | Ref<T> | ComputedRef<T> | (() => T);
176
+ export type MutateAsyncReturn<TResponse> = Promise<AxiosResponse<TResponse>>;
179
177
  /**
180
- * Reactive value that excludes function getters.
181
- * Useful for path params where function overloads have stricter checks.
182
- *
183
- * @internal
178
+ * `mutation.mutate()` function signature.
184
179
  */
185
- export type ReactiveValue<T> = T | Ref<T> | ComputedRef<T>;
186
- /** @internal */
187
- type MaybeRefLeaf<T> = T | Ref<T> | ComputedRef<T>;
188
- type MaybeRefDeep<T> = T extends (...args: never[]) => unknown ? T : T extends object ? {
189
- [K in keyof T]: MaybeRefDeep<T[K]>;
190
- } : MaybeRefLeaf<T>;
191
- /** @internal */
192
- type ShallowOption = {
193
- shallow?: boolean;
194
- };
180
+ export type MutateFn<TPathParams extends Record<string, unknown>, TRequest, TQueryParams extends Record<string, unknown> = Record<string, never>> = (vars?: MutationVars<TPathParams, TRequest, TQueryParams>) => void;
195
181
  /**
196
- * Extract path parameters type from an operation (truly required).
197
- *
198
- * All path parameters from the OpenAPI schema are required - they cannot be undefined.
199
- * This matches the runtime behavior where missing path params cause errors.
200
- *
201
- * @example
202
- * ```typescript
203
- * type Params = ApiPathParams<OpenApiOperations, 'getPet'>
204
- * // { petId: string } - all params required
205
- * ```
182
+ * `mutation.mutateAsync()` function signature.
206
183
  */
207
- export type ApiPathParams<Ops extends Operations<Ops>, Op extends keyof Ops> = Ops[Op] extends {
208
- parameters: {
209
- path: infer PathParams;
210
- };
211
- } ? PathParams extends Record<string, unknown> ? PathParams : Record<string, never> : Record<string, never>;
184
+ export type MutateAsyncFn<TResponse, TPathParams extends Record<string, unknown>, TRequest, TQueryParams extends Record<string, unknown> = Record<string, never>> = (vars?: MutationVars<TPathParams, TRequest, TQueryParams>) => MutateAsyncReturn<TResponse>;
212
185
  /**
213
- * Path params input type that allows undefined values for reactive resolution.
214
- *
215
- * @internal
186
+ * Constraint for operation objects. Accepts any object type including
187
+ * interfaces with known keys (like those generated by openapi-typescript).
216
188
  */
217
- export type ApiPathParamsInput<Ops extends Operations<Ops>, Op extends keyof Ops> = {
218
- [K in keyof ApiPathParams<Ops, Op>]: ApiPathParams<Ops, Op>[K] | undefined;
189
+ type AnyOps = object;
190
+ type RequireAll<T> = {
191
+ [K in keyof T]-?: T[K];
192
+ };
193
+ type IfEquals<X, Y, A = X, B = never> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? A : B;
194
+ type IsReadonly<T, K extends keyof T> = IfEquals<Pick<T, K>, {
195
+ -readonly [Q in K]: T[K];
196
+ }, false, true>;
197
+ type RequireReadonly<T> = {
198
+ [K in keyof T as IsReadonly<T, K> extends true ? K : never]-?: T[K];
199
+ } & {
200
+ [K in keyof T as IsReadonly<T, K> extends false ? K : never]: T[K];
219
201
  };
202
+ type ExtractResponseData<Ops extends AnyOps, Op extends keyof Ops> = Ops[Op] extends {
203
+ responses: {
204
+ 200: {
205
+ content: {
206
+ 'application/json': infer Data;
207
+ };
208
+ };
209
+ };
210
+ } ? Data : Ops[Op] extends {
211
+ responses: {
212
+ 201: {
213
+ content: {
214
+ 'application/json': infer Data;
215
+ };
216
+ };
217
+ };
218
+ } ? Data : Ops[Op] extends {
219
+ responses: {
220
+ 202: {
221
+ content: {
222
+ 'application/json': infer Data;
223
+ };
224
+ };
225
+ };
226
+ } ? Data : Ops[Op] extends {
227
+ responses: {
228
+ 203: {
229
+ content: {
230
+ 'application/json': infer Data;
231
+ };
232
+ };
233
+ };
234
+ } ? Data : Ops[Op] extends {
235
+ responses: {
236
+ 204: {
237
+ content: {
238
+ 'application/json': infer Data;
239
+ };
240
+ };
241
+ };
242
+ } ? Data : Ops[Op] extends {
243
+ responses: {
244
+ 206: {
245
+ content: {
246
+ 'application/json': infer Data;
247
+ };
248
+ };
249
+ };
250
+ } ? Data : unknown;
220
251
  /**
221
- * Extract query parameters type from an operation.
222
- * @example
223
- * ```typescript
224
- * type Params = ApiQueryParams<OpenApiOperations, 'listPets'>
225
- * // { limit?: number, status?: string }
226
- * ```
252
+ * Extract the response data type (all fields required).
253
+ * @example `ApiResponse<operations, 'getPet'>` → `{ readonly id: string, name: string, ... }`
227
254
  */
228
- export type ApiQueryParams<Ops extends Operations<Ops>, Op extends keyof Ops> = Ops[Op] extends {
229
- parameters: {
230
- query?: infer QueryParams;
231
- };
232
- } ? QueryParams extends Record<string, unknown> ? {
233
- [K in keyof QueryParams]?: QueryParams[K];
234
- } : Record<string, never> : Record<string, never>;
255
+ export type ApiResponse<Ops extends AnyOps, Op extends keyof Ops> = RequireAll<ExtractResponseData<Ops, Op>>;
256
+ /**
257
+ * Extract the response data type (only readonly fields required).
258
+ */
259
+ export type ApiResponseSafe<Ops extends AnyOps, Op extends keyof Ops> = RequireReadonly<ExtractResponseData<Ops, Op>>;
235
260
  type Writable<T> = {
236
261
  -readonly [K in keyof T as IfEquals<Pick<T, K>, {
237
262
  -readonly [Q in K]: T[K];
238
263
  }, false, true> extends false ? K : never]: T[K];
239
264
  };
240
265
  /**
241
- * Extract request body type from an operation.
242
- * @example
243
- * ```typescript
244
- * type Body = ApiRequest<OpenApiOperations, 'createPet'>
245
- * // { name: string, species?: string }
246
- * ```
266
+ * Extract the request body type.
267
+ * @example `ApiRequest<operations, 'createPet'>` → `{ name: string, species?: string }`
247
268
  */
248
- export type ApiRequest<Ops extends Operations<Ops>, Op extends keyof Ops> = GetOperation<Ops, Op> extends {
269
+ export type ApiRequest<Ops extends AnyOps, Op extends keyof Ops> = Ops[Op] extends {
249
270
  requestBody: {
250
271
  content: {
251
272
  'application/json': infer Body;
252
273
  };
253
274
  };
254
- } ? Writable<Body> : GetOperation<Ops, Op> extends {
275
+ } ? Writable<Body> : Ops[Op] extends {
255
276
  requestBody: {
256
277
  content: {
257
278
  'multipart/form-data': infer Body;
@@ -259,296 +280,31 @@ export type ApiRequest<Ops extends Operations<Ops>, Op extends keyof Ops> = GetO
259
280
  };
260
281
  } ? Writable<Body> | FormData : never;
261
282
  /**
262
- * Options for controlling automatic cache invalidation and updates after mutations.
263
- *
264
- * By default, mutations automatically:
265
- * - Update cache for PUT/PATCH responses with the returned data
266
- * - Invalidate matching GET queries to trigger refetches
267
- *
268
- * @group Types
283
+ * Extract path parameters type (all required).
284
+ * @example `ApiPathParams<operations, 'getPet'>` → `{ petId: string }`
269
285
  */
270
- export interface CacheInvalidationOptions<Ops extends Operations<Ops>> {
271
- /**
272
- * Skip automatic cache invalidation after mutation completes.
273
- *
274
- * @default false
275
- */
276
- dontInvalidate?: boolean;
277
- /**
278
- * Skip automatic cache update for PUT/PATCH responses.
279
- *
280
- * @default false
281
- */
282
- dontUpdateCache?: boolean;
283
- /**
284
- * Additional operations to invalidate after mutation succeeds.
285
- *
286
- * Can be either:
287
- * - Array of operation IDs: `['listPets', 'getPetStats']`
288
- * - Map of operation ID to path params: `{ getPet: { petId: '123' } }`
289
- *
290
- * @example
291
- * ```typescript
292
- * // Invalidate list when creating
293
- * { invalidateOperations: ['listPets'] }
294
- *
295
- * // Invalidate specific item
296
- * { invalidateOperations: { getPet: { petId: '123' } } }
297
- * ```
298
- */
299
- invalidateOperations?: (keyof Ops)[] | Partial<{
300
- [K in keyof Ops]: ApiPathParams<Ops, K>;
301
- }>;
302
- /**
303
- * Specific query endpoints to refetch after mutation succeeds.
304
- *
305
- * Use when you have specific query results that need to be refetched.
306
- *
307
- * @example
308
- * ```typescript
309
- * const listQuery = api.useQuery('listPets')
310
- * { refetchEndpoints: [listQuery] }
311
- * ```
312
- */
313
- refetchEndpoints?: EndpointQueryReturn<Ops, keyof Ops>[];
314
- }
315
- /**
316
- * Query options for `useQuery` with custom extensions.
317
- *
318
- * Supports all TanStack Query options plus:
319
- * - `enabled`: Reactive boolean to control when query runs
320
- * - `queryParams`: Reactive query string parameters
321
- * - `onLoad`: Callback when data loads successfully
322
- * - `errorHandler`: Custom error handler with fallback support
323
- * - `axiosOptions`: Additional axios configuration
324
- *
325
- * @template Ops - The operations type from your OpenAPI specification
326
- * @template Op - The operation key
327
- *
328
- * @example
329
- * ```typescript
330
- * const { data } = api.useQuery('listPets', {
331
- * queryParams: { limit: 10 },
332
- * enabled: computed(() => isLoggedIn.value),
333
- * staleTime: 5000,
334
- * onLoad: (data) => console.log('Loaded:', data.length)
335
- * })
336
- * ```
337
- *
338
- * @group Types
339
- */
340
- type BaseQueryOptions<Ops extends Operations<Ops>, Op extends keyof Ops> = MaybeRefDeep<QueryObserverOptions<ApiResponse<Ops, Op>, Error, ApiResponse<Ops, Op>, ApiResponse<Ops, Op>, QueryKey>> & ShallowOption;
341
- export type QQueryOptions<Ops extends Operations<Ops>, Op extends keyof Ops> = Omit<BaseQueryOptions<Ops, Op>, 'queryKey' | 'queryFn' | 'enabled'> & {
342
- /** Whether the query should execute. Can be reactive (ref/computed/function). */
343
- enabled?: ReactiveOr<boolean>;
344
- /** Callback when data is successfully loaded for the first time. */
345
- onLoad?: (data: ApiResponse<Ops, Op>) => void;
346
- /** Additional axios configuration for this request. */
347
- axiosOptions?: AxiosRequestConfigExtended;
348
- /** Custom error handler. Return data to use as fallback, or void to use default error. */
349
- errorHandler?: (error: AxiosError) => ApiResponse<Ops, Op> | void | Promise<ApiResponse<Ops, Op> | void>;
350
- /** Query parameters for the request. Can be reactive (ref/computed/function). */
351
- queryParams?: ReactiveOr<ApiQueryParams<Ops, Op>>;
352
- };
353
- /**
354
- * Variables passed to mutation.mutate() or mutation.mutateAsync().
355
- *
356
- * Combines cache invalidation options with mutation-specific data:
357
- * - `data`: Request body (when operation accepts one)
358
- * - `pathParams`: Path parameters (can override those from useMutation call)
359
- * - `queryParams`: Query string parameters
360
- * - `axiosOptions`: Additional axios configuration
361
- *
362
- * Plus all cache invalidation options (dontInvalidate, invalidateOperations, etc.)
363
- *
364
- * @template Ops - The operations type
365
- * @template Op - The operation key
366
- *
367
- * @example
368
- * ```typescript
369
- * const mutation = api.useMutation('createPet')
370
- * mutation.mutate({
371
- * data: { name: 'Fluffy' },
372
- * invalidateOperations: ['listPets']
373
- * })
374
- * ```
375
- *
376
- * @group Types
377
- */
378
- export type QMutationVars<Ops extends Operations<Ops>, Op extends keyof Ops> = CacheInvalidationOptions<Ops> & {
379
- data?: ApiRequest<Ops, Op>;
380
- pathParams?: ApiPathParamsInput<Ops, Op>;
381
- axiosOptions?: AxiosRequestConfigExtended;
382
- queryParams?: ApiQueryParams<Ops, Op>;
383
- };
384
- /**
385
- * Resolved return type for mutateAsync to avoid showing full operations union in tooltips.
386
- * @internal
387
- */
388
- export type MutateAsyncReturn<Ops extends Operations<Ops>, Op extends keyof Ops> = Promise<AxiosResponse<ApiResponse<Ops, Op>>>;
389
- /**
390
- * Function signature for mutation.mutate() - non-blocking mutation execution.
391
- *
392
- * Inlined types allow TypeScript to resolve specific operation types in tooltips
393
- * instead of showing the entire operations union.
394
- *
395
- * @group Types
396
- * @internal
397
- */
398
- export type MutateFn<Ops extends Operations<Ops>, Op extends keyof Ops> = (vars?: {
399
- data?: ApiRequest<Ops, Op>;
400
- pathParams?: ApiPathParamsInput<Ops, Op>;
401
- axiosOptions?: AxiosRequestConfigExtended;
402
- queryParams?: ApiQueryParams<Ops, Op>;
403
- dontInvalidate?: boolean;
404
- dontUpdateCache?: boolean;
405
- invalidateOperations?: (keyof Ops)[];
406
- refetchEndpoints?: EndpointQueryReturn<Ops, keyof Ops>[];
407
- }) => void;
408
- /**
409
- * Function signature for mutation.mutateAsync() - async mutation execution.
410
- *
411
- * Inlined types allow TypeScript to resolve specific operation types in tooltips
412
- * instead of showing the entire operations union.
413
- *
414
- * @group Types
415
- * @internal
416
- */
417
- export type MutateAsyncFn<Ops extends Operations<Ops>, Op extends keyof Ops> = (vars?: {
418
- data?: ApiRequest<Ops, Op>;
419
- pathParams?: ApiPathParamsInput<Ops, Op>;
420
- axiosOptions?: AxiosRequestConfigExtended;
421
- queryParams?: ApiQueryParams<Ops, Op>;
422
- dontInvalidate?: boolean;
423
- dontUpdateCache?: boolean;
424
- invalidateOperations?: (keyof Ops)[];
425
- refetchEndpoints?: EndpointQueryReturn<Ops, keyof Ops>[];
426
- }) => MutateAsyncReturn<Ops, Op>;
286
+ export type ApiPathParams<Ops extends AnyOps, Op extends keyof Ops> = Ops[Op] extends {
287
+ parameters: {
288
+ path: infer PathParams;
289
+ };
290
+ } ? PathParams extends Record<string, unknown> ? PathParams : Record<string, never> : Record<string, never>;
427
291
  /**
428
- * Mutation options for `useMutation` with custom extensions.
429
- *
430
- * Supports all TanStack Query mutation options plus:
431
- * - Cache invalidation options (dontInvalidate, invalidateOperations, etc.)
432
- * - `queryParams`: Reactive query string parameters
433
- * - `axiosOptions`: Additional axios configuration
434
- *
435
- * @template Ops - The operations type
436
- * @template Op - The operation key
437
- *
438
- * @example
439
- * ```typescript
440
- * const mutation = api.useMutation('createPet', {
441
- * onSuccess: () => console.log('Created!'),
442
- * invalidateOperations: ['listPets']
443
- * })
444
- * ```
445
- *
446
- * @group Types
292
+ * Path params input type — same as `ApiPathParams` but all values allow `undefined`
293
+ * (for reactive resolution where params may not yet be set).
447
294
  */
448
- type MutationVarsInput<Ops extends Operations<Ops>, Op extends keyof Ops> = ApiRequest<Ops, Op> extends never ? QMutationVars<Ops, Op> | void : QMutationVars<Ops, Op>;
449
- type BaseMutationOptions<Ops extends Operations<Ops>, Op extends keyof Ops> = MaybeRefDeep<MutationObserverOptions<AxiosResponse<ApiResponse<Ops, Op>>, Error, MutationVarsInput<Ops, Op>, unknown>> & ShallowOption;
450
- export type QMutationOptions<Ops extends Operations<Ops>, Op extends keyof Ops> = Omit<BaseMutationOptions<Ops, Op>, 'mutationFn' | 'mutationKey'> & CacheInvalidationOptions<Ops> & {
451
- axiosOptions?: AxiosRequestConfigExtended;
452
- queryParams?: ReactiveOr<ApiQueryParams<Ops, Op>>;
295
+ export type ApiPathParamsInput<Ops extends AnyOps, Op extends keyof Ops> = {
296
+ [K in keyof ApiPathParams<Ops, Op>]: ApiPathParams<Ops, Op>[K] | undefined;
453
297
  };
454
298
  /**
455
- * Runtime type validator for mutation parameters.
456
- *
457
- * This helper is a pass-through function that helps TypeScript narrow parameter types.
458
- *
459
- * @example
460
- * ```typescript
461
- * const mutation = api.useMutation(MutationOperationId.createPet)
462
- * await mutation.mutateAsync(
463
- * validateMutationParams(MutationOperationId.createPet, {
464
- * data: { name: 'Fluffy' }
465
- * })
466
- * )
467
- * ```
299
+ * Extract query parameters type (all optional).
300
+ * @example `ApiQueryParams<operations, 'listPets'>` → `{ limit?: number, status?: string }`
468
301
  */
469
- export declare function validateMutationParams<Ops extends Operations<Ops>, Op extends keyof Ops>(_operationId: Op, params: QMutationVars<Ops, Op>): QMutationVars<Ops, Op>;
470
- /** @internal */
471
- export type QueryOpsNoPathParams<Ops extends Operations<Ops>> = {
472
- [Op in keyof Ops]: Ops[Op]['method'] extends HttpMethod.GET | HttpMethod.HEAD | HttpMethod.OPTIONS ? ApiPathParams<Ops, Op> extends Record<string, never> ? Op : never : never;
473
- }[keyof Ops];
474
- /** @internal */
475
- export type QueryOpsWithPathParams<Ops extends Operations<Ops>> = {
476
- [Op in keyof Ops]: Ops[Op]['method'] extends HttpMethod.GET | HttpMethod.HEAD | HttpMethod.OPTIONS ? ApiPathParams<Ops, Op> extends Record<string, never> ? never : Op : never;
477
- }[keyof Ops];
478
- /** @internal */
479
- export type MutationOpsNoPathParams<Ops extends Operations<Ops>> = {
480
- [Op in keyof Ops]: Ops[Op]['method'] extends HttpMethod.POST | HttpMethod.PUT | HttpMethod.PATCH | HttpMethod.DELETE ? ApiPathParams<Ops, Op> extends Record<string, never> ? Op : never : never;
481
- }[keyof Ops];
482
- /** @internal */
483
- export type MutationOpsWithPathParams<Ops extends Operations<Ops>> = {
484
- [Op in keyof Ops]: Ops[Op]['method'] extends HttpMethod.POST | HttpMethod.PUT | HttpMethod.PATCH | HttpMethod.DELETE ? ApiPathParams<Ops, Op> extends Record<string, never> ? never : Op : never;
485
- }[keyof Ops];
486
- /**
487
- * Type representing an instance of the OpenAPI client returned by useOpenApi.
488
- *
489
- * This interface defines all the methods available on the API client instance.
490
- *
491
- * @group Types
492
- * @template Ops - The operations type from your OpenAPI specification
493
- *
494
- * @example
495
- * ```typescript
496
- * import { useOpenApi } from '@qualisero/openapi-endpoint'
497
- * import { type OpenApiOperations } from './generated/api-operations'
498
- *
499
- * const api: OpenApiInstance<OpenApiOperations> = useOpenApi(config)
500
- * const query = api.useQuery('getPet', { petId: '123' })
501
- * const mutation = api.useMutation('createPet')
502
- * ```
503
- */
504
- export type OpenApiInstance<Ops extends Operations<Ops>> = {
505
- /**
506
- * Execute a type-safe query (GET/HEAD/OPTIONS) with automatic caching.
507
- *
508
- * @template Op - The operation key
509
- * @param operationId - Query operation ID
510
- * @param pathParams - Path params for operations that require them
511
- * @param options - Query options
512
- * @returns Reactive query result
513
- *
514
- * @example
515
- * ```typescript
516
- * // No path params
517
- * const listQuery = api.useQuery('listPets', { queryParams: { limit: 10 } })
518
- *
519
- * // With path params (direct object)
520
- * const petQuery = api.useQuery('getPet', { petId: '123' })
521
- *
522
- * // With path params (reactive function)
523
- * const id = ref('')
524
- * const detailsQuery = api.useQuery('getPet', () => ({ petId: id.value }))
525
- * ```
526
- */
527
- useQuery: (<Op extends QueryOpsNoPathParams<Ops>>(operationId: Op, options?: QQueryOptions<Ops, Op>) => EndpointQueryReturn<Ops, Op>) & (<Op extends QueryOpsWithPathParams<Ops>>(operationId: Op, pathParams: ReactiveValue<ApiPathParamsInput<Ops, Op>>, options?: QQueryOptions<Ops, Op>) => EndpointQueryReturn<Ops, Op>) & (<Op extends QueryOpsWithPathParams<Ops>, PathParams extends ApiPathParamsInput<Ops, Op>>(operationId: Op, pathParams: () => PathParams & (HasExcessPathParams<PathParams, ApiPathParams<Ops, Op>> extends true ? PathParams : never), options?: QQueryOptions<Ops, Op>) => EndpointQueryReturn<Ops, Op>);
528
- /**
529
- * Execute a type-safe mutation (POST/PUT/PATCH/DELETE) with automatic cache updates.
530
- *
531
- * @template Op - The operation key
532
- * @param operationId - Mutation operation ID
533
- * @param pathParams - Path params for operations that require them
534
- * @param options - Mutation options
535
- * @returns Reactive mutation result
536
- *
537
- * @example
538
- * ```typescript
539
- * // No path params
540
- * const createPet = api.useMutation('createPet')
541
- * createPet.mutate({ data: { name: 'Fluffy' } })
542
- *
543
- * // With path params (direct object)
544
- * const updatePet = api.useMutation('updatePet', { petId: '123' })
545
- * updatePet.mutate({ data: { name: 'Updated' } })
546
- *
547
- * // With path params (reactive function)
548
- * const id = ref('')
549
- * const deletePet = api.useMutation('deletePet', () => ({ petId: id.value }))
550
- * ```
551
- */
552
- useMutation: (<Op extends MutationOpsNoPathParams<Ops>>(operationId: Op, options?: QMutationOptions<Ops, Op>) => EndpointMutationReturn<Ops, Op>) & (<Op extends MutationOpsWithPathParams<Ops>>(operationId: Op, pathParams: ReactiveValue<ApiPathParamsInput<Ops, Op>>, options?: QMutationOptions<Ops, Op>) => EndpointMutationReturn<Ops, Op>) & (<Op extends MutationOpsWithPathParams<Ops>, PathParams extends ApiPathParamsInput<Ops, Op>>(operationId: Op, pathParams: () => PathParams & (HasExcessPathParams<PathParams, ApiPathParams<Ops, Op>> extends true ? PathParams : never), options?: QMutationOptions<Ops, Op>) => EndpointMutationReturn<Ops, Op>);
553
- };
302
+ export type ApiQueryParams<Ops extends AnyOps, Op extends keyof Ops> = Ops[Op] extends {
303
+ parameters: {
304
+ query?: infer QueryParams;
305
+ };
306
+ } ? QueryParams extends Record<string, unknown> ? {
307
+ [K in keyof QueryParams]?: QueryParams[K];
308
+ } : Record<string, never> : Record<string, never>;
309
+ export {};
554
310
  //# sourceMappingURL=types.d.ts.map