@qualisero/openapi-endpoint 0.12.3 → 0.13.2
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/README.md +32 -48
- package/dist/cli.js +740 -25
- package/dist/index.d.ts +15 -192
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -115
- package/dist/openapi-helpers.d.ts.map +1 -1
- package/dist/openapi-helpers.js +70 -38
- package/dist/openapi-mutation.d.ts +76 -108
- package/dist/openapi-mutation.d.ts.map +1 -1
- package/dist/openapi-mutation.js +39 -52
- package/dist/openapi-query.d.ts +73 -208
- package/dist/openapi-query.d.ts.map +1 -1
- package/dist/openapi-query.js +66 -71
- package/dist/openapi-utils.d.ts +30 -4
- package/dist/openapi-utils.d.ts.map +1 -1
- package/dist/openapi-utils.js +45 -56
- package/dist/types.d.ts +411 -197
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +36 -0
- package/package.json +1 -1
- package/dist/openapi-endpoint.d.ts +0 -18
- package/dist/openapi-endpoint.d.ts.map +0 -1
- package/dist/openapi-endpoint.js +0 -24
- package/dist/types-documentation.d.ts +0 -158
- package/dist/types-documentation.d.ts.map +0 -1
- package/dist/types-documentation.js +0 -9
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { Operations, GetPathParameters, OpenApiConfig, QQueryOptions, QMutationOptions, IsQueryOperation } from './types';
|
|
5
|
-
export type { OpenApiConfig, OpenApiInstance, GetResponseData, QueryClientLike, GetQueryParameters, GetPathParameters, GetRequestBody, } from './types';
|
|
6
|
-
export type { QQueryOptions, QMutationOptions, EndpointQueryReturn, EndpointMutationReturn, } from './types-documentation';
|
|
7
|
-
export { queryClient } from './openapi-helpers';
|
|
8
|
-
/** @internal */
|
|
9
|
-
export { type useEndpointQuery } from './openapi-query';
|
|
10
|
-
/** @internal */
|
|
11
|
-
export { type useEndpointMutation } from './openapi-mutation';
|
|
1
|
+
import { Operations, OpenApiConfig, OpenApiInstance } from './types';
|
|
2
|
+
export type { OpenApiConfig, OpenApiInstance, ApiResponse, ApiResponseSafe, ApiRequest, ApiPathParams, ApiPathParamsInput, ApiQueryParams, QueryClientLike, QQueryOptions, QMutationOptions, QMutationVars, CacheInvalidationOptions, EndpointQueryReturn, EndpointMutationReturn, RequiresPathParameters, HasExcessPathParams, NoPathParams, WithPathParams, QueryOpsNoPathParams, QueryOpsWithPathParams, MutationOpsNoPathParams, MutationOpsWithPathParams, AxiosRequestConfigExtended, ReactiveOr, ReactiveValue, MutateFn, MutateAsyncFn, MutateAsyncReturn, } from './types';
|
|
3
|
+
export { validateMutationParams } from './types';
|
|
12
4
|
/**
|
|
13
|
-
*
|
|
5
|
+
* Create a type-safe OpenAPI client with Vue Query integration.
|
|
14
6
|
*
|
|
15
7
|
* This is the main entry point for the library. It provides reactive composables
|
|
16
8
|
* for API operations with full TypeScript type safety based on your OpenAPI specification.
|
|
@@ -18,13 +10,12 @@ export { type useEndpointMutation } from './openapi-mutation';
|
|
|
18
10
|
* @group Setup
|
|
19
11
|
* @template Ops - The operations type, typically generated from your OpenAPI spec
|
|
20
12
|
* @param config - Configuration object containing operations metadata and axios instance
|
|
21
|
-
* @returns {OpenApiInstance<Ops>} API instance with useQuery, useMutation,
|
|
13
|
+
* @returns {OpenApiInstance<Ops>} API instance with useQuery, useMutation, and debug methods
|
|
22
14
|
*
|
|
23
15
|
* @example
|
|
24
16
|
* ```typescript
|
|
25
17
|
* import { useOpenApi } from '@qualisero/openapi-endpoint'
|
|
26
|
-
*
|
|
27
|
-
* import { openApiOperations, type OpenApiOperations } from './generated/api-operations'
|
|
18
|
+
* import { openApiOperations, type OpenApiOperations, QueryOperationId, MutationOperationId } from './generated/api-operations'
|
|
28
19
|
* import axios from 'axios'
|
|
29
20
|
*
|
|
30
21
|
* const api = useOpenApi<OpenApiOperations>({
|
|
@@ -32,183 +23,15 @@ export { type useEndpointMutation } from './openapi-mutation';
|
|
|
32
23
|
* axios: axios.create({ baseURL: 'https://api.example.com' })
|
|
33
24
|
* })
|
|
34
25
|
*
|
|
35
|
-
* //
|
|
36
|
-
* const
|
|
37
|
-
*
|
|
26
|
+
* // Queries
|
|
27
|
+
* const listQuery = api.useQuery(QueryOperationId.listPets, {
|
|
28
|
+
* queryParams: { limit: 10 }
|
|
29
|
+
* })
|
|
30
|
+
*
|
|
31
|
+
* // Mutations
|
|
32
|
+
* const createPet = api.useMutation(MutationOperationId.createPet)
|
|
33
|
+
* createPet.mutate({ data: { name: 'Fluffy' } })
|
|
38
34
|
* ```
|
|
39
35
|
*/
|
|
40
|
-
export declare function useOpenApi<Ops extends Operations<Ops>>(config: OpenApiConfig<Ops>):
|
|
41
|
-
/**
|
|
42
|
-
* Debug utility to inspect operation metadata.
|
|
43
|
-
*
|
|
44
|
-
* @param operationId - The operation ID to debug
|
|
45
|
-
* @returns Information about whether the operation is a query operation
|
|
46
|
-
*/
|
|
47
|
-
_debugIsQueryOperation: <Op extends keyof Ops>(operationId: Op) => IsQueryOperation<Ops, Op>;
|
|
48
|
-
/**
|
|
49
|
-
* Creates a reactive query for GET operations.
|
|
50
|
-
*
|
|
51
|
-
* This composable wraps TanStack Query for read-only operations with automatic
|
|
52
|
-
* type inference, caching, and reactive updates.
|
|
53
|
-
*
|
|
54
|
-
* @template Op - The operation key from your operations type
|
|
55
|
-
* @param operationId - Operation ID (must be a GET operation)
|
|
56
|
-
* @param pathParamsOrOptions - Path parameters or query options
|
|
57
|
-
* @param optionsOrNull - Additional query options when path params are provided
|
|
58
|
-
* @returns Reactive query result with data, loading state, error handling, etc.
|
|
59
|
-
*
|
|
60
|
-
* @example
|
|
61
|
-
* ```typescript
|
|
62
|
-
* // Query without path parameters
|
|
63
|
-
* const { data: pets, isLoading } = api.useQuery(OperationId.listPets, {
|
|
64
|
-
* enabled: true,
|
|
65
|
-
* onLoad: (data) => console.log('Loaded:', data)
|
|
66
|
-
* })
|
|
67
|
-
*
|
|
68
|
-
* // Query with path parameters
|
|
69
|
-
* const { data: pet } = api.useQuery(OperationId.getPet, { petId: '123' }, {
|
|
70
|
-
* enabled: computed(() => Boolean(petId.value))
|
|
71
|
-
* })
|
|
72
|
-
* ```
|
|
73
|
-
*/
|
|
74
|
-
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>;
|
|
75
|
-
/**
|
|
76
|
-
* Creates a reactive mutation for POST/PUT/PATCH/DELETE operations.
|
|
77
|
-
*
|
|
78
|
-
* This composable wraps TanStack Query's useMutation for data-modifying operations
|
|
79
|
-
* with automatic cache invalidation and optimistic updates.
|
|
80
|
-
*
|
|
81
|
-
* @template Op - The operation key from your operations type
|
|
82
|
-
* @param operationId - Operation ID (must be a mutation operation)
|
|
83
|
-
* @param pathParamsOrOptions - Path parameters or mutation options
|
|
84
|
-
* @param optionsOrNull - Additional mutation options when path params are provided
|
|
85
|
-
* @returns Reactive mutation result with mutate, mutateAsync, status, etc.
|
|
86
|
-
*
|
|
87
|
-
* @example
|
|
88
|
-
* ```typescript
|
|
89
|
-
* // Mutation without path parameters
|
|
90
|
-
* const createPet = api.useMutation(OperationId.createPet, {
|
|
91
|
-
* onSuccess: (data) => console.log('Created:', data),
|
|
92
|
-
* onError: (error) => console.error('Failed:', error)
|
|
93
|
-
* })
|
|
94
|
-
*
|
|
95
|
-
* // Mutation with path parameters
|
|
96
|
-
* const updatePet = api.useMutation(OperationId.updatePet, { petId: '123' }, {
|
|
97
|
-
* onSuccess: async () => {
|
|
98
|
-
* // Automatically invalidates related queries
|
|
99
|
-
* }
|
|
100
|
-
* })
|
|
101
|
-
*
|
|
102
|
-
* // Execute the mutation
|
|
103
|
-
* await createPet.mutateAsync({ data: { name: 'Fluffy' } })
|
|
104
|
-
* ```
|
|
105
|
-
*/
|
|
106
|
-
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>) => {
|
|
107
|
-
data: import("vue").ComputedRef<import("axios").AxiosResponse<import("./types").GetResponseData<Ops, Op>, any, {}> | undefined>;
|
|
108
|
-
isEnabled: import("vue").ComputedRef<boolean>;
|
|
109
|
-
extraPathParams: import("vue").Ref<GetPathParameters<Ops, Op>, GetPathParameters<Ops, Op>>;
|
|
110
|
-
pathParams: import("vue").ComputedRef<GetPathParameters<Ops, Op>>;
|
|
111
|
-
context: import("vue").Ref<unknown, unknown>;
|
|
112
|
-
error: import("vue").Ref<null, null>;
|
|
113
|
-
isError: import("vue").Ref<false, false>;
|
|
114
|
-
isPending: import("vue").Ref<false, false>;
|
|
115
|
-
isSuccess: import("vue").Ref<false, false>;
|
|
116
|
-
status: import("vue").Ref<"idle", "idle">;
|
|
117
|
-
failureCount: import("vue").Ref<number, number>;
|
|
118
|
-
failureReason: import("vue").Ref<Error | null, Error | null>;
|
|
119
|
-
isPaused: import("vue").Ref<boolean, boolean>;
|
|
120
|
-
variables: import("vue").Ref<undefined, undefined>;
|
|
121
|
-
isIdle: import("vue").Ref<true, true>;
|
|
122
|
-
submittedAt: import("vue").Ref<number, number>;
|
|
123
|
-
mutate: (variables: import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, options?: import("@tanstack/query-core").MutateOptions<import("axios").AxiosResponse<any, any, {}>, Error, import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, unknown> | undefined) => void;
|
|
124
|
-
mutateAsync: import("@tanstack/query-core").MutateFunction<import("axios").AxiosResponse<any, any, {}>, Error, import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, unknown>;
|
|
125
|
-
reset: import("@tanstack/query-core").MutationObserverResult<TData, TError, TVariables, TOnMutateResult>["reset"];
|
|
126
|
-
} | {
|
|
127
|
-
data: import("vue").ComputedRef<import("axios").AxiosResponse<import("./types").GetResponseData<Ops, Op>, any, {}> | undefined>;
|
|
128
|
-
isEnabled: import("vue").ComputedRef<boolean>;
|
|
129
|
-
extraPathParams: import("vue").Ref<GetPathParameters<Ops, Op>, GetPathParameters<Ops, Op>>;
|
|
130
|
-
pathParams: import("vue").ComputedRef<GetPathParameters<Ops, Op>>;
|
|
131
|
-
context: import("vue").Ref<unknown, unknown>;
|
|
132
|
-
error: import("vue").Ref<null, null>;
|
|
133
|
-
isError: import("vue").Ref<false, false>;
|
|
134
|
-
isPending: import("vue").Ref<true, true>;
|
|
135
|
-
isSuccess: import("vue").Ref<false, false>;
|
|
136
|
-
status: import("vue").Ref<"pending", "pending">;
|
|
137
|
-
failureCount: import("vue").Ref<number, number>;
|
|
138
|
-
failureReason: import("vue").Ref<Error | null, Error | null>;
|
|
139
|
-
isPaused: import("vue").Ref<boolean, boolean>;
|
|
140
|
-
variables: import("@vue/shared").IfAny<import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, import("vue").Ref<import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>>, [import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>] extends [import("vue").Ref<any, any>] ? import("vue").Ref<any, any> & (import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>) : import("vue").Ref<import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>>>;
|
|
141
|
-
isIdle: import("vue").Ref<false, false>;
|
|
142
|
-
submittedAt: import("vue").Ref<number, number>;
|
|
143
|
-
mutate: (variables: import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, options?: import("@tanstack/query-core").MutateOptions<import("axios").AxiosResponse<any, any, {}>, Error, import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, unknown> | undefined) => void;
|
|
144
|
-
mutateAsync: import("@tanstack/query-core").MutateFunction<import("axios").AxiosResponse<any, any, {}>, Error, import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, unknown>;
|
|
145
|
-
reset: import("@tanstack/query-core").MutationObserverResult<TData, TError, TVariables, TOnMutateResult>["reset"];
|
|
146
|
-
} | {
|
|
147
|
-
data: import("vue").ComputedRef<import("axios").AxiosResponse<import("./types").GetResponseData<Ops, Op>, any, {}> | undefined>;
|
|
148
|
-
isEnabled: import("vue").ComputedRef<boolean>;
|
|
149
|
-
extraPathParams: import("vue").Ref<GetPathParameters<Ops, Op>, GetPathParameters<Ops, Op>>;
|
|
150
|
-
pathParams: import("vue").ComputedRef<GetPathParameters<Ops, Op>>;
|
|
151
|
-
context: import("vue").Ref<unknown, unknown>;
|
|
152
|
-
error: import("vue").Ref<Error, Error>;
|
|
153
|
-
isError: import("vue").Ref<true, true>;
|
|
154
|
-
isPending: import("vue").Ref<false, false>;
|
|
155
|
-
isSuccess: import("vue").Ref<false, false>;
|
|
156
|
-
status: import("vue").Ref<"error", "error">;
|
|
157
|
-
failureCount: import("vue").Ref<number, number>;
|
|
158
|
-
failureReason: import("vue").Ref<Error | null, Error | null>;
|
|
159
|
-
isPaused: import("vue").Ref<boolean, boolean>;
|
|
160
|
-
variables: import("@vue/shared").IfAny<import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, import("vue").Ref<import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>>, [import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>] extends [import("vue").Ref<any, any>] ? import("vue").Ref<any, any> & (import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>) : import("vue").Ref<import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>>>;
|
|
161
|
-
isIdle: import("vue").Ref<false, false>;
|
|
162
|
-
submittedAt: import("vue").Ref<number, number>;
|
|
163
|
-
mutate: (variables: import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, options?: import("@tanstack/query-core").MutateOptions<import("axios").AxiosResponse<any, any, {}>, Error, import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, unknown> | undefined) => void;
|
|
164
|
-
mutateAsync: import("@tanstack/query-core").MutateFunction<import("axios").AxiosResponse<any, any, {}>, Error, import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, unknown>;
|
|
165
|
-
reset: import("@tanstack/query-core").MutationObserverResult<TData, TError, TVariables, TOnMutateResult>["reset"];
|
|
166
|
-
} | {
|
|
167
|
-
data: import("vue").ComputedRef<import("axios").AxiosResponse<import("./types").GetResponseData<Ops, Op>, any, {}> | undefined>;
|
|
168
|
-
isEnabled: import("vue").ComputedRef<boolean>;
|
|
169
|
-
extraPathParams: import("vue").Ref<GetPathParameters<Ops, Op>, GetPathParameters<Ops, Op>>;
|
|
170
|
-
pathParams: import("vue").ComputedRef<GetPathParameters<Ops, Op>>;
|
|
171
|
-
context: import("vue").Ref<unknown, unknown>;
|
|
172
|
-
error: import("vue").Ref<null, null>;
|
|
173
|
-
isError: import("vue").Ref<false, false>;
|
|
174
|
-
isPending: import("vue").Ref<false, false>;
|
|
175
|
-
isSuccess: import("vue").Ref<true, true>;
|
|
176
|
-
status: import("vue").Ref<"success", "success">;
|
|
177
|
-
failureCount: import("vue").Ref<number, number>;
|
|
178
|
-
failureReason: import("vue").Ref<Error | null, Error | null>;
|
|
179
|
-
isPaused: import("vue").Ref<boolean, boolean>;
|
|
180
|
-
variables: import("@vue/shared").IfAny<import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, import("vue").Ref<import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>>, [import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>] extends [import("vue").Ref<any, any>] ? import("vue").Ref<any, any> & (import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>) : import("vue").Ref<import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>>>;
|
|
181
|
-
isIdle: import("vue").Ref<false, false>;
|
|
182
|
-
submittedAt: import("vue").Ref<number, number>;
|
|
183
|
-
mutate: (variables: import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, options?: import("@tanstack/query-core").MutateOptions<import("axios").AxiosResponse<any, any, {}>, Error, import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, unknown> | undefined) => void;
|
|
184
|
-
mutateAsync: import("@tanstack/query-core").MutateFunction<import("axios").AxiosResponse<any, any, {}>, Error, import("./types").GetRequestBody<Ops, Op> extends never ? void | import("./types").QMutationVars<Ops, Op> : import("./types").QMutationVars<Ops, Op>, unknown>;
|
|
185
|
-
reset: import("@tanstack/query-core").MutationObserverResult<TData, TError, TVariables, TOnMutateResult>["reset"];
|
|
186
|
-
};
|
|
187
|
-
/**
|
|
188
|
-
* Generic endpoint composable that automatically detects operation type.
|
|
189
|
-
*
|
|
190
|
-
* This is a universal composable that returns either a query or mutation based
|
|
191
|
-
* on the operation's HTTP method. Use this when you want unified handling.
|
|
192
|
-
*
|
|
193
|
-
* @template Op - The operation key from your operations type
|
|
194
|
-
* @param operationId - Any operation ID
|
|
195
|
-
* @param pathParamsOrOptions - Path parameters or operation options
|
|
196
|
-
* @param optionsOrNull - Additional options when path params are provided
|
|
197
|
-
* @returns Query result for GET operations, mutation result for others
|
|
198
|
-
*
|
|
199
|
-
* @example
|
|
200
|
-
* ```typescript
|
|
201
|
-
* // Automatically becomes a query for GET operations
|
|
202
|
-
* const listEndpoint = api.useEndpoint(OperationId.listPets)
|
|
203
|
-
*
|
|
204
|
-
* // Automatically becomes a mutation for POST operations
|
|
205
|
-
* const createEndpoint = api.useEndpoint(OperationId.createPet)
|
|
206
|
-
*
|
|
207
|
-
* // TypeScript knows the correct return type based on the operation
|
|
208
|
-
* const data = listEndpoint.data // Query data
|
|
209
|
-
* await createEndpoint.mutateAsync({ data: petData }) // Mutation execution
|
|
210
|
-
* ```
|
|
211
|
-
*/
|
|
212
|
-
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>;
|
|
213
|
-
};
|
|
36
|
+
export declare function useOpenApi<Ops extends Operations<Ops>>(config: OpenApiConfig<Ops>): OpenApiInstance<Ops>;
|
|
214
37
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,UAAU,EAGV,aAAa,EACb,eAAe,EAShB,MAAM,SAAS,CAAA;AAIhB,YAAY,EACV,aAAa,EACb,eAAe,EACf,WAAW,EACX,eAAe,EACf,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,wBAAwB,EACxB,mBAAmB,EACnB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,YAAY,EACZ,cAAc,EACd,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,yBAAyB,EACzB,0BAA0B,EAC1B,UAAU,EACV,aAAa,EACb,QAAQ,EACR,aAAa,EACb,iBAAiB,GAClB,MAAM,SAAS,CAAA;AAGhB,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAA;AAEhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,UAAU,CAAC,GAAG,SAAS,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,GAAG,CAAC,CA2JxG"}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { useEndpoint } from './openapi-endpoint.js';
|
|
2
1
|
import { useEndpointQuery } from './openapi-query.js';
|
|
3
2
|
import { useEndpointMutation } from './openapi-mutation.js';
|
|
4
3
|
import { getHelpers } from './openapi-helpers.js';
|
|
5
|
-
|
|
4
|
+
// Public function exports
|
|
5
|
+
export { validateMutationParams } from './types.js';
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* Create a type-safe OpenAPI client with Vue Query integration.
|
|
8
8
|
*
|
|
9
9
|
* This is the main entry point for the library. It provides reactive composables
|
|
10
10
|
* for API operations with full TypeScript type safety based on your OpenAPI specification.
|
|
@@ -12,13 +12,12 @@ export { queryClient } from './openapi-helpers.js';
|
|
|
12
12
|
* @group Setup
|
|
13
13
|
* @template Ops - The operations type, typically generated from your OpenAPI spec
|
|
14
14
|
* @param config - Configuration object containing operations metadata and axios instance
|
|
15
|
-
* @returns {OpenApiInstance<Ops>} API instance with useQuery, useMutation,
|
|
15
|
+
* @returns {OpenApiInstance<Ops>} API instance with useQuery, useMutation, and debug methods
|
|
16
16
|
*
|
|
17
17
|
* @example
|
|
18
18
|
* ```typescript
|
|
19
19
|
* import { useOpenApi } from '@qualisero/openapi-endpoint'
|
|
20
|
-
*
|
|
21
|
-
* import { openApiOperations, type OpenApiOperations } from './generated/api-operations'
|
|
20
|
+
* import { openApiOperations, type OpenApiOperations, QueryOperationId, MutationOperationId } from './generated/api-operations'
|
|
22
21
|
* import axios from 'axios'
|
|
23
22
|
*
|
|
24
23
|
* const api = useOpenApi<OpenApiOperations>({
|
|
@@ -26,118 +25,34 @@ export { queryClient } from './openapi-helpers.js';
|
|
|
26
25
|
* axios: axios.create({ baseURL: 'https://api.example.com' })
|
|
27
26
|
* })
|
|
28
27
|
*
|
|
29
|
-
* //
|
|
30
|
-
* const
|
|
31
|
-
*
|
|
28
|
+
* // Queries
|
|
29
|
+
* const listQuery = api.useQuery(QueryOperationId.listPets, {
|
|
30
|
+
* queryParams: { limit: 10 }
|
|
31
|
+
* })
|
|
32
|
+
*
|
|
33
|
+
* // Mutations
|
|
34
|
+
* const createPet = api.useMutation(MutationOperationId.createPet)
|
|
35
|
+
* createPet.mutate({ data: { name: 'Fluffy' } })
|
|
32
36
|
* ```
|
|
33
37
|
*/
|
|
34
38
|
export function useOpenApi(config) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
* @returns Information about whether the operation is a query operation
|
|
41
|
-
*/
|
|
42
|
-
_debugIsQueryOperation: function (operationId) {
|
|
43
|
-
const helpers = getHelpers(config);
|
|
44
|
-
const info = helpers.getOperationInfo(operationId);
|
|
45
|
-
console.log('Operation Info:', info);
|
|
46
|
-
return {};
|
|
47
|
-
},
|
|
48
|
-
/**
|
|
49
|
-
* Creates a reactive query for GET operations.
|
|
50
|
-
*
|
|
51
|
-
* This composable wraps TanStack Query for read-only operations with automatic
|
|
52
|
-
* type inference, caching, and reactive updates.
|
|
53
|
-
*
|
|
54
|
-
* @template Op - The operation key from your operations type
|
|
55
|
-
* @param operationId - Operation ID (must be a GET operation)
|
|
56
|
-
* @param pathParamsOrOptions - Path parameters or query options
|
|
57
|
-
* @param optionsOrNull - Additional query options when path params are provided
|
|
58
|
-
* @returns Reactive query result with data, loading state, error handling, etc.
|
|
59
|
-
*
|
|
60
|
-
* @example
|
|
61
|
-
* ```typescript
|
|
62
|
-
* // Query without path parameters
|
|
63
|
-
* const { data: pets, isLoading } = api.useQuery(OperationId.listPets, {
|
|
64
|
-
* enabled: true,
|
|
65
|
-
* onLoad: (data) => console.log('Loaded:', data)
|
|
66
|
-
* })
|
|
67
|
-
*
|
|
68
|
-
* // Query with path parameters
|
|
69
|
-
* const { data: pet } = api.useQuery(OperationId.getPet, { petId: '123' }, {
|
|
70
|
-
* enabled: computed(() => Boolean(petId.value))
|
|
71
|
-
* })
|
|
72
|
-
* ```
|
|
73
|
-
*/
|
|
74
|
-
useQuery: function (operationId, pathParamsOrOptions, optionsOrNull) {
|
|
75
|
-
const helpers = getHelpers(config);
|
|
39
|
+
function useQuery(operationId, pathParamsOrOptions, optionsOrNull) {
|
|
40
|
+
const helpers = getHelpers(config);
|
|
41
|
+
const { path } = helpers.getOperationInfo(operationId);
|
|
42
|
+
const hasPathParams = path.includes('{');
|
|
43
|
+
if (hasPathParams) {
|
|
76
44
|
return useEndpointQuery(operationId, helpers, pathParamsOrOptions, optionsOrNull);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
* @param operationId - Operation ID (must be a mutation operation)
|
|
86
|
-
* @param pathParamsOrOptions - Path parameters or mutation options
|
|
87
|
-
* @param optionsOrNull - Additional mutation options when path params are provided
|
|
88
|
-
* @returns Reactive mutation result with mutate, mutateAsync, status, etc.
|
|
89
|
-
*
|
|
90
|
-
* @example
|
|
91
|
-
* ```typescript
|
|
92
|
-
* // Mutation without path parameters
|
|
93
|
-
* const createPet = api.useMutation(OperationId.createPet, {
|
|
94
|
-
* onSuccess: (data) => console.log('Created:', data),
|
|
95
|
-
* onError: (error) => console.error('Failed:', error)
|
|
96
|
-
* })
|
|
97
|
-
*
|
|
98
|
-
* // Mutation with path parameters
|
|
99
|
-
* const updatePet = api.useMutation(OperationId.updatePet, { petId: '123' }, {
|
|
100
|
-
* onSuccess: async () => {
|
|
101
|
-
* // Automatically invalidates related queries
|
|
102
|
-
* }
|
|
103
|
-
* })
|
|
104
|
-
*
|
|
105
|
-
* // Execute the mutation
|
|
106
|
-
* await createPet.mutateAsync({ data: { name: 'Fluffy' } })
|
|
107
|
-
* ```
|
|
108
|
-
*/
|
|
109
|
-
useMutation: function (operationId, pathParamsOrOptions, optionsOrNull) {
|
|
110
|
-
const helpers = getHelpers(config);
|
|
45
|
+
}
|
|
46
|
+
return useEndpointQuery(operationId, helpers, undefined, pathParamsOrOptions);
|
|
47
|
+
}
|
|
48
|
+
function useMutation(operationId, pathParamsOrOptions, optionsOrNull) {
|
|
49
|
+
const helpers = getHelpers(config);
|
|
50
|
+
const { path } = helpers.getOperationInfo(operationId);
|
|
51
|
+
const hasPathParams = path.includes('{');
|
|
52
|
+
if (hasPathParams) {
|
|
111
53
|
return useEndpointMutation(operationId, helpers, pathParamsOrOptions, optionsOrNull);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
* This is a universal composable that returns either a query or mutation based
|
|
117
|
-
* on the operation's HTTP method. Use this when you want unified handling.
|
|
118
|
-
*
|
|
119
|
-
* @template Op - The operation key from your operations type
|
|
120
|
-
* @param operationId - Any operation ID
|
|
121
|
-
* @param pathParamsOrOptions - Path parameters or operation options
|
|
122
|
-
* @param optionsOrNull - Additional options when path params are provided
|
|
123
|
-
* @returns Query result for GET operations, mutation result for others
|
|
124
|
-
*
|
|
125
|
-
* @example
|
|
126
|
-
* ```typescript
|
|
127
|
-
* // Automatically becomes a query for GET operations
|
|
128
|
-
* const listEndpoint = api.useEndpoint(OperationId.listPets)
|
|
129
|
-
*
|
|
130
|
-
* // Automatically becomes a mutation for POST operations
|
|
131
|
-
* const createEndpoint = api.useEndpoint(OperationId.createPet)
|
|
132
|
-
*
|
|
133
|
-
* // TypeScript knows the correct return type based on the operation
|
|
134
|
-
* const data = listEndpoint.data // Query data
|
|
135
|
-
* await createEndpoint.mutateAsync({ data: petData }) // Mutation execution
|
|
136
|
-
* ```
|
|
137
|
-
*/
|
|
138
|
-
useEndpoint: function (operationId, pathParamsOrOptions, optionsOrNull) {
|
|
139
|
-
const helpers = getHelpers(config);
|
|
140
|
-
return useEndpoint(operationId, helpers, pathParamsOrOptions, optionsOrNull);
|
|
141
|
-
},
|
|
142
|
-
};
|
|
54
|
+
}
|
|
55
|
+
return useEndpointMutation(operationId, helpers, undefined, pathParamsOrOptions);
|
|
56
|
+
}
|
|
57
|
+
return { useQuery, useMutation };
|
|
143
58
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openapi-helpers.d.ts","sourceRoot":"","sources":["../src/openapi-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"openapi-helpers.d.ts","sourceRoot":"","sources":["../src/openapi-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,aAAa,EAClB,aAAa,EACb,UAAU,EACV,eAAe,EAGhB,MAAM,SAAS,CAAA;AAGhB;;;;;GAKG;AACH,QAAA,MAAM,kBAAkB,EAAE,eAIxB,CAAA;AAiEF,wBAAgB,UAAU,CAAC,GAAG,SAAS,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,MAAM,GAAG,EAAE,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC;oCAE/D,EAAE,KAAG,aAAa;wCAMd,EAAE,KAAG,MAAM,GAAG,IAAI;yCA6BjB,EAAE,KAAG,MAAM,GAAG,IAAI;oCAWvB,EAAE,KAAG,OAAO;uCAMT,EAAE,KAAG,OAAO;;;EAcvD;AAED,MAAM,MAAM,cAAc,CAAC,GAAG,SAAS,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,MAAM,GAAG,IAAI,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAA;AAEtH,OAAO,EAAE,kBAAkB,IAAI,WAAW,EAAE,CAAA"}
|
package/dist/openapi-helpers.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HttpMethod } from './types.js';
|
|
1
|
+
import { HttpMethod, isQueryMethod, isMutationMethod, } from './types.js';
|
|
2
2
|
import { QueryClient } from '@tanstack/vue-query';
|
|
3
3
|
/**
|
|
4
4
|
* Default QueryClient instance with pre-configured options.
|
|
@@ -11,19 +11,63 @@ const defaultQueryClient = new QueryClient({
|
|
|
11
11
|
queries: { staleTime: 1000 * 60 * 5 },
|
|
12
12
|
},
|
|
13
13
|
});
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Suffixes that require adding 'es' for pluralization (e.g., 'box' -> 'boxes').
|
|
16
|
+
*/
|
|
17
|
+
const PLURAL_ES_SUFFIXES = ['s', 'x', 'z', 'ch', 'sh', 'o'];
|
|
18
|
+
/**
|
|
19
|
+
* Mapping of HTTP methods to their CRUD operation name prefixes.
|
|
20
|
+
* Used to infer resource names from operation IDs.
|
|
21
|
+
*/
|
|
22
|
+
const CRUD_PREFIXES = {
|
|
23
|
+
[HttpMethod.GET]: { singular: 'get', plural: 'list' },
|
|
24
|
+
[HttpMethod.POST]: { singular: 'create', plural: 'create' },
|
|
25
|
+
[HttpMethod.PUT]: { singular: 'update', plural: 'update' },
|
|
26
|
+
[HttpMethod.PATCH]: { singular: 'update', plural: 'update' },
|
|
27
|
+
[HttpMethod.DELETE]: { singular: 'delete', plural: 'delete' },
|
|
28
|
+
[HttpMethod.HEAD]: null,
|
|
29
|
+
[HttpMethod.OPTIONS]: null,
|
|
30
|
+
[HttpMethod.TRACE]: null,
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Extracts the resource name from an operation ID based on its HTTP method.
|
|
34
|
+
* @param operationId - The operation ID (e.g., 'createPet', 'updatePet')
|
|
35
|
+
* @param method - The HTTP method
|
|
36
|
+
* @returns The resource name (e.g., 'Pet') or null if not extractable
|
|
37
|
+
*/
|
|
38
|
+
function getResourceName(operationId, method) {
|
|
39
|
+
const prefixes = CRUD_PREFIXES[method];
|
|
40
|
+
if (!prefixes)
|
|
41
|
+
return null;
|
|
42
|
+
// Try singular prefix first (get, create, update, delete)
|
|
43
|
+
if (operationId.startsWith(prefixes.singular)) {
|
|
44
|
+
const remaining = operationId.slice(prefixes.singular.length);
|
|
45
|
+
if (remaining.length > 0 && /^[A-Z]/.test(remaining)) {
|
|
46
|
+
return remaining;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Try plural prefix (list)
|
|
50
|
+
if (operationId.startsWith(prefixes.plural)) {
|
|
51
|
+
const remaining = operationId.slice(prefixes.plural.length);
|
|
52
|
+
if (remaining.length > 0 && /^[A-Z]/.test(remaining)) {
|
|
53
|
+
return remaining;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Pluralizes a resource name using common English rules.
|
|
60
|
+
* @param name - The singular resource name
|
|
61
|
+
* @returns The pluralized name
|
|
62
|
+
*/
|
|
63
|
+
function pluralizeResource(name) {
|
|
64
|
+
if (name.endsWith('y')) {
|
|
65
|
+
return name.slice(0, -1) + 'ies';
|
|
66
|
+
}
|
|
67
|
+
else if (PLURAL_ES_SUFFIXES.some((suffix) => name.endsWith(suffix))) {
|
|
68
|
+
return name + 'es';
|
|
69
|
+
}
|
|
70
|
+
return name + 's';
|
|
27
71
|
}
|
|
28
72
|
export function getHelpers(config) {
|
|
29
73
|
// Helper function to get operation info by ID
|
|
@@ -31,32 +75,23 @@ export function getHelpers(config) {
|
|
|
31
75
|
return config.operations[operationId];
|
|
32
76
|
}
|
|
33
77
|
// Helper to return a url path for matching list endpoint (e.g. /items/123 -> /items/)
|
|
34
|
-
// Based on operationId prefix: createItem, updateItem ->
|
|
78
|
+
// Based on operationId prefix: createItem, updateItem -> listItem
|
|
35
79
|
function getListOperationPath(operationId) {
|
|
36
80
|
const opInfo = getOperationInfo(operationId);
|
|
37
81
|
const operationIdStr = operationId;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (!
|
|
41
|
-
//
|
|
82
|
+
// Try to extract resource name from operation ID
|
|
83
|
+
const resourceName = getResourceName(operationIdStr, opInfo.method);
|
|
84
|
+
if (!resourceName) {
|
|
85
|
+
// Fallback to CRUD heuristic based on path structure
|
|
42
86
|
return getCrudListPathPrefix(operationId);
|
|
43
|
-
|
|
87
|
+
}
|
|
88
|
+
// Try to find list operation with same resource name
|
|
44
89
|
const listOperationId = `list${resourceName}`;
|
|
45
90
|
let listOperationInfo = getOperationInfo(listOperationId);
|
|
91
|
+
// If not found, try pluralized version
|
|
46
92
|
if (!listOperationInfo) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const addEsSuffixes = ['s', 'x', 'z', 'ch', 'sh', 'o'];
|
|
50
|
-
if (resourceName.endsWith('y')) {
|
|
51
|
-
pluralResourceName = resourceName.slice(0, -1) + 'ies';
|
|
52
|
-
}
|
|
53
|
-
else if (addEsSuffixes.some((suffix) => resourceName.endsWith(suffix))) {
|
|
54
|
-
pluralResourceName = resourceName + 'es';
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
pluralResourceName = resourceName + 's';
|
|
58
|
-
}
|
|
59
|
-
listOperationInfo = getOperationInfo(`list${pluralResourceName}`);
|
|
93
|
+
const pluralName = pluralizeResource(resourceName);
|
|
94
|
+
listOperationInfo = getOperationInfo(`list${pluralName}`);
|
|
60
95
|
}
|
|
61
96
|
if (listOperationInfo && listOperationInfo.method === HttpMethod.GET) {
|
|
62
97
|
return listOperationInfo.path;
|
|
@@ -74,18 +109,15 @@ export function getHelpers(config) {
|
|
|
74
109
|
}
|
|
75
110
|
return null;
|
|
76
111
|
}
|
|
77
|
-
// Constants for HTTP method categorization
|
|
78
|
-
const QUERY_METHODS = [HttpMethod.GET, HttpMethod.HEAD, HttpMethod.OPTIONS];
|
|
79
|
-
const MUTATION_METHODS = [HttpMethod.POST, HttpMethod.PUT, HttpMethod.PATCH, HttpMethod.DELETE];
|
|
80
112
|
// Helper to check if an operation is a query method at runtime
|
|
81
113
|
function isQueryOperation(operationId) {
|
|
82
114
|
const { method } = getOperationInfo(operationId);
|
|
83
|
-
return
|
|
115
|
+
return isQueryMethod(method);
|
|
84
116
|
}
|
|
85
117
|
// Helper to check if an operation is a mutation method at runtime
|
|
86
118
|
function isMutationOperation(operationId) {
|
|
87
119
|
const { method } = getOperationInfo(operationId);
|
|
88
|
-
return
|
|
120
|
+
return isMutationMethod(method);
|
|
89
121
|
}
|
|
90
122
|
return {
|
|
91
123
|
getOperationInfo,
|