More Examples
Vue
Use typed Axios OpenAPI clients in Vue 3 and Nuxt with composables and Result handling.
Vue composables are a natural fit for api.op: one function owns the request, the component owns the template. Types still come from api.contracts.ts.
Vite/Nuxt: env_accessor = "import.meta.env", base_url_env = "VITE_API_URL" (or NUXT_PUBLIC_API_URL if you mirror it).
Composable
import { ref } from "vue";
import { api } from "@/services/api/api.client";
import type { UserDto } from "@/services/api/_generated/api.contracts";
import type { ApiError } from "@/services/api/api.error";
export function useUsers() {
const users = ref<UserDto[] | null>(null);
const error = ref<ApiError | null>(null);
const loading = ref(false);
async function load() {
loading.value = true;
error.value = null;
const result = await api.op.listUsers();
loading.value = false;
if (result.error) {
error.value = result.error;
users.value = null;
return;
}
users.value = result.data;
}
return { users, error, loading, load };
}<script setup lang="ts">
import { onMounted } from "vue";
import { useUsers } from "@/composables/useUsers";
const { users, error, loading, load } = useUsers();
onMounted(load);
</script>
<template>
<p v-if="loading">Loading…</p>
<p v-else-if="error" role="alert">{{ error.message }}</p>
<ul v-else>
<li v-for="user in users" :key="user.id">{{ user.email }}</li>
</ul>
</template>One-shot get
import { ref, watchEffect } from "vue";
import { api } from "@/services/api/api.client";
import type { UserDto } from "@/services/api/_generated/api.contracts";
import type { ApiError } from "@/services/api/api.error";
export function useUser(id: () => string) {
const user = ref<UserDto | null>(null);
const error = ref<ApiError | null>(null);
const loading = ref(false);
watchEffect(async () => {
const currentId = id();
if (!currentId) return;
loading.value = true;
const result = await api.op.getUser({ id: currentId });
loading.value = false;
if (result.error) {
error.value = result.error;
user.value = null;
return;
}
error.value = null;
user.value = result.data;
});
return { user, error, loading };
}Nuxt note
Run generation in Node (api:fetch) at build/dev time. Import the client only from client-safe paths if your auth interceptor touches localStorage — or use auth_mode = "custom" with a cookie/token strategy that works on the server.