Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A lightweight fetching library packed with essential features - retries, interceptors, request deduplication and much more, all while still retaining a similar API surface with regular Fetch.

License

Notifications You must be signed in to change notification settings

zayne-labs/callapi

Repository files navigation

CallApi

CallApi Logo

npm version license downloads per month commit activity Ask DeepWiki Code2Tutorial

An advanced fetch library that actually solves real problems.

Documentation · Getting Started · Plugins


Why CallApi?

Fetch is too basic for real apps. You end up writing the same boilerplate: error handling, retries, deduplication, response parsing etc. CallApi handles all of that and practically more.

Drop-in replacement for fetch. Under 6KB. All kinds of convenience features. Zero dependencies.

import { callApi } from "@zayne-labs/callapi";
const { data, error } = await callApi("/api/users");

Features

Request Deduplication

User spam-clicks a button? Handled. No race conditions.

const req1 = callApi("/api/user");
const req2 = callApi("/api/user"); // Cancels req1 (can be configured to share it's response instead)

Smart Response Parsing

Looks at Content-Type and parses accordingly.

const { data } = await callApi("/api/data"); // JSON? Parsed.

Error Handling

Structured errors make robust error handling trivial.

const { data, error } = await callApi("/api/users");
if (error) {
	console.log(error.name); // "HTTPError", "ValidationError"
	console.log(error.errorData); // Actual API response
}

Retries

Supports exponential backoff and custom retry conditions.

await callApi("/api/data", {
	retryAttempts: 3,
	retryStrategy: "exponential",
	retryStatusCodes: [429, 500, 502, 503],
});

Schema Validation

TypeScript-first types with runtime validation.

import { createFetchClient } from "@zayne-labs/callapi";
import { defineSchema } from "@zayne-labs/callapi/utils";
import { z } from "zod";
const callMainApi = createFetchClient({
	schema: defineSchema({
		"/users/:id": {
			data: z.object({
				id: z.number(),
				name: z.string(),
			}),
		},
	}),
});
// Fully typed + validated
const user = await callMainApi("/users/:id", {
	params: { id: 123 },
});

Hooks

Hook into CallApi's lifecycle at any point.

const api = createFetchClient({
	onRequest: ({ request }) => {
		request.headers.set("Authorization", `Bearer ${token}`);
	},
	onError: ({ error }) => {
		Sentry.captureException(error);
	},
	onResponseStream: ({ event }) => {
		console.log(`Downloaded ${event.progress}%`);
	},
});

Plugins

Extend functionality with setup, hooks, and middleware.

const metricsPlugin = definePlugin({
	id: "metrics",
	name: "Metrics Plugin",
	setup: ({ options }) => ({
		options: {
			...options,
			meta: { startTime: Date.now() },
		},
	}),
	hooks: {
		onSuccess: ({ options }) => {
			const duration = Date.now() - options.meta.startTime;
			console.info(`Request took ${duration}ms`);
		},
	},
	middlewares: {
		fetchMiddleware: (ctx) => async (input, init) => {
			console.info("→", input);
			const response = await ctx.fetchImpl(input, init);
			console.info("←", response.status);
			return response;
		},
	},
});
const api = createFetchClient({
	plugins: [metricsPlugin],
});

URL Helpers

Dynamic params, query strings, and method prefixes.

await callApi("/users/:id", { params: { id: 123 } });
await callApi("/search", { query: { q: "test" } });
await callApi("@delete/users/123");

And so many more

See the full documentation for the full list of features.

Installation

npm install @zayne-labs/callapi
import { callApi, createFetchClient } from "@zayne-labs/callapi";
// Simple
const { data } = await callApi("/api/users");
// Configured
const api = createFetchClient({
	baseURL: "https://api.example.com",
	retryAttempts: 2,
	timeout: 10000,
	onError: ({ error }) => trackError(error),
});

CDN

<script type="module">
	import { callApi } from "https://esm.run/@zayne-labs/callapi";
</script>

What makes it worth considering?

  • TypeScript-first - Full inference everywhere
  • Familiar API - If you know fetch, you know CallApi
  • Actually small - Zero dependencies and Under 6KB, unlike other 50kb libs in the wild
  • Fast - Built on native Web APIs
  • Works everywhere - Browsers, Node 18+, Deno, Bun, Cloudflare Workers

License

MIT © Ryan Zayne

About

A lightweight fetching library packed with essential features - retries, interceptors, request deduplication and much more, all while still retaining a similar API surface with regular Fetch.

Topics

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Sponsor this project

Contributors 10

Languages

AltStyle によって変換されたページ (->オリジナル) /