chowbea-axios
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

composables/useUsers.ts
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 };
}
components/UserList.vue
<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

composables/useUser.ts
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.

Next Steps

On this page