@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 +33 -48
- package/dist/cli.js +741 -26
- package/dist/index.d.ts +16 -191
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +34 -122
- 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 +40 -53
- 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 +414 -197
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +36 -0
- package/package.json +2 -2
- 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/README.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
[](https://github.com/qualisero/openapi-endpoint/actions/workflows/ci.yml)
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
6
|
[](https://bundlephobia.com/package/@qualisero/openapi-endpoint)
|
|
7
|
+
[](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(
|
|
16
|
+
const { data, isLoading } = api.useQuery(QueryOperationId.getPet, { petId: '123' })
|
|
16
17
|
|
|
17
|
-
const createPetMutation = api.useMutation(
|
|
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 {
|
|
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,
|
|
81
|
+
import { api, QueryOperationId, MutationOperationId } from './api/init'
|
|
76
82
|
|
|
77
83
|
// Use queries for GET operations
|
|
78
|
-
const { data: pets, isLoading } = api.useQuery(
|
|
79
|
-
const { data: pet } = api.useQuery(
|
|
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(
|
|
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,
|
|
104
|
+
import { api, QueryOperationId } from './api/init'
|
|
99
105
|
|
|
100
106
|
// Static query parameters
|
|
101
|
-
const { data: pets } = api.useQuery(
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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(
|
|
162
|
+
const updatePet = api.useMutation(MutationOperationId.updatePet, {
|
|
178
163
|
dontInvalidate: true, // Disable automatic invalidation
|
|
179
164
|
dontUpdateCache: true, // Disable automatic cache updates
|
|
180
|
-
invalidateOperations: [
|
|
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(
|
|
185
|
-
const createPetWithRefetch = api.useMutation(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
218
|
+
MutationOperationId.uploadPetPic,
|
|
234
219
|
{ petId },
|
|
235
220
|
{
|
|
236
|
-
invalidateOperations: [
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
295
|
+
const petsQuery = api.useQuery(QueryOperationId.listPets, {
|
|
311
296
|
queryParams: { limit: limit.value },
|
|
312
297
|
})
|
|
313
298
|
|