@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/dist/index.d.ts CHANGED
@@ -1,16 +1,8 @@
1
- import type { MaybeRefOrGetter } from 'vue';
2
- import { EndpointQueryReturn } from './openapi-query';
3
- import { EndpointMutationReturn } from './openapi-mutation';
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
- * Creates a type-safe OpenAPI client for Vue applications.
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, useEndpoint, and debug methods
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
- * // See documentation on how to generate types and operations automatically:
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
- * // Use in components
36
- * const { data, isLoading } = api.useQuery('listPets', {})
37
- * const createPet = api.useMutation('createPet', {})
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
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
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
- export { queryClient } from './openapi-helpers.js';
4
+ // Public function exports
5
+ export { validateMutationParams } from './types.js';
6
6
  /**
7
- * Creates a type-safe OpenAPI client for Vue applications.
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, useEndpoint, and debug methods
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
- * // See documentation on how to generate types and operations automatically:
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
- * // Use in components
30
- * const { data, isLoading } = api.useQuery('listPets', {})
31
- * const createPet = api.useMutation('createPet', {})
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
- return {
36
- /**
37
- * Debug utility to inspect operation metadata.
38
- *
39
- * @param operationId - The operation ID to debug
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
- * Creates a reactive mutation for POST/PUT/PATCH/DELETE operations.
80
- *
81
- * This composable wraps TanStack Query's useMutation for data-modifying operations
82
- * with automatic cache invalidation and optimistic updates.
83
- *
84
- * @template Op - The operation key from your operations type
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
- * Generic endpoint composable that automatically detects operation type.
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,EAAc,KAAK,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAGpG;;;;;GAKG;AACH,QAAA,MAAM,kBAAkB,EAAE,eAIxB,CAAA;AAiBF,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;yCAiCjB,EAAE,KAAG,MAAM,GAAG,IAAI;oCAevB,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"}
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"}
@@ -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
- // Helper returning the operationId prefix given an http method
15
- function getMethodPrefix(method) {
16
- const METHOD_PREFIXES = {
17
- [HttpMethod.GET]: 'get', // or 'list' depending on the operationId
18
- [HttpMethod.POST]: 'create',
19
- [HttpMethod.PUT]: 'update',
20
- [HttpMethod.PATCH]: 'update',
21
- [HttpMethod.DELETE]: 'delete',
22
- [HttpMethod.HEAD]: null,
23
- [HttpMethod.OPTIONS]: null,
24
- [HttpMethod.TRACE]: null,
25
- };
26
- return METHOD_PREFIXES[method];
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 -> listItems
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
- const operationPrefix = opInfo ? getMethodPrefix(opInfo.method) : null;
39
- // Make sure operationId matches `<operationPrefix><upercase resourceName>` pattern
40
- if (!operationPrefix || !/^[A-Z]/.test(operationIdStr.charAt(operationPrefix.length)))
41
- // If not, fallback to CRUD heuristic
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
- const resourceName = operationIdStr.substring(operationPrefix.length);
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
- // Try pluralizing the resource name (simple heuristic)
48
- let pluralResourceName = resourceName;
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 QUERY_METHODS.includes(method);
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 MUTATION_METHODS.includes(method);
120
+ return isMutationMethod(method);
89
121
  }
90
122
  return {
91
123
  getOperationInfo,