@qualisero/openapi-endpoint 0.12.3 → 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,49 +1,57 @@
1
1
  import { type AxiosInstance, type AxiosError, type AxiosRequestConfig, type AxiosResponse } from 'axios';
2
- import { UseMutationOptions, type UseQueryOptions } from '@tanstack/vue-query';
3
- import type { MaybeRef, MaybeRefOrGetter } from 'vue';
4
- import type { EndpointQueryReturn } from './openapi-query';
5
- import type { EndpointMutationReturn } from './openapi-mutation';
2
+ import type { MutationObserverOptions, QueryKey, QueryObserverOptions } from '@tanstack/query-core';
3
+ import type { ComputedRef, Ref } from 'vue';
6
4
  /**
7
5
  * Extended Axios request configuration that allows custom properties.
8
- *
9
- * This type extends the standard AxiosRequestConfig to support custom properties
10
- * that users might add through module augmentation. It ensures compatibility with
11
- * both standard axios options and user-defined custom properties.
12
6
  */
13
7
  export type AxiosRequestConfigExtended = AxiosRequestConfig & Record<string, unknown>;
14
- /** @internal */
15
- export type { EndpointQueryReturn, EndpointMutationReturn };
16
- export type OperationId = string;
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;
17
22
  /**
18
- * Interface defining the minimal QueryClient methods required by this library.
23
+ * A value that can be reactive (ref, computed, getter function) or direct.
24
+ */
25
+ export type ReactiveOr<T> = T | Ref<T> | ComputedRef<T> | (() => T);
26
+ /**
27
+ * Constrains a getter function `F` so that its return type has no excess
28
+ * properties beyond the expected type `T`.
29
+ *
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.
19
33
  *
20
- * This interface ensures compatibility with different versions of @tanstack/vue-query
21
- * by only requiring the specific methods that are actually used internally.
22
- * This prevents version compatibility issues where internal implementation details
23
- * (like private properties) might differ between versions.
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
+ * ```
24
40
  *
25
- * @group Types
41
+ * @internal Used in generated `api-client.ts` to enforce strict path params on getter fns.
42
+ */
43
+ export type NoExcessReturn<T extends Record<string, unknown>, F extends () => T> = Exclude<keyof ReturnType<F>, keyof T> extends never ? F : never;
44
+ /**
45
+ * Reactive value that excludes function getters.
46
+ * @internal Used for internal type inference.
26
47
  */
48
+ export type ReactiveValue<T> = T | Ref<T> | ComputedRef<T>;
27
49
  export interface QueryClientLike {
28
- /**
29
- * Cancel running queries that match the provided filters.
30
- * Used to prevent race conditions when mutations affect data.
31
- */
32
50
  cancelQueries(filters: {
33
51
  queryKey: unknown[];
34
52
  exact?: boolean;
35
53
  }): Promise<void>;
36
- /**
37
- * Set query data for a specific query key.
38
- * Used for optimistic updates after successful mutations.
39
- */
40
54
  setQueryData(queryKey: unknown[], data: unknown): void;
41
- /**
42
- * Invalidate queries that match the provided filters.
43
- * Used to trigger refetches of related data after mutations.
44
- *
45
- * @param filters - Filters can include queryKey, exact, and/or a predicate function
46
- */
47
55
  invalidateQueries(filters: {
48
56
  queryKey?: unknown[];
49
57
  exact?: boolean;
@@ -52,289 +60,251 @@ export interface QueryClientLike {
52
60
  }) => boolean;
53
61
  }): Promise<void>;
54
62
  }
