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