fork of hey-api/openapi-ts because I need some additional things
1<script setup lang="ts">
2import { ref } from 'vue';
3
4import { createClient } from './client/client';
5import { PetSchema } from './client/schemas.gen';
6import { addPet, getPetById, updatePet } from './client/sdk.gen';
7import type { Pet } from './client/types.gen';
8
9const pet = ref<Pet | undefined>();
10const petInput = ref({ name: '', category: '' });
11const isPetNameRequired = PetSchema.required.includes('name');
12
13const localClient = createClient({
14 baseUrl: 'https://petstore3.swagger.io/api/v3',
15 headers: {
16 Authorization: 'Bearer <token_from_local_client>',
17 },
18});
19
20localClient.interceptors.request.use((request, options) => {
21 if (
22 options.url === '/pet/{petId}' &&
23 options.method === 'GET' &&
24 Math.random() < 0.5
25 ) {
26 request.headers.set('Authorization', 'Bearer <token_from_interceptor>');
27 }
28 return request;
29});
30
31localClient.interceptors.error.use((error) => {
32 console.error(error);
33 return error;
34});
35
36function randomInt(min: number, max: number) {
37 return Math.floor(Math.random() * (max - min + 1) + min);
38}
39
40async function setRandomPetId() {
41 const id = randomInt(1, 10);
42 const { data, error } = await getPetById({
43 client: localClient,
44 path: { petId: id },
45 });
46 if (error) {
47 console.error(error);
48 return;
49 }
50 pet.value = data!;
51}
52
53function buildPetBody(base?: Partial<Pet>) {
54 return {
55 category: {
56 id: base?.category?.id ?? 0,
57 name: petInput.value.category,
58 },
59 id: base?.id ?? 0,
60 name: petInput.value.name,
61 photoUrls: ['string'],
62 status: 'available' as const,
63 tags: [
64 {
65 id: 0,
66 name: 'string',
67 },
68 ],
69 };
70}
71
72async function handleAddPet() {
73 if (isPetNameRequired && !petInput.value.name) return;
74 const { data, error } = await addPet({ body: buildPetBody() });
75 if (error) {
76 console.error(error);
77 return;
78 }
79 pet.value = data!;
80}
81
82async function handleUpdatePet() {
83 if (!pet.value) return;
84 const { data, error } = await updatePet({
85 body: buildPetBody(pet.value),
86 headers: { Authorization: 'Bearer <token_from_method>' },
87 });
88 if (error) {
89 console.error(error);
90 return;
91 }
92 pet.value = data!;
93}
94</script>
95
96<template>
97 <div class="bg-[#18191b] py-12">
98 <div class="mx-auto flex max-w-md flex-col gap-12">
99 <div class="flex items-center">
100 <a class="shrink-0" href="https://heyapi.dev/" target="_blank">
101 <img
102 alt="Hey API logo"
103 class="size-16 transition duration-300 will-change-auto"
104 src="https://heyapi.dev/assets/raw/logo.png"
105 />
106 </a>
107
108 <h1 class="text-2xl font-bold text-white">
109 @hey-api/openapi-ts 🤝 ofetch
110 </h1>
111 </div>
112
113 <div class="flex flex-col gap-2">
114 <div
115 class="flex max-w-60 items-center gap-3 rounded border border-[#575e64] bg-[#1f2123] p-4"
116 >
117 <div
118 class="flex size-10 place-content-center place-items-center rounded-full bg-[#233057] text-lg font-medium text-[#9eb1ff]"
119 >
120 <span>
121 {{ pet?.name?.slice(0, 1) || 'N' }}
122 </span>
123 </div>
124
125 <div>
126 <p class="text-sm font-bold text-white">
127 Name: {{ pet?.name || 'N/A' }}
128 </p>
129
130 <p class="text-sm text-[#f1f7feb5]">
131 Category: {{ pet?.category?.name || 'N/A' }}
132 </p>
133 </div>
134 </div>
135
136 <button
137 class="rounded bg-[#3e63dd] p-1 text-sm font-medium text-white"
138 type="button"
139 @click="setRandomPetId"
140 >
141 Get Random Pet
142 </button>
143 </div>
144
145 <form class="flex flex-col gap-3" @submit.prevent="handleAddPet">
146 <div class="flex w-64 flex-col gap-1">
147 <label class="font-medium text-white" for="name">Name</label>
148
149 <input
150 v-model="petInput.name"
151 class="rounded border border-[#575e64] bg-[#121314] p-1 text-sm text-white placeholder:text-[#575e64]"
152 name="name"
153 placeholder="Kitty"
154 :required="isPetNameRequired"
155 />
156 </div>
157
158 <div class="flex w-64 flex-col gap-1">
159 <label class="font-medium text-white" for="category">Category</label>
160
161 <input
162 v-model="petInput.category"
163 class="rounded border border-[#575e64] bg-[#121314] p-1 text-sm text-white placeholder:text-[#575e64]"
164 name="category"
165 placeholder="Cats"
166 required
167 />
168 </div>
169
170 <div class="flex gap-2">
171 <button
172 class="rounded bg-[#3e63dd] p-2 text-sm font-medium text-white"
173 type="submit"
174 >
175 Add Pet
176 </button>
177
178 <button
179 class="rounded bg-[#3e63dd] p-2 text-sm font-medium text-white disabled:cursor-not-allowed"
180 :disabled="!pet"
181 type="button"
182 @click="handleUpdatePet"
183 >
184 Update Pet
185 </button>
186 </div>
187 </form>
188 </div>
189 </div>
190</template>