Skip to content

Instantly share code, notes, and snippets.

@jordienr
Created January 15, 2024 12:48
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jordienr/3127f4186d520e57d3e77fa784058366 to your computer and use it in GitHub Desktop.
Save jordienr/3127f4186d520e57d3e77fa784058366 to your computer and use it in GitHub Desktop.
Fully typed API client with zod and fetch
import { z } from "zod";
const Post = z.object({
id: z.string(),
slug: z.string(),
content: z.string(),
title: z.string()
})
export function createAPIClient() {
async function _fetch<T extends z.ZodTypeAny>(
input: RequestInfo,
init: RequestInit,
type: T
): Promise<z.infer<T>> {
const headers = new Headers(init?.headers);
const res = await fetch(input, { ...init, headers });
if (!res.ok) {
throw new Error(res.statusText);
}
const data = await res.json();
const result = await type.safeParseAsync(data);
if (!result.success) {
throw new Error(result.error.message);
}
return result.data;
}
async function getPostsForBlog(blogSlug: string) {
const res = await _fetch(
`/api/blogs/${blogSlug}/posts`,
{ method: "GET" },
z.array(ClientPost)
);
return res;
}
return {
posts: {
get: (slug: string) => _fetch(`/api/posts/${slug}`, { method: "GET" }, Post),
getAll: _fetch('/api/posts', { method: 'GET' }, z.array(Post))
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment