Extensible and tiny HTTP client, that gives you unlimited control over you requests
- 🌐 Global options: The client object allows you to set global request options, headers, and a baseURL for all requests.
- 💡 Middlewares: Gain full control over requests and responses using middlewares.
- 💪 Custom client properties: Extend the client with your own custom properties. Add additional functionality or data to enhance the client's capabilities.
- 🔍 Custom response methods: Extend the response object with custom functions.
- 🔌 Powerful plugin system: Benefit from a robust plugin system that offers a wide range of out-of-the-box plugins.
- ✨ Fully type safe: Typescript first package. I fight with typescript, so you dont need to.
This package works with various JavaScript runtimes, utilizing the Fetch API available in most modern environments. It supports web browsers, Node.js (v17.5 and above), and older Node.js versions when using a package like node-fetch. It is also compatible with Deno, Bun, and other runtimes supporting the Fetch API.
npm i yumi-fetch
<script type="module">
import { yumi } from "https://unpkg.com/yumi-fetch/dist/mod.js";
</script>
import { yumi } from "https://deno.land/x/yumi/mod.ts";
import { yumi } from "yumi-fetch";
const client = yumi.withBaseURL("https://dummyjson.com/");
type Todo = {
id: number;
todo: string;
completed: boolean;
userId: number;
};
type Todos = {
todos: Todo[];
total: number;
skip: number;
limit: number;
};
const { todos } = await client
.get("/todos", { query: { limit: 2 } })
.json<Todos>();
console.log(todos);
const createdTodo = await client
.post("/todos/add", {
json: {
todo: "Star Yumi-Fetch repository",
completed: false,
userId: 5,
},
})
.json<Todo>();
console.log(createdTodo);
Here you can find a straightforward API that is similar to the fetch
function but with several notable improvements. You may be familiar with these features from libraries like axios
, etc.. Firstly, it includes functions named after HTTP methods, such as .post()
and .get()
, which make it more intuitive and convenient to perform these actions. Additionally, the API provides simplified serialization capabilities and includes a .json()
resolver for easy handling of JSON data.
For comparison, here's a code snippet using the plain fetch function
type Todo = {
id: number;
todo: string;
completed: boolean;
userId: number;
};
type Todos = {
todos: Todo[];
total: number;
skip: number;
limit: number;
};
const res = await fetch("https://dummyjson.com/todos?limit=2",
{
headers: { "Accept": "application/json" }
}
);
if (!res.ok) throw new Error(await res.text());
const { todos } = (await res.json()) as Todos;
console.log(todos);
const res2 = await fetch("https://dummyjson.com/todos/add",
{
method: "POST",
headers: {
"Accept": "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
todo: "Star Yumi-Fetch repository",
completed: false,
userId: 5,
})
}
);
if (!res2.ok) throw new Error(await res.text());
const createdTodo = (await res2.json()) as Todo;
console.log(createdTodo);
Imagine a scenario where I told you that all these incredible features can be easily attached to your client as modular plug-ins, allowing you to effortlessly expand its functionality. Well, guess what? It's absolutely true!
The yumi
object we imported is essentially a client that has been enhanced with custom modifications on top of it.
import { clientCore, /* ... */ } from "yumi-fetch";
export const yumi = clientCore
// adds http methods like .get(), .post(), .put() ...
.withProperties(httpMethods())
// adds response resolvers .json(), .text(), .formData() ...
.withResolvers(bodyResolvers())
// adds query serialization
.withPlugin(query())
// adds json serialization
.withPlugin(json());
The beauty of this approach is that all these plug-ins seamlessly modify the client type, making it a breeze to work with TypeScript. By composing these plug-ins together, you can create a powerful and flexible client that meets your specific needs.
Package | Base API | Minified size | Minified and gzipped size |
---|---|---|---|
yumi-fetch | fetch | ||
wretch | fetch | ||
ofetch | fetch | ||
ky | fetch | ||
axios | XMLHttpRequest | ||
got | XMLHttpRequest |
cpu: Apple M1
runtime: deno 1.35.0 (aarch64-apple-darwin)
benchmark time (avg) (min … max) p75 p99 p995
-------------------------------------------------- -----------------------------
fetch 72.39 µs/iter (60.75 µs … 714.62 µs) 72.46 µs 204.96 µs 307.29 µs
wretch 77.1 µs/iter (67.92 µs … 1.02 ms) 76.92 µs 109.83 µs 286.46 µs
yumi-fetch 87.31 µs/iter (75.04 µs … 1.05 ms) 87.08 µs 131.83 µs 277.79 µs
ky 156.34 µs/iter (121.21 µs … 2.28 ms) 151.5 µs 534.71 µs 1.22 ms
ya-fetch 89.77 µs/iter (76.38 µs … 1.75 ms) 88.79 µs 144.62 µs 317.83 µs
ofetch 77.51 µs/iter (68.33 µs … 977.96 µs) 76.5 µs 150.96 µs 197.71 µs
summary
fetch
1.07x faster than wretch
1.07x faster than ofetch
1.21x faster than yumi-fetch
1.24x faster than ya-fetch
2.16x faster than ky