tangled
alpha
login
or
join now
mokkenstorm.dev
/
openapi-ts
0
fork
atom
fork of hey-api/openapi-ts because I need some additional things
0
fork
atom
overview
issues
pulls
pipelines
docs: @tanstack/vue-query vue example
Mads Hougesen
2 years ago
4ea48082
8efb1072
+234
-2
4 changed files
expand all
collapse all
unified
split
examples
openapi-ts-tanstack-vue-query
postcss.config.js
src
assets
main.css
views
TanstackExample.vue
tailwind.config.ts
+6
examples/openapi-ts-tanstack-vue-query/postcss.config.js
···
1
1
+
export default {
2
2
+
plugins: {
3
3
+
autoprefixer: {},
4
4
+
tailwindcss: {}
5
5
+
}
6
6
+
}
+4
examples/openapi-ts-tanstack-vue-query/src/assets/main.css
···
1
1
@tailwind base;
2
2
@tailwind components;
3
3
@tailwind utilities;
4
4
+
5
5
+
body {
6
6
+
@apply bg-[#111113];
7
7
+
}
+223
-1
examples/openapi-ts-tanstack-vue-query/src/views/TanstackExample.vue
···
1
1
+
<script lang="ts" setup>
2
2
+
import { $Pet, type Pet } from '@/client'
3
3
+
import {
4
4
+
addPetMutation,
5
5
+
getPetByIdOptions,
6
6
+
updatePetMutation
7
7
+
} from '@/client/@tanstack/vue-query.gen'
8
8
+
import { createClient } from '@hey-api/client-fetch'
9
9
+
import { useMutation, useQuery } from '@tanstack/vue-query'
10
10
+
import { computed, ref, watch } from 'vue'
11
11
+
12
12
+
const localClient = createClient({
13
13
+
// set default base url for requests made by this client
14
14
+
baseUrl: 'https://petstore3.swagger.io/api/v3',
15
15
+
/**
16
16
+
* Set default headers only for requests made by this client. This is to
17
17
+
* demonstrate local clients and their configuration taking precedence over
18
18
+
* internal service client.
19
19
+
*/
20
20
+
headers: {
21
21
+
Authorization: 'Bearer <token_from_local_client>'
22
22
+
}
23
23
+
})
24
24
+
25
25
+
localClient.interceptors.request.use((request, options) => {
26
26
+
// Middleware is great for adding authorization tokens to requests made to
27
27
+
// protected paths. Headers are set randomly here to allow surfacing the
28
28
+
// default headers, too.
29
29
+
if (options.url === '/pet/{petId}' && options.method === 'GET' && Math.random() < 0.5) {
30
30
+
request.headers.set('Authorization', 'Bearer <token_from_interceptor>')
31
31
+
}
32
32
+
return request
33
33
+
})
34
34
+
35
35
+
const pet = ref<Pet>()
36
36
+
const petId = ref<number>()
37
37
+
const isRequiredNameError = ref(false)
38
38
+
39
39
+
const petInput = ref({ name: '', category: '' })
40
40
+
41
41
+
const addPet = useMutation({
42
42
+
...addPetMutation,
43
43
+
onError: (error) => {
44
44
+
console.log(error)
45
45
+
isRequiredNameError.value = false
46
46
+
},
47
47
+
onSuccess: (data) => {
48
48
+
pet.value = data
49
49
+
isRequiredNameError.value = false
50
50
+
}
51
51
+
})
52
52
+
53
53
+
const updatePet = useMutation({
54
54
+
...updatePetMutation,
55
55
+
onError: (error) => {
56
56
+
console.log(error)
57
57
+
},
58
58
+
onSuccess: (data) => {
59
59
+
pet.value = data
60
60
+
}
61
61
+
})
62
62
+
63
63
+
const { data, error } = useQuery(
64
64
+
computed(() => ({
65
65
+
...getPetByIdOptions({
66
66
+
client: localClient,
67
67
+
path: {
68
68
+
petId: petId.value!
69
69
+
}
70
70
+
}),
71
71
+
enabled: Boolean(petId.value)
72
72
+
}))
73
73
+
)
74
74
+
75
75
+
const handleAddPet = async () => {
76
76
+
if ($Pet.required.includes('name') && !petInput.value?.name?.length) {
77
77
+
isRequiredNameError.value = true
78
78
+
return
79
79
+
}
80
80
+
81
81
+
addPet.mutate({
82
82
+
body: {
83
83
+
category: {
84
84
+
id: 0,
85
85
+
name: petInput.value.category
86
86
+
},
87
87
+
id: 0,
88
88
+
name: petInput.value?.name,
89
89
+
photoUrls: ['string'],
90
90
+
status: 'available',
91
91
+
tags: [
92
92
+
{
93
93
+
id: 0,
94
94
+
name: 'string'
95
95
+
}
96
96
+
]
97
97
+
}
98
98
+
})
99
99
+
}
100
100
+
101
101
+
function setRandomPetId() {
102
102
+
// random id 1-10
103
103
+
petId.value = Math.floor(Math.random() * (10 - 1 + 1) + 1)
104
104
+
}
105
105
+
106
106
+
const handleUpdatePet = async () => {
107
107
+
updatePet.mutate({
108
108
+
body: {
109
109
+
category: {
110
110
+
id: pet.value?.category?.id ?? 0,
111
111
+
name: petInput.value.category
112
112
+
},
113
113
+
id: pet.value?.id ?? 0,
114
114
+
name: petInput.value.name,
115
115
+
photoUrls: ['string'],
116
116
+
status: 'available',
117
117
+
tags: [
118
118
+
{
119
119
+
id: 0,
120
120
+
name: 'string'
121
121
+
}
122
122
+
]
123
123
+
},
124
124
+
// setting headers per request
125
125
+
headers: {
126
126
+
Authorization: 'Bearer <token_from_method>'
127
127
+
}
128
128
+
})
129
129
+
}
130
130
+
131
131
+
watch(data, () => {
132
132
+
pet.value = data.value
133
133
+
})
134
134
+
135
135
+
watch(error, (error) => {
136
136
+
console.log(error)
137
137
+
})
138
138
+
</script>
139
139
+
1
140
<template>
2
2
-
<div></div>
141
141
+
<div class="bg-[#18191b] py-12">
142
142
+
<div class="flex flex-col gap-12 max-w-md mx-auto">
143
143
+
<div class="flex items-center">
144
144
+
<a className="shrink-0" href="https://heyapi.vercel.app/" target="_blank">
145
145
+
<img
146
146
+
src="https://heyapi.vercel.app/logo.png"
147
147
+
class="h-16 w-16 transition duration-300 will-change-auto"
148
148
+
alt="Hey API logo"
149
149
+
/>
150
150
+
</a>
151
151
+
152
152
+
<h1 class="text-2xl font-bold text-white">@hey-api/openapi-ts 🤝 TanStack Vue Query</h1>
153
153
+
</div>
154
154
+
155
155
+
<div class="flex flex-col gap-2">
156
156
+
<div
157
157
+
class="p-2 bg-[#1f2123] border-[#575e64] rounded border flex gap-3 w-[50%] items-center"
158
158
+
>
159
159
+
<div
160
160
+
class="rounded-full bg-[#233057] flex size-[40px] text-[#9eb1ff] text-lg font-medium place-content-center place-items-center"
161
161
+
>
162
162
+
<span>
163
163
+
{{ pet?.name?.slice(0, 1) || 'N' }}
164
164
+
</span>
165
165
+
</div>
166
166
+
167
167
+
<div>
168
168
+
<p class="text-white text-sm font-bold">Name: {{ pet?.name || 'N/A' }}</p>
169
169
+
170
170
+
<p class="text-[#f1f7feb5] text-sm">Category: {{ pet?.category?.name || 'N/A' }}</p>
171
171
+
</div>
172
172
+
</div>
173
173
+
174
174
+
<button
175
175
+
type="button"
176
176
+
class="text-white p-1 font-medium text-sm rounded bg-[#3e63dd]"
177
177
+
@click="setRandomPetId"
178
178
+
>
179
179
+
Get Random Pet
180
180
+
</button>
181
181
+
</div>
182
182
+
183
183
+
<form @submit.prevent="handleAddPet" class="flex flex-col gap-3">
184
184
+
<div class="flex flex-col gap-1 w-64">
185
185
+
<label for="name" class="text-white font-medium">Name</label>
186
186
+
187
187
+
<input
188
188
+
v-model="petInput.name"
189
189
+
name="name"
190
190
+
required
191
191
+
class="border rounded bg-[#121314] text-sm p-1 border-[#575e64] placeholder:text-[#575e64] text-white"
192
192
+
placeholder="Kitty"
193
193
+
/>
194
194
+
</div>
195
195
+
196
196
+
<div class="flex flex-col gap-1 w-64">
197
197
+
<label for="category" class="text-white font-medium">Category</label>
198
198
+
199
199
+
<input
200
200
+
v-model="petInput.category"
201
201
+
name="category"
202
202
+
required
203
203
+
class="border rounded bg-[#121314] text-sm p-1 border-[#575e64] placeholder:text-[#575e64] text-white"
204
204
+
placeholder="Cats"
205
205
+
/>
206
206
+
</div>
207
207
+
208
208
+
<div class="flex gap-2">
209
209
+
<button type="submit" class="text-white p-2 font-medium text-sm rounded bg-[#3e63dd]">
210
210
+
Add Pet
211
211
+
</button>
212
212
+
213
213
+
<button
214
214
+
type="button"
215
215
+
class="cursor- text-white p-2 font-medium text-sm rounded bg-[#3e63dd] disabled:cursor-not-allowed"
216
216
+
@click="handleUpdatePet"
217
217
+
:disabled="!pet"
218
218
+
>
219
219
+
Update Pet
220
220
+
</button>
221
221
+
</div>
222
222
+
</form>
223
223
+
</div>
224
224
+
</div>
3
225
</template>
+1
-1
examples/openapi-ts-tanstack-vue-query/tailwind.config.ts
···
1
1
import type { Config } from 'tailwindcss'
2
2
3
3
export default {
4
4
-
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx,vue}'],
4
4
+
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
5
5
plugins: [],
6
6
theme: {
7
7
extend: {}