@qualisero/openapi-endpoint 0.12.1 → 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 CHANGED
@@ -4,6 +4,7 @@
4
4
  [![CI](https://github.com/qualisero/openapi-endpoint/workflows/CI/badge.svg)](https://github.com/qualisero/openapi-endpoint/actions/workflows/ci.yml)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
6
  [![npm bundle size](https://img.shields.io/bundlephobia/minzip/@qualisero/openapi-endpoint)](https://bundlephobia.com/package/@qualisero/openapi-endpoint)
7
+ [![Documentation](https://img.shields.io/badge/docs-online-brightgreen.svg)](https://qualisero.github.io/openapi-endpoint/)
7
8
 
8
9
  Turns your `openapi.json` into typesafe API composables using Vue Query (TanStack Query): guaranteeing that your frontend and backend share the same contract.
9
10
 
@@ -12,9 +13,9 @@ Turns your `openapi.json` into typesafe API composables using Vue Query (TanStac
12
13
  Let's you get TanStack Vue Query composables that enforce consistency (name of endpoints, typing) with your API's `openapi.json` file:
13
14
 
14
15
  ```typescript
15
- const { data, isLoading } = api.useQuery(OperationId.getPet, { petId: '123' })
16
+ const { data, isLoading } = api.useQuery(QueryOperationId.getPet, { petId: '123' })
16
17
 
17
- const createPetMutation = api.useMutation(OperationId.createPet)
18
+ const createPetMutation = api.useMutation(MutationOperationId.createPet)
18
19
  createPetMutation.mutate({ data: { name: 'Fluffy', species: 'cat' } })
19
20
  ```
20
21
 
@@ -51,7 +52,12 @@ import { useOpenApi } from '@qualisero/openapi-endpoint'
51
52
  import axios from 'axios'
52
53
 
53
54
  // Import your auto-generated operations (includes both metadata and types)
54
- import { OperationId, openApiOperations, type OpenApiOperations } from './generated/api-operations'
55
+ import {
56
+ QueryOperationId,
57
+ MutationOperationId,
58
+ openApiOperations,
59
+ type OpenApiOperations,
60
+ } from './generated/api-operations'
55
61
 
56
62
  // Create axios instance
57
63
  const axiosInstance = axios.create({
@@ -65,21 +71,21 @@ const api = useOpenApi<OpenApiOperations>({
65
71
  })
66
72
 
67
73
  // Export for use in other parts of your application
68
- export { api, OperationId }
74
+ export { api, QueryOperationId, MutationOperationId, OperationId }
69
75
  ```
70
76
 
71
77
  ### 2. Use the API in your components
72
78
 
73
79
  ```typescript
74
80
  // In your Vue components
75
- import { api, OperationId } from './api/init'
81
+ import { api, QueryOperationId, MutationOperationId } from './api/init'
76
82
 
77
83
  // Use queries for GET operations
78
- const { data: pets, isLoading } = api.useQuery(OperationId.listPets)
79
- const { data: pet } = api.useQuery(OperationId.getPet, { petId: '123' })
84
+ const { data: pets, isLoading } = api.useQuery(QueryOperationId.listPets)
85
+ const { data: pet } = api.useQuery(QueryOperationId.getPet, { petId: '123' })
80
86
 
81
87
  // Use mutations for POST/PUT/PATCH/DELETE operations
82
- const createPetMutation = api.useMutation(OperationId.createPet)
88
+ const createPetMutation = api.useMutation(MutationOperationId.createPet)
83
89
 
84
90
  // Execute mutations
85
91
  await createPetMutation.mutateAsync({
@@ -95,10 +101,10 @@ The library supports type-safe, reactive query parameters that automatically tri
95
101
 
96
102
  ```typescript
97
103
  import { ref, computed } from 'vue'
98
- import { api, OperationId } from './api/init'
104
+ import { api, QueryOperationId } from './api/init'
99
105
 
100
106
  // Static query parameters
101
- const { data: pets } = api.useQuery(OperationId.listPets, {
107
+ const { data: pets } = api.useQuery(QueryOperationId.listPets, {
102
108
  queryParams: { limit: 10 },
103
109
  })
104
110
  // Results in: GET /pets?limit=10
@@ -107,7 +113,7 @@ const { data: pets } = api.useQuery(OperationId.listPets, {
107
113
  const limit = ref(10)
108
114
  const status = ref<'available' | 'pending' | 'sold'>('available')
109
115
 
110
- const petsQuery = api.useQuery(OperationId.listPets, {
116
+ const petsQuery = api.useQuery(QueryOperationId.listPets, {
111
117
  queryParams: computed(() => ({
112
118
  limit: limit.value,
113
119
  status: status.value,
@@ -121,7 +127,7 @@ status.value = 'pending'
121
127
 
122
128
  // Combine with path parameters
123
129
  const userPetsQuery = api.useQuery(
124
- OperationId.listUserPets,
130
+ QueryOperationId.listUserPets,
125
131
  computed(() => ({ userId: userId.value })),
126
132
  {
127
133
  queryParams: computed(() => ({
@@ -139,27 +145,6 @@ const userPetsQuery = api.useQuery(
139
145
  - **Automatic refetch**: Changes to query params trigger automatic refetch via TanStack Query's key mechanism
140
146
  - **Backward compatible**: Works alongside existing `axiosOptions.params`
141
147
 
142
- ### Automatic Operation Type Detection with `api.useEndpoint`
143
-
144
- The `api.useEndpoint` method automatically detects whether an operation is a query (GET/HEAD/OPTIONS) or mutation (POST/PUT/PATCH/DELETE) based on the HTTP method defined in your OpenAPI specification:
145
-
146
- ```typescript
147
- import { ref, computed } from 'vue'
148
- import { api, OperationId } from './api/init'
149
-
150
- // Automatically becomes a query for GET operations
151
- const listEndpoint = api.useEndpoint(OperationId.listPets)
152
- // TypeScript knows this has query properties like .data, .isLoading, .refetch()
153
-
154
- // Automatically becomes a mutation for POST operations
155
- const createEndpoint = api.useEndpoint(OperationId.createPet)
156
- // TypeScript knows this has mutation properties like .mutate(), .mutateAsync()
157
-
158
- // Use the endpoints according to their detected type
159
- const petData = listEndpoint.data // Query data
160
- await createEndpoint.mutateAsync({ data: { name: 'Fluffy' } }) // Mutation execution
161
- ```
162
-
163
148
  ### Automatic Cache Management and Refetching
164
149
 
165
150
  By default, mutations automatically:
@@ -170,19 +155,19 @@ By default, mutations automatically:
170
155
 
171
156
  ```typescript
172
157
  // Default behavior: automatic cache management
173
- const createPet = api.useMutation(OperationId.createPet)
158
+ const createPet = api.useMutation(MutationOperationId.createPet)
174
159
  // No additional configuration needed - cache management is automatic
175
160
 
176
161
  // Manual control over cache invalidation
177
- const updatePet = api.useMutation(OperationId.updatePet, {
162
+ const updatePet = api.useMutation(MutationOperationId.updatePet, {
178
163
  dontInvalidate: true, // Disable automatic invalidation
179
164
  dontUpdateCache: true, // Disable automatic cache updates
180
- invalidateOperations: [OperationId.listPets], // Manually specify operations to invalidate
165
+ invalidateOperations: [QueryOperationId.listPets], // Manually specify operations to invalidate
181
166
  })
182
167
 
183
168
  // Refetch specific endpoints after mutation
184
- const petListQuery = api.useQuery(OperationId.listPets)
185
- const createPetWithRefetch = api.useMutation(OperationId.createPet, {
169
+ const petListQuery = api.useQuery(QueryOperationId.listPets)
170
+ const createPetWithRefetch = api.useMutation(MutationOperationId.createPet, {
186
171
  refetchEndpoints: [petListQuery], // Manually refetch these endpoints
187
172
  })
188
173
  ```
@@ -197,7 +182,7 @@ async function uploadPetPicture(petId: string, file: File) {
197
182
  const formData = new FormData()
198
183
  formData.append('file', file)
199
184
 
200
- const uploadMutation = api.useMutation(OperationId.uploadPetPic, { petId })
185
+ const uploadMutation = api.useMutation(MutationOperationId.uploadPetPic, { petId })
201
186
 
202
187
  return uploadMutation.mutateAsync({
203
188
  data: formData,
@@ -211,7 +196,7 @@ async function uploadPetPicture(petId: string, file: File) {
211
196
 
212
197
  // Alternative: using the object structure (if your API supports binary strings)
213
198
  async function uploadPetPictureAsString(petId: string, binaryData: string) {
214
- const uploadMutation = api.useMutation(OperationId.uploadPetPic, { petId })
199
+ const uploadMutation = api.useMutation(MutationOperationId.uploadPetPic, { petId })
215
200
 
216
201
  return uploadMutation.mutateAsync({
217
202
  data: {
@@ -230,10 +215,10 @@ async function handleFileUpload(event: Event, petId: string) {
230
215
  formData.append('file', file)
231
216
 
232
217
  const uploadMutation = api.useMutation(
233
- OperationId.uploadPetPic,
218
+ MutationOperationId.uploadPetPic,
234
219
  { petId },
235
220
  {
236
- invalidateOperations: [OperationId.getPet, OperationId.listPets],
221
+ invalidateOperations: [QueryOperationId.getPet, QueryOperationId.listPets],
237
222
  onSuccess: (data) => {
238
223
  console.log('Upload successful:', data)
239
224
  },
@@ -253,17 +238,17 @@ async function handleFileUpload(event: Event, petId: string) {
253
238
 
254
239
  ### Reactive Enabling/Disabling Based on Path Parameters
255
240
 
256
- One powerful feature is chaining queries where one query provides the parameters for another:
241
+ You can chain queries where one query provides the parameters for another:
257
242
 
258
243
  ```typescript
259
244
  import { ref, computed } from 'vue'
260
245
 
261
246
  // First query to get user information
262
- const userQuery = api.useQuery(OperationId.getUser, { userId: 123 })
247
+ const userQuery = api.useQuery(QueryOperationId.getUser, { userId: 123 })
263
248
 
264
249
  // Second query that depends on the first query's result
265
250
  const userPetsQuery = api.useQuery(
266
- OperationId.listUserPets,
251
+ QueryOperationId.listUserPets,
267
252
  computed(() => ({
268
253
  userId: userQuery.data.value?.id, // Chain: use ID from first query
269
254
  })),
@@ -274,7 +259,7 @@ const selectedPetId = ref<string | undefined>(undefined)
274
259
 
275
260
  // Query automatically enables/disables based on parameter availability
276
261
  const petQuery = api.useQuery(
277
- OperationId.getPet,
262
+ QueryOperationId.getPet,
278
263
  computed(() => ({ petId: selectedPetId.value })),
279
264
  )
280
265
 
@@ -290,7 +275,7 @@ const userId = ref<string>('user1')
290
275
  const shouldFetchPets = ref(true)
291
276
 
292
277
  const userPetsQuery = api.useQuery(
293
- OperationId.listUserPets,
278
+ QueryOperationId.listUserPets,
294
279
  computed(() => ({ userId: userId.value })),
295
280
  {
296
281
  enabled: computed(
@@ -307,7 +292,7 @@ import { ref } from 'vue'
307
292
 
308
293
  // Use reactive query parameters
309
294
  const limit = ref(10)
310
- const petsQuery = api.useQuery(OperationId.listPets, {
295
+ const petsQuery = api.useQuery(QueryOperationId.listPets, {
311
296
  queryParams: { limit: limit.value },
312
297
  })
313
298