55
- export type Operations<Ops> = object & {
56
- [K in keyof Ops]: {
57
- method: HttpMethod;
58
- };
59
- };
60
63
  /**
61
- * Configuration object for initializing the OpenAPI client.
64
+ * Runtime configuration for a single endpoint. Passed directly to
65
+ * `useEndpointQuery` / `useEndpointMutation` by generated code.
62
66
  *
63
- * This interface defines the required configuration to set up a type-safe OpenAPI client
64
- * with Vue Query integration. It requires both the operations metadata (typically generated
65
- * from your OpenAPI specification) and an Axios instance for making HTTP requests.
66
- *
67
- * @template Ops - The operations type, typically generated from your OpenAPI specification
68
- * @template AxiosConfig - The axios request configuration type (defaults to AxiosRequestConfig)
69
- *
70
- * @example
71
- * ```typescript
72
- * import { OpenApiConfig } from '@qualisero/openapi-endpoint'
73
- * import { openApiOperations, type OpenApiOperations } from './generated/api-operations'
74
- * import axios from 'axios'
75
- *
76
- * // Basic usage with default axios config
77
- * const config: OpenApiConfig<OpenApiOperations> = {
78
- * operations: openApiOperations,
79
- * axios: axios.create({
80
- * baseURL: 'https://api.example.com',
81
- * headers: { 'Authorization': 'Bearer token' }
82
- * }),
83
- * queryClient: customQueryClient // optional
84
- * }
85
- *
86
- * // With custom axios config type (for module augmentation)
87
- * const configWithCustomAxios: OpenApiConfig<OpenApiOperations, MyCustomAxiosRequestConfig> = {
88
- * operations: openApiOperations,
89
- * axios: customAxiosInstance
90
- * }
91
- * ```
67
+ * Created by the generated `createApiClient` factory and embedded per-operation
68
+ * in the generated `api-client.ts`.
92
69
  */
