zodios

Typescript API client with autocompletion and zod validations

Usage no npm install needed!

<script type="module">
  import zodios from 'https://cdn.skypack.dev/zodios';
</script>

README

Zodios

Zodios logo

Zodios is a typescript api client with auto-completion features backed by axios and zod

langue typescript npm GitHub GitHub Workflow Status

What is it ?

It's an axios compatible API client, with the following features:

  • really simple centralized API declaration
  • typescript autocompletion in your favorite IDE for URL and parameters
  • typescript response types
  • parameters and responses schema thanks to zod
  • response schema validation
  • bearer token injection and token renewal with simple token provider interface
  • all axios features available

Install

> npm install zodios

or

> yarn add zodios

Usage

For an almost complete example on how to use zodios and how to split your APIs declarations, take a look at dev.to example.

Declare your API with zodios

import { Zodios } from "zodios";
import { z } from "zod";

const apiClient = new Zodios(
  "https://jsonplaceholder.typicode.com",
  // API definition
  [
    {
      method: "get",
      path: "/users/:id", // auto detect :id and ask for it in apiClient get params
      description: "Get a user",
      response: z.object({
        id: z.number(),
        name: z.string(),
      }),
    },
  ] as const,
);
//   typed                     auto-complete path   auto-complete params
//     ▼                               ▼                   ▼
const user = await apiClient.get("/users/:id", { params: { id: 7 } });
console.log(user);
// Output: { id: 7, name: 'Kurtis Weissnat' }

Use token provider plugin

Zodios comes with a plugin to inject and renew your tokens :

  import { pluginToken } from 'zodios/plugins/token';

  apiClient.use(pluginToken({
    getToken: async () => "token"
  }));

Get underlying axios instance

you can get back the underlying axios instance to customize it.

const axiosInstance = apiClient.axios;

Give your own axios instance to zodios

you can instanciate zodios with your own axios intance.

const apiClient = new Zodios(
  "https://jsonplaceholder.typicode.com",
  [ ... ] as const,
  // Optional Axios instance
  {
    axiosIntance: customAxiosInstance
  }
);

Disable zodios response validation

const apiClient = new Zodios(
  "https://jsonplaceholder.typicode.com",
  [ ... ] as const,
  // Disable validation
  {
    validateResponse: false
  }
);

React helpers

Zodios comes with a React Provider to register all your api clients and a hook to use them.
The hook is a thin wrapper around react-query useQuery, so you need to also add a react-query provider.

import { QueryClient, QueryClientProvider } from 'react-query';
import { Paths, Zodios, ZodiosRequestOptions } from "zodios";
import { useZodios, ZodiosProvider } from "zodios/react";
import { z } from "zod";

const userSchema = z
  .object({
    id: z.number(),
    name: z.string(),
  });
const usersSchema = z.array(userSchema);

type User = z.infer<typeof userSchema>;
type Users = z.infer<typeof usersSchema>;

const api = [
  {
    method: "get",
    path: "/users",
    description: "Get all users",
    response: usersSchema,
  }
] as const;
const baseUrl = "https://jsonplaceholder.typicode.com";

type Api = typeof api;

function useJsonPlaceholder<Path extends Paths<Api, "get">>(path: Path, config?: ZodiosRequestOptions<Api, "get", Path>) {
  return useZodios(baseUrl, path, config);
}

const Users = () => {
  const { data: users, isLoading, error } = useJsonPlaceholder("/users");

  return (
    <div>
      <h1>Users</h1>
      {isLoading && <div>Loading...</div>}
      {error && <div>Error: {(error as Error).message}</div>}
      {users && (
        <ul>
          {users.map((user) => (
            <li key={user.id}>{user.name}</li>
          ))}
        </ul>
      )}
    </div>
  );
};

const apiClient = new Zodios(baseUrl, api);
const queryClient = new QueryClient();

export const App = () => {
  return (
    <QueryClientProvider client={queryClient}>
      <ZodiosProvider apis={[apiClient]}>
        <Users />
      </ZodiosProvider>
    </QueryClientProvider>
  );
};