93
- export interface OpenApiConfig<Ops extends Operations<Ops>> {
94
- /**
95
- * The operations metadata object, typically generated from your OpenAPI specification.
96
- * This contains type information and HTTP method details for each API endpoint.
97
- */
98
- operations: Ops;
70
+ export interface EndpointConfig {
71
+ axios: AxiosInstance;
72
+ queryClient: QueryClientLike;
73
+ /** The OpenAPI path template, e.g. `/pets/{petId}` */
74
+ path: string;
75
+ method: HttpMethod;
99
76
  /**
100
- * Axios instance for making HTTP requests.
101
- * Configure this with your base URL, authentication, and any global request/response interceptors.
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.
102
81
  */
103
- axios: AxiosInstance;
82
+ listPath?: string | null;
104
83
  /**
105
- * Optional TanStack Query client instance.
106
- * If not provided, a default QueryClient with sensible defaults will be used.
107
- *
108
- * Note: This accepts any QueryClient-like object that implements the required methods,
109
- * ensuring compatibility across different versions of @tanstack/vue-query.
84
+ * Registry of all operations' paths, used to resolve `invalidateOperations`
85
+ * option at mutation time. Generated and embedded by the CLI.
110
86
  */
111
- queryClient?: QueryClientLike;
112
- }
113
- export declare enum HttpMethod {
114
- GET = "GET",
115
- POST = "POST",
116
- PUT = "PUT",
117
- PATCH = "PATCH",
118
- DELETE = "DELETE",
119
- HEAD = "HEAD",
120
- OPTIONS = "OPTIONS",
121
- TRACE = "TRACE"
87
+ operationsRegistry?: Readonly<Record<string, {
88
+ path: string;
89
+ }>>;
122
90
  }
123
- /** @internal */
124
- export interface OperationInfo {
125
- path: string;
126
- method: HttpMethod;
91
+ /**
92
+ * Minimal interface satisfied by `QueryReturn`. Used for `refetchEndpoints`
93
+ * in cache invalidation options.
94
+ */
95
+ export interface Refetchable {
96
+ refetch: () => Promise<void>;
127
97
  }
128
- export type GetOperation<Ops extends Operations<Ops>, Op extends keyof Ops> = Ops[Op];
129
- export type GetResponseData<Ops extends Operations<Ops>, Op extends keyof Ops> = GetOperation<Ops, Op> extends {
130
- responses: {
131
- 200: {
132
- content: {
133
- 'application/json': infer Data;
134
- };
135
- };
136
- };
137
- } ? RequireReadonly<Data> : unknown;
138
- type OmitMaybeRef<T, K extends PropertyKey> = T extends MaybeRef<infer U> ? MaybeRef<Omit<U, K> & Partial<Pick<U, K & keyof U>>> : Omit<T, K> & Partial<Pick<T, K & keyof T>>;
139
- /** @internal */
140
- export type QQueryOptions<Ops extends Operations<Ops>, Op extends keyof Ops> = OmitMaybeRef<UseQueryOptions<GetResponseData<Ops, Op>, Error, GetResponseData<Ops, Op>, GetResponseData<Ops, Op>>, 'queryKey' | 'queryFn' | 'enabled'> & {
141
- enabled?: MaybeRefOrGetter<boolean>;
142
- onLoad?: (data: GetResponseData<Ops, Op>) => void;
143
- axiosOptions?: AxiosRequestConfigExtended;
144
- errorHandler?: (error: AxiosError) => GetResponseData<Ops, Op> | void | Promise<GetResponseData<Ops, Op> | void>;
145
- queryParams?: MaybeRefOrGetter<GetQueryParameters<Ops, Op>>;
146
- };
147
- type MutationOnSuccessOptions<Ops extends Operations<Ops>> = {
98
+ /**
99
+ * Options for controlling automatic cache invalidation after mutations.
100
+ */
101
+ export interface CacheInvalidationOptions {
102
+ /** Skip automatic cache invalidation. @default false */
148
103
  dontInvalidate?: boolean;
104
+ /** Skip automatic cache update for PUT/PATCH responses. @default false */
149
105
  dontUpdateCache?: boolean;
150
- invalidateOperations?: (keyof Ops)[] | Partial<{
151
- [K in keyof Ops]: GetPathParameters<Ops, K>;
152
- }>;
153
- refetchEndpoints?: EndpointQueryReturn<Ops, keyof Ops>[];
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[];
115
+ }
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;
154
122
  };
155
- /** @internal */
156
- export type QMutationVars<Ops extends Operations<Ops>, Op extends keyof Ops> = MutationOnSuccessOptions<Ops> & {
157
- data?: GetRequestBody<Ops, Op>;
158
- pathParams?: GetPathParameters<Ops, Op>;
123
+ /**
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
133
+ */
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;
159
137
  axiosOptions?: AxiosRequestConfigExtended;
160
- queryParams?: GetQueryParameters<Ops, Op>;
138
+ errorHandler?: (error: AxiosError) => TResponse | void | Promise<TResponse | void>;
139
+ queryParams?: ReactiveOr<TQueryParams>;
161
140
  };
162
- /** @internal */
163
- export type QMutationOptions<Ops extends Operations<Ops>, Op extends keyof Ops> = OmitMaybeRef<UseMutationOptions<AxiosResponse<GetResponseData<Ops, Op>>, Error, GetRequestBody<Ops, Op> extends never ? QMutationVars<Ops, Op> | void : QMutationVars<Ops, Op>>, 'mutationFn' | 'mutationKey'> & MutationOnSuccessOptions<Ops> & {
141
+ type MutationVarsBase<TPathParams extends Record<string, unknown>, TQueryParams extends Record<string, unknown>> = CacheInvalidationOptions & {
142
+ pathParams?: Partial<TPathParams>;
164
143
  axiosOptions?: AxiosRequestConfigExtended;
165
- queryParams?: MaybeRefOrGetter<GetQueryParameters<Ops, Op>>;
144
+ queryParams?: TQueryParams;
145
+ };
146
+ /**
147
+ * Variables passed to `mutation.mutate()` or `mutation.mutateAsync()`.
148
+ *
149
+ * When `TRequest` is `never` (operation has no request body), `data` is excluded.
150
+ *
151
+ * @template TPathParams Path parameters type
152
+ * @template TRequest Request body type (`never` if none)
153
+ * @template TQueryParams Query parameters type
154
+ */
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
+ };
161
+ /**
162
+ * Options for `useMutation` composable.
163
+ *
164
+ * @template TResponse Response data type
165
+ * @template TPathParams Path parameters type
166
+ * @template TRequest Request body type
167
+ * @template TQueryParams Query parameters type
168
+ */
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
+ };
173
+ /**
174
+ * Return type of `mutation.mutateAsync()`.
175
+ */
176
+ export type MutateAsyncReturn<TResponse> = Promise<AxiosResponse<TResponse>>;
177
+ /**
178
+ * `mutation.mutate()` function signature.
179
+ */
180
+ export type MutateFn<TPathParams extends Record<string, unknown>, TRequest, TQueryParams extends Record<string, unknown> = Record<string, never>> = (vars?: MutationVars<TPathParams, TRequest, TQueryParams>) => void;
181
+ /**
182
+ * `mutation.mutateAsync()` function signature.
183
+ */
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>;
185
+ /**
186
+ * Constraint for operation objects. Accepts any object type including
187
+ * interfaces with known keys (like those generated by openapi-typescript).
188
+ */
189
+ type AnyOps = object;
190
+ type RequireAll<T> = {
191
+ [K in keyof T]-?: T[K];
166
192
  };
167
- export type GetPathParameters<Ops extends Operations<Ops>, Op extends keyof Ops> = Ops[Op] extends {
168
- parameters: {
169
- path: infer PathParams;
170
- };
171
- } ? {
172
- [K in keyof PathParams]: PathParams[K] | undefined;
173
- } : Record<string, never>;
174
- export type GetQueryParameters<Ops extends Operations<Ops>, Op extends keyof Ops> = Ops[Op] extends {
175
- parameters: {
176
- query?: infer QueryParams;
177
- };
178
- } ? QueryParams extends Record<string, unknown> ? {
179
- [K in keyof QueryParams]?: QueryParams[K];
180
- } : Record<string, never> : Record<string, never>;
181
193
  type IfEquals<X, Y, A = X, B = never> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? A : B;
182
194
  type IsReadonly<T, K extends keyof T> = IfEquals<Pick<T, K>, {
183
195
  -readonly [Q in K]: T[K];
184
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];
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;
251
+ /**
252
+ * Extract the response data type (all fields required).
253
+ * @example `ApiResponse<operations, 'getPet'>` → `{ readonly id: string, name: string, ... }`
254
+ */
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>>;
185
260
  type Writable<T> = {
186
- -readonly [K in keyof T as IsReadonly<T, K> extends false ? K : never]: T[K];
261
+ -readonly [K in keyof T as IfEquals<Pick<T, K>, {
262
+ -readonly [Q in K]: T[K];
263
+ }, false, true> extends false ? K : never]: T[K];
187
264
  };
188
- export type GetRequestBody<Ops extends Operations<Ops>, Op extends keyof Ops> = GetOperation<Ops, Op> extends {
265
+ /**
266
+ * Extract the request body type.
267
+ * @example `ApiRequest<operations, 'createPet'>` → `{ name: string, species?: string }`
268
+ */
269
+ export type ApiRequest<Ops extends AnyOps, Op extends keyof Ops> = Ops[Op] extends {
189
270
  requestBody: {
190
271
  content: {
191
272
  'application/json': infer Body;
192
273
  };
193
274
  };
194
- } ? Writable<Body> : GetOperation<Ops, Op> extends {
275
+ } ? Writable<Body> : Ops[Op] extends {
195
276
  requestBody: {
196
277
  content: {
197
278
  'multipart/form-data': infer Body;
198
279
  };
199
280
  };
200
281
  } ? Writable<Body> | FormData : never;
201
- type RequireReadonly<T> = {
202
- [K in keyof T as IsReadonly<T, K> extends true ? K : never]-?: T[K];
203
- } & {
204
- [K in keyof T as IsReadonly<T, K> extends false ? K : never]: T[K];
205
- };
206
- export type IsQueryOperation<Ops extends Operations<Ops>, Op extends keyof Ops> = Ops[Op] extends {
207
- method: HttpMethod.GET | HttpMethod.HEAD | HttpMethod.OPTIONS;
208
- } ? true : false;
209
282
  /**
210
- * Type representing an instance of the OpenAPI client returned by useOpenApi.
211
- *
212
- * This interface defines all the methods available on the API client instance,
213
- * providing type-safe access to queries, mutations, and generic endpoints based
214
- * on your OpenAPI specification.
215
- *
216
- * @group Types
217
- * @template Ops - The operations type from your OpenAPI specification
218
- * @template AxiosConfig - The axios request configuration type (defaults to AxiosRequestConfig)
219
- *
220
- * @example
221
- * ```typescript
222
- * import { OpenApiInstance } from '@qualisero/openapi-endpoint'
223
- * import { type OpenApiOperations } from './generated/api-operations'
224
- *
225
- * // Type your API instance for better IntelliSense
226
- * const api: OpenApiInstance<OpenApiOperations> = useOpenApi(config)
227
- *
228
- * // All methods are now fully typed
229
- * const query = api.useQuery('getPet', { petId: '123' })
230
- * const mutation = api.useMutation('createPet')
231
- * const endpoint = api.useEndpoint('listPets')
232
- * ```
283
+ * Extract path parameters type (all required).
284
+ * @example `ApiPathParams<operations, 'getPet'>` → `{ petId: string }`
233
285
  */
234
- export type OpenApiInstance<Ops extends Operations<Ops>> = {
235
- /**
236
- * Debug utility to inspect operation metadata at runtime.
237
- *
238
- * This method helps during development to understand how operations are classified
239
- * and can be useful for debugging type inference issues.
240
- *
241
- * @param operationId - The operation ID to inspect
242
- * @returns Boolean indicating whether the operation is a query (GET/HEAD/OPTIONS)
243
- *
244
- * @example
245
- * ```typescript
246
- * // Check if an operation is a query or mutation
247
- * const isQuery = api._debugIsQueryOperation('getPet') // true for GET
248
- * const isMutation = api._debugIsQueryOperation('createPet') // false for POST
249
- * ```
250
- */
251
- _debugIsQueryOperation: <Op extends keyof Ops>(operationId: Op) => IsQueryOperation<Ops, Op>;
252
- /**
253
- * Creates a reactive query for GET/HEAD/OPTIONS operations.
254
- *
255
- * This method creates a TanStack Query with automatic type inference, caching,
256
- * and reactive updates. Only accepts operation IDs that correspond to query operations.
257
- *
258
- * @template Op - The operation key from your operations type
259
- * @param operationId - Operation ID (must be a GET/HEAD/OPTIONS operation)
260
- * @param pathParamsOrOptions - Path parameters (for parameterized routes) or query options
261
- * @param optionsOrNull - Additional query options when path parameters are provided separately
262
- * @returns Reactive query result with data, loading state, error handling, etc.
263
- *
264
- * @example
265
- * ```typescript
266
- * // Simple query without parameters
267
- * const { data: pets, isLoading } = api.useQuery('listPets')
268
- *
269
- * // Query with path parameters
270
- * const { data: pet } = api.useQuery('getPet', { petId: '123' })
271
- *
272
- * // Query with options
273
- * const { data: pets } = api.useQuery('listPets', {
274
- * enabled: computed(() => shouldLoad.value),
275
- * onLoad: (data) => console.log('Loaded:', data)
276
- * })
277
- * ```
278
- */
279
- useQuery: <Op extends keyof Ops>(operationId: IsQueryOperation<Ops, Op> extends true ? Op : never, pathParamsOrOptions?: GetPathParameters<Ops, Op> extends Record<string, never> ? QQueryOptions<Ops, Op> : MaybeRefOrGetter<GetPathParameters<Ops, Op> | null | undefined> | QQueryOptions<Ops, Op>, optionsOrNull?: QQueryOptions<Ops, Op>) => EndpointQueryReturn<Ops, Op>;
280
- /**
281
- * Creates a reactive mutation for POST/PUT/PATCH/DELETE operations.
282
- *
283
- * This method creates a TanStack Query mutation with automatic cache invalidation,
284
- * optimistic updates, and type-safe request/response handling. Only accepts operation IDs
285
- * that correspond to mutation operations.
286
- *
287
- * @template Op - The operation key from your operations type
288
- * @param operationId - Operation ID (must be a POST/PUT/PATCH/DELETE operation)
289
- * @param pathParamsOrOptions - Path parameters (for parameterized routes) or mutation options
290
- * @param optionsOrNull - Additional mutation options when path parameters are provided separately
291
- * @returns Reactive mutation result with mutate, mutateAsync, status, etc.
292
- *
293
- * @example
294
- * ```typescript
295
- * // Simple mutation without path parameters
296
- * const createPet = api.useMutation('createPet', {
297
- * onSuccess: (data) => console.log('Created:', data),
298
- * onError: (error) => console.error('Failed:', error)
299
- * })
300
- *
301
- * // Mutation with path parameters
302
- * const updatePet = api.useMutation('updatePet', { petId: '123' })
303
- *
304
- * // Execute mutations
305
- * await createPet.mutateAsync({ data: { name: 'Fluffy', species: 'cat' } })
306
- * await updatePet.mutateAsync({ data: { name: 'Updated Name' } })
307
- * ```
308
- */
309
- useMutation: <Op extends keyof Ops>(operationId: IsQueryOperation<Ops, Op> extends false ? Op : never, pathParamsOrOptions?: GetPathParameters<Ops, Op> extends Record<string, never> ? QMutationOptions<Ops, Op> : MaybeRefOrGetter<GetPathParameters<Ops, Op> | null | undefined> | QMutationOptions<Ops, Op>, optionsOrNull?: QMutationOptions<Ops, Op>) => EndpointMutationReturn<Ops, Op>;
310
- /**
311
- * Generic endpoint composable that automatically detects operation type.
312
- *
313
- * This is a universal method that returns either a query or mutation based on the
314
- * operation's HTTP method. It provides the same functionality as useQuery/useMutation
315
- * but with automatic type detection, making it useful for generic or dynamic scenarios.
316
- *
317
- * @template Op - The operation key from your operations type
318
- * @param operationId - Any valid operation ID from your API specification
319
- * @param pathParamsOrOptions - Path parameters (for parameterized routes) or operation-specific options
320
- * @param optionsOrNull - Additional options when path parameters are provided separately
321
- * @returns Query result for GET/HEAD/OPTIONS operations, mutation result for others
322
- *
323
- * @example
324
- * ```typescript
325
- * // Automatically becomes a query for GET operations
326
- * const listEndpoint = api.useEndpoint('listPets')
327
- * // TypeScript infers this has query properties: .data, .isLoading, .refetch(), etc.
328
- *
329
- * // Automatically becomes a mutation for POST operations
330
- * const createEndpoint = api.useEndpoint('createPet')
331
- * // TypeScript infers this has mutation properties: .mutate(), .mutateAsync(), etc.
332
- *
333
- * // Use based on the detected type
334
- * const petData = listEndpoint.data // Query data
335
- * await createEndpoint.mutateAsync({ data: { name: 'Fluffy' } }) // Mutation execution
336
- * ```
337
- */
338
- useEndpoint: <Op extends keyof Ops>(operationId: Op, pathParamsOrOptions?: GetPathParameters<Ops, Op> extends Record<string, never> ? IsQueryOperation<Ops, Op> extends true ? QQueryOptions<Ops, Op> : QMutationOptions<Ops, Op> : MaybeRefOrGetter<GetPathParameters<Ops, Op> | null | undefined> | (IsQueryOperation<Ops, Op> extends true ? QQueryOptions<Ops, Op> : QMutationOptions<Ops, Op>), optionsOrNull?: IsQueryOperation<Ops, Op> extends true ? QQueryOptions<Ops, Op> : QMutationOptions<Ops, Op>) => IsQueryOperation<Ops, Op> extends true ? EndpointQueryReturn<Ops, Op> : EndpointMutationReturn<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>;
291
+ /**
292
+ * Path params input type — same as `ApiPathParams` but all values allow `undefined`
293
+ * (for reactive resolution where params may not yet be set).
294
+ */
295
+ export type ApiPathParamsInput<Ops extends AnyOps, Op extends keyof Ops> = {
296
+ [K in keyof ApiPathParams<Ops, Op>]: ApiPathParams<Ops, Op>[K] | undefined;
339
297
  };
298
+ /**
299
+ * Extract query parameters type (all optional).
300
+ * @example `ApiQueryParams<operations, 'listPets'>` → `{ limit?: number, status?: string }`
301
+ */
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 {};
340
310
  //# sourceMappingURL=types.d.ts.map